Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | // Copyright 2019-2022 Cambridge Quantum Computing | |||
2 | // | |||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | |||
4 | // you may not use this file except in compliance with the License. | |||
5 | // You may obtain a copy of the License at | |||
6 | // | |||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | |||
8 | // | |||
9 | // Unless required by applicable law or agreed to in writing, software | |||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | |||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
12 | // See the License for the specific language governing permissions and | |||
13 | // limitations under the License. | |||
14 | ||||
15 | #include "Gate.hpp" | |||
16 | ||||
17 | #include <algorithm> | |||
18 | #include <stdexcept> | |||
19 | #include <tkrng/RNG.hpp> | |||
20 | #include <vector> | |||
21 | ||||
22 | #include "GateUnitaryMatrix.hpp" | |||
23 | #include "GateUnitaryMatrixError.hpp" | |||
24 | #include "OpPtrFunctions.hpp" | |||
25 | #include "OpType/OpType.hpp" | |||
26 | #include "OpType/OpTypeFunctions.hpp" | |||
27 | #include "OpType/OpTypeInfo.hpp" | |||
28 | #include "Ops/Op.hpp" | |||
29 | #include "Utils/Expression.hpp" | |||
30 | #include "Utils/PauliStrings.hpp" | |||
31 | #include "symengine/eval_double.h" | |||
32 | ||||
33 | namespace tket { | |||
34 | using std::stringstream; | |||
35 | ||||
36 | 337071 | Op_ptr Gate::dagger() const { | ||
37 | 337071 | OpType optype = get_type(); | ||
38 |
18/26✓ Branch 0 taken 12028 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1051 times.
✓ Branch 3 taken 1402 times.
✓ Branch 4 taken 1323 times.
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 1854 times.
✓ Branch 7 taken 3050 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 326 times.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 312402 times.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 122 times.
✓ Branch 20 taken 138 times.
✓ Branch 21 taken 2956 times.
✓ Branch 22 taken 30 times.
✓ Branch 23 taken 361 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
|
337071 | switch (optype) { | |
39 | 12028 | case OpType::H: | ||
40 | case OpType::X: | |||
41 | case OpType::Y: | |||
42 | case OpType::Z: | |||
43 | case OpType::SWAP: | |||
44 | case OpType::CH: | |||
45 | case OpType::CX: | |||
46 | case OpType::CY: | |||
47 | case OpType::CZ: | |||
48 | case OpType::CCX: | |||
49 | case OpType::noop: | |||
50 | case OpType::CSWAP: | |||
51 | case OpType::ECR: | |||
52 | case OpType::BRIDGE: { | |||
53 |
1/2✓ Branch 2 taken 12028 times.
✗ Branch 3 not taken.
|
12028 | return get_op_ptr(optype); | |
54 | } | |||
55 | ✗ | case OpType::CnX: | ||
56 | case OpType::CnZ: | |||
57 | case OpType::CnY: { | |||
58 | ✗ | return get_op_ptr(optype, std::vector<Expr>(), n_qubits_); | ||
59 | } | |||
60 |
1/1✓ Decision 'true' taken 1051 times.
|
1051 | case OpType::S: { | |
61 |
1/2✓ Branch 2 taken 1051 times.
✗ Branch 3 not taken.
|
1051 | return get_op_ptr(OpType::Sdg); | |
62 | } | |||
63 |
1/1✓ Decision 'true' taken 1402 times.
|
1402 | case OpType::Sdg: { | |
64 |
1/2✓ Branch 2 taken 1402 times.
✗ Branch 3 not taken.
|
1402 | return get_op_ptr(OpType::S); | |
65 | } | |||
66 |
1/1✓ Decision 'true' taken 1323 times.
|
1323 | case OpType::T: { | |
67 |
1/2✓ Branch 2 taken 1323 times.
✗ Branch 3 not taken.
|
1323 | return get_op_ptr(OpType::Tdg); | |
68 | } | |||
69 |
1/1✓ Decision 'true' taken 22 times.
|
22 | case OpType::Tdg: { | |
70 |
1/2✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
|
22 | return get_op_ptr(OpType::T); | |
71 | } | |||
72 |
1/1✓ Decision 'true' taken 1854 times.
|
1854 | case OpType::V: { | |
73 |
1/2✓ Branch 2 taken 1854 times.
✗ Branch 3 not taken.
|
1854 | return get_op_ptr(OpType::Vdg); | |
74 | } | |||
75 |
1/1✓ Decision 'true' taken 3050 times.
|
3050 | case OpType::Vdg: { | |
76 |
1/2✓ Branch 2 taken 3050 times.
✗ Branch 3 not taken.
|
3050 | return get_op_ptr(OpType::V); | |
77 | } | |||
78 |
1/1✓ Decision 'true' taken 1 times.
|
1 | case OpType::CV: { | |
79 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | return get_op_ptr(OpType::CVdg); | |
80 | } | |||
81 |
1/1✓ Decision 'true' taken 1 times.
|
1 | case OpType::CVdg: { | |
82 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | return get_op_ptr(OpType::CV); | |
83 | } | |||
84 |
1/1✓ Decision 'true' taken 326 times.
|
326 | case OpType::SX: { | |
85 |
1/2✓ Branch 2 taken 326 times.
✗ Branch 3 not taken.
|
326 | return get_op_ptr(OpType::SXdg); | |
86 | } | |||
87 |
1/1✓ Decision 'true' taken 3 times.
|
3 | case OpType::SXdg: { | |
88 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | return get_op_ptr(OpType::SX); | |
89 | } | |||
90 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::CSX: { | |
91 | ✗ | return get_op_ptr(OpType::CSXdg); | ||
92 | } | |||
93 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::CSXdg: { | |
94 | ✗ | return get_op_ptr(OpType::CSX); | ||
95 | } | |||
96 | 312402 | case OpType::Phase: | ||
97 | case OpType::CRz: | |||
98 | case OpType::CRx: | |||
99 | case OpType::CRy: | |||
100 | case OpType::CU1: | |||
101 | case OpType::U1: | |||
102 | case OpType::Rz: | |||
103 | case OpType::Ry: | |||
104 | case OpType::Rx: | |||
105 | case OpType::PhaseGadget: | |||
106 | case OpType::CnRy: | |||
107 | case OpType::XXPhase: | |||
108 | case OpType::YYPhase: | |||
109 | case OpType::ZZPhase: | |||
110 | case OpType::XXPhase3: | |||
111 | case OpType::ISWAP: | |||
112 | case OpType::ESWAP: { | |||
113 |
1/2✓ Branch 3 taken 312402 times.
✗ Branch 4 not taken.
|
624804 | return get_op_ptr(optype, minus_times(params_[0]), n_qubits_); | |
114 | } | |||
115 |
0/1✗ Decision 'true' not taken.
|
1 | case OpType::ZZMax: { | |
116 | // ZZMax.dagger = ZZPhase(-0.5) | |||
117 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | return get_op_ptr(OpType::ZZPhase, -0.5); | |
118 | } | |||
119 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::FSim: { | |
120 | // FSim(a,b).dagger() == FSim(-a,-b) | |||
121 | ✗ | return get_op_ptr( | ||
122 | ✗ | OpType::FSim, {minus_times(params_[0]), minus_times(params_[1])}); | ||
123 | } | |||
124 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::Sycamore: { | |
125 | ✗ | return get_op_ptr(OpType::FSim, {-0.5, -1. / 6.}); | ||
126 | } | |||
127 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::ISWAPMax: { | |
128 | ✗ | return get_op_ptr(OpType::ISWAP, 3.); | ||
129 | } | |||
130 |
0/1✗ Decision 'true' not taken.
|
122 | case OpType::U2: { | |
131 | // U2(a,b).dagger() == U3(-pi/2,-b,-a) | |||
132 | 366 | return get_op_ptr( | ||
133 |
4/8✓ Branch 7 taken 122 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 122 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 366 times.
✓ Branch 15 taken 122 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
488 | OpType::U3, {-0.5, minus_times(params_[1]), minus_times(params_[0])}); | |
134 | } | |||
135 | 138 | case OpType::U3: | ||
136 | case OpType::CU3: | |||
137 | // U3(a,b,c).dagger() == U3(-a,-c.-b) | |||
138 | { | |||
139 | 414 | return get_op_ptr( | ||
140 | 276 | optype, {minus_times(params_[0]), minus_times(params_[2]), | ||
141 |
4/8✓ Branch 6 taken 138 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 138 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 414 times.
✓ Branch 14 taken 138 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
690 | minus_times(params_[1])}); | |
142 | } | |||
143 |
0/1✗ Decision 'true' not taken.
|
2956 | case OpType::TK1: | |
144 | // TK1(a,b,c).dagger() == TK1(-c,-b,-a) | |||
145 | { | |||
146 | 8868 | return get_op_ptr( | ||
147 | 5912 | OpType::TK1, {minus_times(params_[2]), minus_times(params_[1]), | ||
148 |
4/8✓ Branch 6 taken 2956 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2956 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 8868 times.
✓ Branch 14 taken 2956 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
14780 | minus_times(params_[0])}); | |
149 | } | |||
150 |
1/1✓ Decision 'true' taken 90 times.
|
30 | case OpType::TK2: | |
151 | 90 | return get_op_ptr( | ||
152 | 60 | OpType::TK2, {minus_times(params_[0]), minus_times(params_[1]), | ||
153 |
4/8✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 30 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 90 times.
✓ Branch 14 taken 30 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
150 | minus_times(params_[2])}); | |
154 | 361 | case OpType::PhasedX: | ||
155 | case OpType::NPhasedX: | |||
156 | // PhasedX(a,b).dagger() == PhasedX(-a,b) | |||
157 | { | |||
158 | 722 | return get_op_ptr( | ||
159 |
4/8✓ Branch 6 taken 361 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 361 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 722 times.
✓ Branch 14 taken 361 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
1083 | optype, {minus_times(params_[0]), params_[1]}, n_qubits_); | |
160 | } | |||
161 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::PhasedISWAP: | |
162 | // PhasedISWAP(a,b).dagger() == PhasedISWAP(a,-b) | |||
163 | { | |||
164 | ✗ | return get_op_ptr( | ||
165 | ✗ | OpType::PhasedISWAP, {params_[0], minus_times(params_[1])}); | ||
166 | } | |||
167 |
0/1✗ Decision 'true' not taken.
|
✗ | default: { | |
168 | ✗ | throw BadOpType("Cannot compute dagger", optype); | ||
169 | } | |||
170 | } | |||
171 | } | |||
172 | ||||
173 | 243 | Op_ptr Gate::transpose() const { | ||
174 | 243 | OpType optype = get_type(); | ||
175 |
8/10✓ Branch 0 taken 231 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
243 | switch (optype) { | |
176 | 231 | case OpType::Phase: | ||
177 | case OpType::H: | |||
178 | case OpType::X: | |||
179 | case OpType::Z: | |||
180 | case OpType::SWAP: | |||
181 | case OpType::CH: | |||
182 | case OpType::CX: | |||
183 | case OpType::CZ: | |||
184 | case OpType::CV: | |||
185 | case OpType::CVdg: | |||
186 | case OpType::CSX: | |||
187 | case OpType::CSXdg: | |||
188 | case OpType::CCX: | |||
189 | case OpType::noop: | |||
190 | case OpType::CSWAP: | |||
191 | case OpType::BRIDGE: | |||
192 | case OpType::S: | |||
193 | case OpType::Sdg: | |||
194 | case OpType::T: | |||
195 | case OpType::V: | |||
196 | case OpType::Vdg: | |||
197 | case OpType::SX: | |||
198 | case OpType::SXdg: | |||
199 | case OpType::CRz: | |||
200 | case OpType::CRx: | |||
201 | case OpType::CU1: | |||
202 | case OpType::U1: | |||
203 | case OpType::Rz: | |||
204 | case OpType::Rx: | |||
205 | case OpType::PhaseGadget: | |||
206 | case OpType::XXPhase: | |||
207 | case OpType::YYPhase: | |||
208 | case OpType::ZZPhase: | |||
209 | case OpType::TK2: | |||
210 | case OpType::XXPhase3: | |||
211 | case OpType::ESWAP: | |||
212 | case OpType::FSim: { | |||
213 | 231 | return get_op_ptr(optype, params_); | ||
214 | } | |||
215 |
1/1✓ Decision 'true' taken 4 times.
|
1 | case OpType::Y: { | |
216 |
4/8✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 3 times.
✓ Branch 13 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
4 | return get_op_ptr(OpType::U3, {3, 0.5, 0.5}); | |
217 | } | |||
218 | 3 | case OpType::Ry: | ||
219 | case OpType::CRy: | |||
220 | case OpType::CnRy: { | |||
221 |
1/2✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
|
6 | return get_op_ptr(optype, minus_times(params_[0]), n_qubits_); | |
222 | } | |||
223 | 2 | case OpType::CnX: | ||
224 | case OpType::CnZ: { | |||
225 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
4 | return get_op_ptr(optype, std::vector<Expr>(), n_qubits_); | |
226 | } | |||
227 |
0/1✗ Decision 'true' not taken.
|
1 | case OpType::U2: { | |
228 | // U2(a,b).transpose() == U2(b+1,a+1) | |||
229 |
7/14✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 21 taken 2 times.
✓ Branch 22 taken 1 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
3 | return get_op_ptr(OpType::U2, {params_[1] + 1., params_[0] + 1.}); | |
230 | } | |||
231 | 2 | case OpType::U3: | ||
232 | case OpType::CU3: { | |||
233 | // U3(a,b,c).transpose() == U3(-a,c,b) | |||
234 | 6 | return get_op_ptr( | ||
235 |
4/8✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 6 times.
✓ Branch 16 taken 2 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
|
8 | OpType::U3, {minus_times(params_[0]), params_[2], params_[1]}); | |
236 | } | |||
237 |
0/1✗ Decision 'true' not taken.
|
1 | case OpType::TK1: { | |
238 | // TK1(a,b,c).transpose() == TK1(c,b,a) | |||
239 |
4/8✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 1 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
4 | return get_op_ptr(OpType::TK1, {params_[2], params_[1], params_[0]}); | |
240 | } | |||
241 | 2 | case OpType::PhasedX: | ||
242 | case OpType::NPhasedX: { | |||
243 | // PhasedX(a,b).transpose() == PhasedX(a,-b) | |||
244 | 4 | return get_op_ptr( | ||
245 |
4/8✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 4 times.
✓ Branch 14 taken 2 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
6 | optype, {params_[0], minus_times(params_[1])}, n_qubits_); | |
246 | } | |||
247 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::PhasedISWAP: { | |
248 | // PhasedISWAP(a,b).transpose() == PhasedISWAP(-a,b) | |||
249 | ✗ | return get_op_ptr( | ||
250 | ✗ | OpType::PhasedISWAP, {minus_times(params_[0]), params_[1]}); | ||
251 | } | |||
252 | ||||
253 |
0/1✗ Decision 'true' not taken.
|
✗ | default: { | |
254 | ✗ | throw BadOpType("Cannot compute transpose", optype); | ||
255 | } | |||
256 | } | |||
257 | } | |||
258 | ||||
259 | 2376 | static bool params_contain_nan(const std::vector<Expr>& params) { | ||
260 |
4/8✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2375 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
2376 | static const std::regex nan_regex("\\bnan\\b"); | |
261 |
2/2✓ Branch 5 taken 2014 times.
✓ Branch 6 taken 2375 times.
|
2/2✓ Decision 'true' taken 2014 times.
✓ Decision 'false' taken 2375 times.
|
4389 | for (const Expr& e : params) { |
262 |
1/2✓ Branch 1 taken 2014 times.
✗ Branch 2 not taken.
|
2014 | stringstream ss; | |
263 |
1/2✓ Branch 1 taken 2014 times.
✗ Branch 2 not taken.
|
2014 | ss << e; | |
264 |
4/6✓ Branch 1 taken 2014 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2014 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 2013 times.
|
1/2✓ Decision 'true' taken 2014 times.
✗ Decision 'false' not taken.
|
2014 | if (std::regex_search(ss.str(), nan_regex)) return true; |
265 |
2/2✓ Branch 1 taken 2013 times.
✓ Branch 2 taken 1 times.
|
2014 | } | |
266 | 2375 | return false; | ||
267 | } | |||
268 | ||||
269 | 2 | static double random_perturbation() { | ||
270 |
4/8✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
2 | static RNG rng; | |
271 | 2 | int a = rng.get_size_t(10); | ||
272 | 2 | return (a - 5) * EPS; | ||
273 | } | |||
274 | ||||
275 | // If `to_doubles` is true, when an expression contains no free symbols evaluate | |||
276 | // it as a double. This is appropriate in the case where an expression has been | |||
277 | // perturbed, when there is no point retaining exact values for symbolic | |||
278 | // constants. | |||
279 | 2376 | static std::vector<Expr> subs_all_params( | ||
280 | const std::vector<Expr>& params, const SymEngine::map_basic_basic& sub_map, | |||
281 | bool to_doubles = false) { | |||
282 | 2376 | std::vector<Expr> new_params; | ||
283 |
2/2✓ Branch 5 taken 2016 times.
✓ Branch 6 taken 2376 times.
|
2/2✓ Decision 'true' taken 2016 times.
✓ Decision 'false' taken 2376 times.
|
4392 | for (const Expr& p : params) { |
284 |
1/2✓ Branch 1 taken 2016 times.
✗ Branch 2 not taken.
|
2016 | Expr psub = p.subs(sub_map); | |
285 |
8/12✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2013 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 2013 times.
✓ Branch 11 taken 3 times.
✓ Branch 12 taken 2013 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 2013 times.
|
2016 | if (to_doubles && expr_free_symbols(psub).empty()) { |
286 |
4/8✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
|
3 | new_params.push_back(SymEngine::eval_double(psub)); | |
287 | } else { | |||
288 |
1/2✓ Branch 1 taken 2013 times.
✗ Branch 2 not taken.
|
2013 | new_params.push_back(psub); | |
289 | } | |||
290 | 2016 | } | ||
291 | 2376 | return new_params; | ||
292 | } | |||
293 | ||||
294 | 2375 | Op_ptr Gate::symbol_substitution( | ||
295 | const SymEngine::map_basic_basic& sub_map) const { | |||
296 | // Perform symbolic substitution, but catch the case where the returned | |||
297 | // expression is not a number, and in that case try to set a value by | |||
298 | // perturbing the inputs. This deals with cases where expressions contain | |||
299 | // terms that are undefined at specific values but where the singularity is | |||
300 | // removable at the op level. (Non-removable singularities, which ought | |||
301 | // strictly to fail substitution, will result in spectacularly wrong values, | |||
302 | // but are unlikely to arise in practice.) | |||
303 | // | |||
304 | // This is a partial workaround for issues arising from squashing symbolic | |||
305 | // rotations, where it is hard or impossible to handle special cases (e.g. | |||
306 | // where the general formula reduces to one involving atan2(0,0)). | |||
307 | // | |||
308 | // A proper solution to this problem may have to wait for TKET 2. | |||
309 |
1/2✓ Branch 1 taken 2375 times.
✗ Branch 2 not taken.
|
2375 | std::vector<Expr> new_params = subs_all_params(this->params_, sub_map); | |
310 |
3/4✓ Branch 1 taken 2375 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2374 times.
✓ Branch 4 taken 1 times.
|
2/2✓ Decision 'true' taken 2374 times.
✓ Decision 'false' taken 1 times.
|
2375 | if (!params_contain_nan(new_params)) { // happy path |
311 |
1/2✓ Branch 1 taken 2374 times.
✗ Branch 2 not taken.
|
2374 | return get_op_ptr(this->type_, new_params, this->n_qubits_); | |
312 | } | |||
313 | ||||
314 | // Try perturbing all values in the map. May need several attempts in case | |||
315 | // there are subexpressions on the boundary of validity, such as acos(1.0). If | |||
316 | // we fail after 1000 attempts, give up. | |||
317 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1/2✓ Decision 'true' taken 1 times.
✗ Decision 'false' not taken.
|
1 | for (unsigned i = 0; i < 1000; i++) { |
318 | 1 | SymEngine::map_basic_basic new_sub_map; | ||
319 |
2/2✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 1 times.
|
3 | for (const auto& pair : sub_map) { |
320 |
6/12✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
|
2 | new_sub_map[pair.first] = Expr(pair.second) + random_perturbation(); | |
321 | } | |||
322 | std::vector<Expr> new_params_1 = | |||
323 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | subs_all_params(this->params_, new_sub_map, true); | |
324 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1/2✓ Decision 'true' taken 1 times.
✗ Decision 'false' not taken.
|
1 | if (!params_contain_nan(new_params_1)) { |
325 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | return get_op_ptr(this->type_, new_params_1, this->n_qubits_); | |
326 | } | |||
327 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
|
2 | } | |
328 | ||||
329 | // Something really is fishy. | |||
330 | ✗ | std::stringstream msg; | ||
331 | ✗ | msg << "Failed to substitute values { "; | ||
332 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | for (const auto& pair : sub_map) { | |
333 | ✗ | msg << Expr(pair.first) << " --> " << Expr(pair.second) << ", "; | ||
334 | } | |||
335 | ✗ | msg << "} in operation " << get_name() << "."; | ||
336 | ✗ | throw SubstitutionFailure(msg.str()); | ||
337 | 2375 | } | ||
338 | ||||
339 | 168169 | std::optional<double> Gate::is_identity() const { | ||
340 | static const std::optional<double> notid; | |||
341 |
1/2✓ Branch 1 taken 168169 times.
✗ Branch 2 not taken.
|
168169 | const std::vector<Expr>& params = get_params(); | |
342 |
9/12✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 77351 times.
✓ Branch 4 taken 13663 times.
✓ Branch 5 taken 8621 times.
✓ Branch 6 taken 2713 times.
✓ Branch 7 taken 21528 times.
✓ Branch 8 taken 3911 times.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 40371 times.
|
168169 | switch (get_type()) { | |
343 |
1/1✓ Decision 'true' taken 7 times.
|
7 | case OpType::noop: { | |
344 | 7 | return 0.; | ||
345 | } | |||
346 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::Phase: { | |
347 | // This is _always_ the identity up to phase, but the method does not | |||
348 | // allow us to return a symbolic phase, so we must reject in that case. | |||
349 | ✗ | std::optional<double> eval = eval_expr(params[0]); | ||
350 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | if (!eval) return notid; | |
351 | ✗ | return eval.value(); | ||
352 | } | |||
353 | 77351 | case OpType::Rx: | ||
354 | case OpType::Ry: | |||
355 | case OpType::Rz: | |||
356 | case OpType::PhasedX: | |||
357 | case OpType::NPhasedX: | |||
358 | case OpType::XXPhase: | |||
359 | case OpType::YYPhase: | |||
360 | case OpType::ZZPhase: | |||
361 | case OpType::XXPhase3: | |||
362 | case OpType::ESWAP: { | |||
363 |
1/2✓ Branch 2 taken 77351 times.
✗ Branch 3 not taken.
|
77351 | Expr e = params[0]; | |
364 |
3/4✓ Branch 1 taken 77351 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 388 times.
✓ Branch 4 taken 76963 times.
|
2/2✓ Decision 'true' taken 388 times.
✓ Decision 'false' taken 76963 times.
|
77351 | if (equiv_0(e, 4)) { |
365 | 388 | return 0.; | ||
366 |
5/8✓ Branch 1 taken 76963 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 76963 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 76963 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 798 times.
✓ Branch 12 taken 76165 times.
|
2/2✓ Decision 'true' taken 798 times.
✓ Decision 'false' taken 76165 times.
|
76963 | } else if (equiv_0(e + 2, 4)) { |
367 | 798 | return 1.; | ||
368 | } else | |||
369 | 76165 | return notid; | ||
370 | 77351 | } | ||
371 | 13663 | case OpType::U1: | ||
372 | case OpType::CU1: { | |||
373 |
3/4✓ Branch 2 taken 13663 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
✓ Branch 5 taken 13577 times.
|
27326 | return equiv_0(params[0]) ? 0. : notid; | |
374 | } | |||
375 |
1/1✓ Decision 'true' taken 8621 times.
|
8621 | case OpType::U3: { | |
376 |
1/2✓ Branch 2 taken 8621 times.
✗ Branch 3 not taken.
|
8621 | Expr theta = params[0]; | |
377 |
4/6✓ Branch 3 taken 8621 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 8621 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 109 times.
✓ Branch 10 taken 8512 times.
|
2/2✓ Decision 'true' taken 109 times.
✓ Decision 'false' taken 8512 times.
|
8621 | if (equiv_0(params[1] + params[2])) { |
378 |
3/4✓ Branch 1 taken 109 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 103 times.
|
2/2✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 103 times.
|
109 | if (equiv_0(theta, 4)) { |
379 | 6 | return 0.; | ||
380 |
4/8✓ Branch 1 taken 103 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 103 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 103 times.
✗ Branch 8 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 103 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 103 times.
|
103 | } else if (equiv_0(theta + 2, 4)) { |
381 | ✗ | return 1.; | ||
382 | } else | |||
383 | 103 | return notid; | ||
384 | } else | |||
385 | 8512 | return notid; | ||
386 | 8621 | } | ||
387 |
1/1✓ Decision 'true' taken 2713 times.
|
2713 | case OpType::CU3: { | |
388 |
9/16✓ Branch 2 taken 2713 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 29 times.
✓ Branch 5 taken 2684 times.
✓ Branch 9 taken 29 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 29 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 29 times.
✓ Branch 16 taken 29 times.
✓ Branch 17 taken 2684 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 2713 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 2713 times.
|
2713 | if (equiv_0(params[0], 4) && equiv_0(params[1] + params[2])) { |
389 | ✗ | return 0.; | ||
390 | } else | |||
391 | 2713 | return notid; | ||
392 | } | |||
393 |
1/1✓ Decision 'true' taken 21528 times.
|
21528 | case OpType::TK1: { | |
394 |
2/4✓ Branch 3 taken 21528 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 21528 times.
✗ Branch 8 not taken.
|
21528 | Expr s = params[0] + params[2], t = params[1]; | |
395 |
8/10✓ Branch 1 taken 21528 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3182 times.
✓ Branch 4 taken 18346 times.
✓ Branch 6 taken 3182 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 68 times.
✓ Branch 9 taken 3114 times.
✓ Branch 10 taken 68 times.
✓ Branch 11 taken 21460 times.
|
2/2✓ Decision 'true' taken 68 times.
✓ Decision 'false' taken 21460 times.
|
21528 | if (equiv_0(s) && equiv_0(t)) { |
396 |
4/6✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 68 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 67 times.
|
68 | return (equiv_0(s, 4) ^ equiv_0(t, 4)) ? 1. : 0.; | |
397 | } else | |||
398 | 21460 | return notid; | ||
399 | 21528 | } | ||
400 |
1/1✓ Decision 'true' taken 3911 times.
|
3911 | case OpType::TK2: { | |
401 | 3911 | bool pi_phase = false; | ||
402 |
2/2✓ Branch 5 taken 3946 times.
✓ Branch 6 taken 4 times.
|
2/2✓ Decision 'true' taken 3946 times.
✓ Decision 'false' taken 4 times.
|
3950 | for (const Expr& a : params) { |
403 |
5/8✓ Branch 1 taken 3946 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3946 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3946 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 3944 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 3944 times.
|
3946 | if (equiv_0(a + 2, 4)) { |
404 | 2 | pi_phase = !pi_phase; | ||
405 |
3/4✓ Branch 1 taken 3944 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3907 times.
✓ Branch 4 taken 37 times.
|
2/2✓ Decision 'true' taken 3907 times.
✓ Decision 'false' taken 37 times.
|
3944 | } else if (!equiv_0(a, 4)) { |
406 | 3907 | return notid; | ||
407 | } | |||
408 | } | |||
409 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | return pi_phase ? 1. : 0.; | |
410 | } | |||
411 | 4 | case OpType::CRz: | ||
412 | case OpType::CRx: | |||
413 | case OpType::CRy: | |||
414 | case OpType::PhaseGadget: | |||
415 | case OpType::ISWAP: | |||
416 | case OpType::CnRy: { | |||
417 |
2/4✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
|
8 | return equiv_0(params[0], 4) ? 0. : notid; | |
418 | } | |||
419 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::FSim: { | |
420 | ✗ | return (equiv_0(params[0]) && equiv_0(params[1])) ? 0. : notid; | ||
421 | } | |||
422 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::PhasedISWAP: { | |
423 | ✗ | return (equiv_0(params[0], 1) && equiv_0(params[1], 4)) ? 0. : notid; | ||
424 | } | |||
425 |
1/1✓ Decision 'true' taken 40371 times.
|
40371 | default: | |
426 | 40371 | return notid; | ||
427 | } | |||
428 | 168169 | } | ||
429 | ||||
430 | 8087 | bool Gate::is_clifford() const { | ||
431 |
2/2✓ Branch 1 taken 714 times.
✓ Branch 2 taken 7373 times.
|
2/2✓ Decision 'true' taken 7373 times.
✓ Decision 'false' taken 714 times.
|
8087 | if (is_clifford_type(type_)) return true; |
432 | ||||
433 |
4/4✓ Branch 0 taken 7360 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9 times.
|
7373 | switch (type_) { | |
434 | 7360 | case OpType::Rx: | ||
435 | case OpType::Ry: | |||
436 | case OpType::Rz: | |||
437 | case OpType::U1: | |||
438 | case OpType::U2: | |||
439 | case OpType::U3: | |||
440 | case OpType::TK1: | |||
441 | case OpType::TK2: | |||
442 | case OpType::XXPhase: | |||
443 | case OpType::YYPhase: | |||
444 | case OpType::ZZPhase: | |||
445 | case OpType::XXPhase3: | |||
446 | case OpType::PhasedX: | |||
447 | case OpType::NPhasedX: | |||
448 | 7360 | return std::all_of(params_.begin(), params_.end(), [](const Expr& e) { | ||
449 |
2/4✓ Branch 2 taken 17307 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 17307 times.
✗ Branch 6 not taken.
|
17307 | return equiv_0(4 * e); | |
450 | 7360 | }); | ||
451 | 2 | case OpType::ISWAP: | ||
452 | case OpType::ESWAP: | |||
453 |
2/4✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
2 | return equiv_0(2 * params_.at(0)); | |
454 | 2 | case OpType::PhasedISWAP: | ||
455 | case OpType::FSim: | |||
456 |
14/36✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 2 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 2 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 2 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 2 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 2 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 2 times.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
|
2 | return equiv_0(4 * params_.at(0)) && equiv_0(2 * params_.at(1)); | |
457 |
1/1✓ Decision 'true' taken 9 times.
|
9 | default: | |
458 | 9 | return false; | ||
459 | } | |||
460 | } | |||
461 | ||||
462 | 1248 | std::string Gate::get_name(bool latex) const { | ||
463 |
1/2✓ Branch 1 taken 1248 times.
✗ Branch 2 not taken.
|
1248 | OpDesc desc = get_desc(); | |
464 |
2/2✓ Branch 1 taken 434 times.
✓ Branch 2 taken 814 times.
|
2/2✓ Decision 'true' taken 434 times.
✓ Decision 'false' taken 814 times.
|
1248 | if (params_.size() > 0) { |
465 |
1/2✓ Branch 1 taken 434 times.
✗ Branch 2 not taken.
|
434 | std::stringstream name; | |
466 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 426 times.
|
2/2✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 426 times.
|
434 | if (latex) { |
467 |
3/6✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
|
8 | name << desc.latex() << "("; | |
468 | } else { | |||
469 |
3/6✓ Branch 1 taken 426 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 426 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 426 times.
✗ Branch 8 not taken.
|
426 | name << desc.name() << "("; | |
470 | } | |||
471 |
2/2✓ Branch 1 taken 719 times.
✓ Branch 2 taken 434 times.
|
2/2✓ Decision 'true' taken 719 times.
✓ Decision 'false' taken 434 times.
|
1153 | for (unsigned i = 0; i < params_.size(); ++i) { |
472 | std::optional<double> reduced = | |||
473 |
2/4✓ Branch 1 taken 719 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 719 times.
✗ Branch 6 not taken.
|
719 | eval_expr_mod(params_[i], desc.param_mod(i)); | |
474 |
2/2✓ Branch 1 taken 652 times.
✓ Branch 2 taken 67 times.
|
2/2✓ Decision 'true' taken 652 times.
✓ Decision 'false' taken 67 times.
|
719 | if (reduced) { |
475 |
2/4✓ Branch 1 taken 652 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 652 times.
✗ Branch 5 not taken.
|
652 | name << reduced.value(); | |
476 | } else { | |||
477 |
1/2✓ Branch 2 taken 67 times.
✗ Branch 3 not taken.
|
67 | name << params_[i]; | |
478 | } | |||
479 |
3/4✓ Branch 1 taken 285 times.
✓ Branch 2 taken 434 times.
✓ Branch 4 taken 285 times.
✗ Branch 5 not taken.
|
2/2✓ Decision 'true' taken 434 times.
✓ Decision 'false' taken 285 times.
|
719 | if (i < params_.size() - 1) name << ", "; |
480 | } | |||
481 |
1/2✓ Branch 1 taken 434 times.
✗ Branch 2 not taken.
|
434 | name << ")"; | |
482 |
1/2✓ Branch 1 taken 434 times.
✗ Branch 2 not taken.
|
434 | return name.str(); | |
483 | 434 | } else { | ||
484 |
1/2✓ Branch 1 taken 814 times.
✗ Branch 2 not taken.
|
814 | return Op::get_name(latex); | |
485 | } | |||
486 | 1248 | } | ||
487 | ||||
488 | 1175 | std::string Gate::get_command_str(const unit_vector_t& args) const { | ||
489 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1172 times.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 1172 times.
|
1175 | if (get_type() == OpType::Measure) { |
490 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | std::stringstream out; | |
491 |
3/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
|
12 | out << get_name() << " " << args[0].repr() << " --> " << args[1].repr() | |
492 |
6/12✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 3 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
|
9 | << ";"; | |
493 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | return out.str(); | |
494 | 3 | } else | ||
495 | 1172 | return Op::get_command_str(args); | ||
496 | } | |||
497 | ||||
498 | 778790 | unsigned Gate::n_qubits() const { | ||
499 |
1/2✓ Branch 1 taken 778790 times.
✗ Branch 2 not taken.
|
778790 | OptUInt n = desc_.n_qubits(); | |
500 |
2/2✓ Branch 1 taken 2971 times.
✓ Branch 2 taken 775819 times.
|
2/2✓ Decision 'true' taken 2971 times.
✓ Decision 'false' taken 775819 times.
|
778790 | if (n == any) { |
501 | 2971 | return n_qubits_; | ||
502 | } else { | |||
503 |
1/2✓ Branch 1 taken 775819 times.
✗ Branch 2 not taken.
|
775819 | return n.value(); | |
504 | } | |||
505 | } | |||
506 | ||||
507 | 24673 | bool Gate::is_equal(const Op& op_other) const { | ||
508 |
1/2✓ Branch 0 taken 24673 times.
✗ Branch 1 not taken.
|
24673 | const Gate& other = dynamic_cast<const Gate&>(op_other); | |
509 | ||||
510 |
1/2✓ Branch 1 taken 24673 times.
✗ Branch 2 not taken.
|
24673 | OpDesc desc = get_desc(); | |
511 |
3/6✓ Branch 1 taken 24673 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24673 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 24673 times.
|
1/2✓ Decision 'true' taken 24673 times.
✗ Decision 'false' not taken.
|
24673 | if (n_qubits() != other.n_qubits()) return false; |
512 |
1/2✓ Branch 1 taken 24673 times.
✗ Branch 2 not taken.
|
24673 | std::vector<Expr> params1 = this->get_params(); | |
513 |
1/2✓ Branch 1 taken 24673 times.
✗ Branch 2 not taken.
|
24673 | std::vector<Expr> params2 = other.get_params(); | |
514 | 24673 | unsigned param_count = params1.size(); | ||
515 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 24673 times.
|
0/1? Decision couldn't be analyzed.
|
24673 | if (params2.size() != param_count) return false; |
516 |
2/2✓ Branch 0 taken 22979 times.
✓ Branch 1 taken 21991 times.
|
2/2✓ Decision 'true' taken 22979 times.
✓ Decision 'false' taken 21991 times.
|
44970 | for (unsigned i = 0; i < param_count; i++) { |
517 |
4/6✓ Branch 1 taken 22979 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 22979 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2682 times.
✓ Branch 9 taken 20297 times.
|
2/2✓ Decision 'true' taken 21991 times.
✓ Decision 'false' taken 988 times.
|
22979 | if (!equiv_expr(params1[i], params2[i], desc.param_mod(i))) return false; |
518 | } | |||
519 | 21991 | return true; | ||
520 | 24673 | } | ||
521 | ||||
522 | 2 | std::vector<Expr> Gate::get_params_reduced() const { | ||
523 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | OpDesc desc = get_desc(); | |
524 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | unsigned n_params = desc.n_params(); | |
525 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::vector<Expr> params(n_params); | |
526 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 2 times.
|
4 | for (unsigned i = 0; i < n_params; i++) { |
527 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | Expr param = params_[i]; | |
528 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | std::optional<double> e = eval_expr_mod(param, desc.param_mod(i)); | |
529 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
1/2✓ Decision 'true' taken 2 times.
✗ Decision 'false' not taken.
|
2 | if (e) { |
530 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | params[i] = e.value(); | |
531 | } else { | |||
532 | ✗ | params[i] = param; | ||
533 | } | |||
534 | 2 | } | ||
535 | 4 | return params; | ||
536 | 2 | } | ||
537 | ||||
538 | 131694 | std::vector<Expr> Gate::get_tk1_angles() const { | ||
539 | const Expr half = | |||
540 |
6/12✓ Branch 1 taken 131694 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 131694 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 131694 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 131694 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 131694 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 131694 times.
✗ Branch 17 not taken.
|
263388 | SymEngine::div(SymEngine::integer(1), SymEngine::integer(2)); | |
541 | const Expr quarter = | |||
542 |
6/12✓ Branch 1 taken 131694 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 131694 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 131694 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 131694 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 131694 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 131694 times.
✗ Branch 17 not taken.
|
263388 | SymEngine::div(SymEngine::integer(1), SymEngine::integer(4)); | |
543 | const Expr eighth = | |||
544 |
6/12✓ Branch 1 taken 131694 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 131694 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 131694 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 131694 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 131694 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 131694 times.
✗ Branch 17 not taken.
|
263388 | SymEngine::div(SymEngine::integer(1), SymEngine::integer(8)); | |
545 |
22/23✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5788 times.
✓ Branch 3 taken 4993 times.
✓ Branch 4 taken 1090 times.
✓ Branch 5 taken 5563 times.
✓ Branch 6 taken 2137 times.
✓ Branch 7 taken 4702 times.
✓ Branch 8 taken 1786 times.
✓ Branch 9 taken 8246 times.
✓ Branch 10 taken 4177 times.
✓ Branch 11 taken 78 times.
✓ Branch 12 taken 6 times.
✓ Branch 13 taken 2922 times.
✓ Branch 14 taken 1338 times.
✓ Branch 15 taken 13585 times.
✓ Branch 16 taken 26103 times.
✓ Branch 17 taken 2746 times.
✓ Branch 18 taken 85 times.
✓ Branch 19 taken 685 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 351 times.
✓ Branch 22 taken 45304 times.
✓ Branch 23 taken 4 times.
|
131694 | switch (get_type()) { | |
546 |
1/1✓ Decision 'true' taken 25 times.
|
5 | case OpType::noop: { | |
547 |
7/14✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 20 times.
✓ Branch 18 taken 5 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
25 | return {0, 0, 0, 0}; | |
548 | } | |||
549 |
1/1✓ Decision 'true' taken 28940 times.
|
5788 | case OpType::Z: { | |
550 |
7/14✓ Branch 1 taken 5788 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5788 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5788 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5788 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 5788 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 23152 times.
✓ Branch 18 taken 5788 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
28940 | return {0, 0, 1, half}; | |
551 | } | |||
552 |
1/1✓ Decision 'true' taken 24965 times.
|
4993 | case OpType::X: { | |
553 |
7/14✓ Branch 1 taken 4993 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4993 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4993 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4993 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 4993 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 19972 times.
✓ Branch 18 taken 4993 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
24965 | return {0, 1, 0, half}; | |
554 | } | |||
555 |
1/1✓ Decision 'true' taken 5450 times.
|
1090 | case OpType::Y: { | |
556 |
7/14✓ Branch 1 taken 1090 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1090 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1090 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1090 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1090 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 4360 times.
✓ Branch 18 taken 1090 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
5450 | return {half, 1, -half, half}; | |
557 | } | |||
558 |
1/1✓ Decision 'true' taken 27815 times.
|
5563 | case OpType::S: { | |
559 |
7/14✓ Branch 1 taken 5563 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5563 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5563 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5563 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 5563 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 22252 times.
✓ Branch 18 taken 5563 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
27815 | return {0, 0, half, quarter}; | |
560 | } | |||
561 |
1/1✓ Decision 'true' taken 10685 times.
|
2137 | case OpType::Sdg: { | |
562 |
7/14✓ Branch 1 taken 2137 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2137 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2137 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2137 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 2137 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 8548 times.
✓ Branch 18 taken 2137 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
10685 | return {0, 0, -half, -quarter}; | |
563 | } | |||
564 |
1/1✓ Decision 'true' taken 23510 times.
|
4702 | case OpType::T: { | |
565 |
7/14✓ Branch 1 taken 4702 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4702 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4702 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4702 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 4702 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 18808 times.
✓ Branch 18 taken 4702 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
23510 | return {0, 0, quarter, eighth}; | |
566 | } | |||
567 |
1/1✓ Decision 'true' taken 8930 times.
|
1786 | case OpType::Tdg: { | |
568 |
7/14✓ Branch 1 taken 1786 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1786 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1786 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1786 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1786 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 7144 times.
✓ Branch 18 taken 1786 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
8930 | return {0, 0, -quarter, -eighth}; | |
569 | } | |||
570 |
1/1✓ Decision 'true' taken 41230 times.
|
8246 | case OpType::V: { | |
571 |
7/14✓ Branch 1 taken 8246 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8246 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8246 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 8246 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 8246 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 32984 times.
✓ Branch 18 taken 8246 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
41230 | return {0, half, 0, 0}; | |
572 | } | |||
573 |
1/1✓ Decision 'true' taken 20885 times.
|
4177 | case OpType::Vdg: { | |
574 |
7/14✓ Branch 1 taken 4177 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4177 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4177 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4177 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 4177 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 16708 times.
✓ Branch 18 taken 4177 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
20885 | return {0, -half, 0, 0}; | |
575 | } | |||
576 |
1/1✓ Decision 'true' taken 390 times.
|
78 | case OpType::SX: { | |
577 |
7/14✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 78 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 78 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 78 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 78 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 312 times.
✓ Branch 18 taken 78 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
390 | return {0, half, 0, quarter}; | |
578 | } | |||
579 |
1/1✓ Decision 'true' taken 30 times.
|
6 | case OpType::SXdg: { | |
580 |
7/14✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 6 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 24 times.
✓ Branch 18 taken 6 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
30 | return {0, -half, 0, -quarter}; | |
581 | } | |||
582 |
1/1✓ Decision 'true' taken 14610 times.
|
2922 | case OpType::H: { | |
583 |
7/14✓ Branch 1 taken 2922 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2922 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2922 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2922 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 2922 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 11688 times.
✓ Branch 18 taken 2922 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
14610 | return {half, half, half, half}; | |
584 | } | |||
585 |
1/1✓ Decision 'true' taken 6690 times.
|
1338 | case OpType::Rx: { | |
586 |
8/16✓ Branch 1 taken 1338 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1338 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1338 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1338 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1338 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 1338 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 5352 times.
✓ Branch 21 taken 1338 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
|
6690 | return {0, params_.at(0), 0, 0}; | |
587 | } | |||
588 |
1/1✓ Decision 'true' taken 67925 times.
|
13585 | case OpType::Ry: { | |
589 |
8/16✓ Branch 1 taken 13585 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13585 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13585 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 13585 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 13585 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 13585 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 54340 times.
✓ Branch 21 taken 13585 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
|
67925 | return {half, params_.at(0), -half, 0}; | |
590 | } | |||
591 | 26103 | case OpType::Rz: | ||
592 | case OpType::PhaseGadget: { | |||
593 |
8/16✓ Branch 1 taken 26103 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 26103 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 26103 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 26103 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 26103 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 26103 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 104412 times.
✓ Branch 21 taken 26103 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
|
130515 | return {0, 0, params_.at(0), 0}; | |
594 | } | |||
595 |
1/1✓ Decision 'true' taken 13730 times.
|
2746 | case OpType::U1: { | |
596 |
10/20✓ Branch 1 taken 2746 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2746 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2746 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2746 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2746 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2746 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 2746 times.
✗ Branch 20 not taken.
✓ Branch 23 taken 2746 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 10984 times.
✓ Branch 27 taken 2746 times.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
|
13730 | return {0, 0, params_.at(0), params_.at(0) / 2}; | |
597 | } | |||
598 | 85 | case OpType::U2: { | ||
599 | return { | |||
600 |
2/4✓ Branch 1 taken 85 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 85 times.
✗ Branch 5 not taken.
|
170 | params_.at(0) + half, half, params_.at(1) - half, | |
601 |
11/22✓ Branch 1 taken 85 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 85 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 85 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 85 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 85 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 85 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 85 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 85 times.
✗ Branch 23 not taken.
✓ Branch 26 taken 85 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 340 times.
✓ Branch 30 taken 85 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
|
510 | (params_.at(0) + params_.at(1)) / 2}; | |
602 | } | |||
603 | 685 | case OpType::U3: { | ||
604 | return { | |||
605 |
3/6✓ Branch 1 taken 685 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 685 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 685 times.
✗ Branch 8 not taken.
|
2055 | params_.at(1) + half, params_.at(0), params_.at(2) - half, | |
606 |
11/22✓ Branch 1 taken 685 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 685 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 685 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 685 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 685 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 685 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 685 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 685 times.
✗ Branch 23 not taken.
✓ Branch 26 taken 685 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 2740 times.
✓ Branch 30 taken 685 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
|
4795 | (params_.at(1) + params_.at(2)) / 2}; | |
607 | } | |||
608 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::NPhasedX: { | |
609 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | if (n_qubits_ != 1) { | |
610 | ✗ | throw BadOpType( | ||
611 | "OpType::NPhasedX can only be decomposed into a TK1 " | |||
612 | "if it acts on a single qubit", | |||
613 | ✗ | OpType::NPhasedX); | ||
614 | } | |||
615 | ✗ | return {params_.at(1), params_.at(0), minus_times(params_.at(1)), 0}; | ||
616 | } | |||
617 |
1/1✓ Decision 'true' taken 1755 times.
|
351 | case OpType::PhasedX: { | |
618 |
10/20✓ Branch 1 taken 351 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 351 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 351 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 351 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 351 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 351 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 351 times.
✗ Branch 20 not taken.
✓ Branch 23 taken 351 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 1404 times.
✓ Branch 27 taken 351 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
|
1755 | return {params_.at(1), params_.at(0), minus_times(params_.at(1)), 0}; | |
619 | } | |||
620 |
1/1✓ Decision 'true' taken 226520 times.
|
45304 | case OpType::TK1: { | |
621 |
10/20✓ Branch 1 taken 45304 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 45304 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 45304 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 45304 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 45304 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 45304 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 45304 times.
✗ Branch 20 not taken.
✓ Branch 23 taken 45304 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 181216 times.
✓ Branch 27 taken 45304 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
|
226520 | return {params_.at(0), params_.at(1), params_.at(2), 0}; | |
622 | } | |||
623 |
1/1✓ Decision 'true' taken 4 times.
|
4 | default: { | |
624 |
2/4✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
4 | throw BadOpType("Cannot compute TK1 angles", get_type()); | |
625 | } | |||
626 | } | |||
627 | 131702 | } | ||
628 | ||||
629 | 799348 | std::vector<Expr> Gate::get_params() const { return params_; } | ||
630 | ||||
631 |
1/2✓ Branch 2 taken 5179 times.
✗ Branch 3 not taken.
|
10358 | SymSet Gate::free_symbols() const { return expr_free_symbols(get_params()); } | |
632 | ||||
633 | /** | |||
634 | * @brief The commutation colour of TK1(a,b,c) | |||
635 | * | |||
636 | * - commutes with everything if b == 0 && a == -c | |||
637 | * - commutes with Z if b == 0 | |||
638 | * - commutes with X if a == c == 0 | |||
639 | * - commutes with nothing otherwise | |||
640 | * | |||
641 | * @param params the TK1 angles | |||
642 | * @return std::optional<Pauli> commutation colour | |||
643 | */ | |||
644 | 19881 | static std::optional<Pauli> tk1_commuting_basis(std::vector<Expr> params) { | ||
645 | 19881 | const bool p0_is_zero = equiv_0(params[0], 2); | ||
646 | 19881 | const bool p1_is_zero = equiv_0(params[1], 2); | ||
647 | 19881 | const bool p2_is_zero = equiv_0(params[2], 2); | ||
648 |
10/14✓ Branch 0 taken 10400 times.
✓ Branch 1 taken 9481 times.
✓ Branch 4 taken 10400 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 10400 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✓ Branch 11 taken 10392 times.
✓ Branch 12 taken 10400 times.
✓ Branch 13 taken 9481 times.
✓ Branch 15 taken 8 times.
✓ Branch 16 taken 19873 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
2/2✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 19873 times.
|
19881 | if (p1_is_zero && equiv_expr(params[0], -params[2], 2)) { |
649 | 8 | return Pauli::I; | ||
650 |
2/2✓ Branch 0 taken 10392 times.
✓ Branch 1 taken 9481 times.
|
2/2✓ Decision 'true' taken 10392 times.
✓ Decision 'false' taken 9481 times.
|
19873 | } else if (p1_is_zero) { |
651 | 10392 | return Pauli::Z; | ||
652 |
4/4✓ Branch 0 taken 3256 times.
✓ Branch 1 taken 6225 times.
✓ Branch 2 taken 1473 times.
✓ Branch 3 taken 1783 times.
|
2/2✓ Decision 'true' taken 1473 times.
✓ Decision 'false' taken 8008 times.
|
9481 | } else if (p0_is_zero && p2_is_zero) { |
653 | 1473 | return Pauli::X; | ||
654 | } else { | |||
655 | 8008 | return std::nullopt; | ||
656 | } | |||
657 | } | |||
658 | ||||
659 | /** | |||
660 | * @brief The commutation colour of TK2(a,b,c) | |||
661 | * | |||
662 | * - commutes with everything if a == b == c | |||
663 | * - commutes with X if b == c == 0 | |||
664 | * - commutes with Y if a == c == 0 | |||
665 | * - commutes with Z if a == b == 0 | |||
666 | * - commutes with nothing otherwise | |||
667 | * | |||
668 | * @param params the TK2 angles | |||
669 | * @return std::optional<Pauli> commutation colour | |||
670 | */ | |||
671 | 10912 | static std::optional<Pauli> tk2_commuting_basis(std::vector<Expr> params) { | ||
672 | 10912 | const bool p0_is_zero = equiv_0(params[0], 2); | ||
673 | 10912 | const bool p1_is_zero = equiv_0(params[1], 2); | ||
674 | 10912 | const bool p2_is_zero = equiv_0(params[2], 2); | ||
675 |
6/6✓ Branch 0 taken 66 times.
✓ Branch 1 taken 10846 times.
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 32 times.
✓ Branch 5 taken 23 times.
|
2/2✓ Decision 'true' taken 32 times.
✓ Decision 'false' taken 10880 times.
|
10912 | if (p0_is_zero && p1_is_zero && p2_is_zero) { |
676 | 32 | return Pauli::I; | ||
677 |
4/4✓ Branch 0 taken 9992 times.
✓ Branch 1 taken 888 times.
✓ Branch 2 taken 9969 times.
✓ Branch 3 taken 23 times.
|
2/2✓ Decision 'true' taken 9969 times.
✓ Decision 'false' taken 911 times.
|
10880 | } else if (p1_is_zero && p2_is_zero) { |
678 | 9969 | return Pauli::X; | ||
679 |
4/4✓ Branch 0 taken 34 times.
✓ Branch 1 taken 877 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 23 times.
|
2/2✓ Decision 'true' taken 11 times.
✓ Decision 'false' taken 900 times.
|
911 | } else if (p0_is_zero && p2_is_zero) { |
680 | 11 | return Pauli::Y; | ||
681 |
3/4✓ Branch 0 taken 23 times.
✓ Branch 1 taken 877 times.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
|
2/2✓ Decision 'true' taken 23 times.
✓ Decision 'false' taken 877 times.
|
900 | } else if (p0_is_zero && p1_is_zero) { |
682 | 23 | return Pauli::Z; | ||
683 | } else { | |||
684 | 877 | return std::nullopt; | ||
685 | } | |||
686 | } | |||
687 | ||||
688 | 77060 | std::optional<Pauli> Gate::commuting_basis(unsigned i) const { | ||
689 | 77060 | unsigned n_q = n_qubits(); | ||
690 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 77059 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2/2✓ Decision 'true' taken 77059 times.
✓ Decision 'false' taken 1 times.
|
77060 | if (i >= n_q) throw std::domain_error("Qubit index out of range"); |
691 |
11/13✗ Branch 1 not taken.
✓ Branch 2 taken 19881 times.
✓ Branch 3 taken 164 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1815 times.
✓ Branch 6 taken 339 times.
✓ Branch 7 taken 10912 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 20 times.
✓ Branch 10 taken 43460 times.
✓ Branch 11 taken 405 times.
✓ Branch 12 taken 34 times.
✓ Branch 13 taken 25 times.
|
77059 | switch (get_type()) { | |
692 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::Phase: { | |
693 | ✗ | return Pauli::I; | ||
694 | } | |||
695 | 19881 | case OpType::X: | ||
696 | case OpType::V: | |||
697 | case OpType::Vdg: | |||
698 | case OpType::SX: | |||
699 | case OpType::SXdg: | |||
700 | case OpType::Rx: | |||
701 | case OpType::Y: | |||
702 | case OpType::Ry: | |||
703 | case OpType::noop: | |||
704 | case OpType::H: | |||
705 | case OpType::U3: | |||
706 | case OpType::U2: | |||
707 | case OpType::PhasedX: | |||
708 | case OpType::Z: | |||
709 | case OpType::S: | |||
710 | case OpType::Sdg: | |||
711 | case OpType::T: | |||
712 | case OpType::Tdg: | |||
713 | case OpType::Rz: | |||
714 | case OpType::U1: | |||
715 | case OpType::TK1: { | |||
716 |
1/2✓ Branch 2 taken 19881 times.
✗ Branch 3 not taken.
|
19881 | return tk1_commuting_basis(get_tk1_angles()); | |
717 | } | |||
718 | 164 | case OpType::XXPhase: | ||
719 | case OpType::XXPhase3: { | |||
720 | 164 | return Pauli::X; | ||
721 | } | |||
722 |
0/1✗ Decision 'true' not taken.
|
✗ | case OpType::YYPhase: { | |
723 | ✗ | return Pauli::Y; | ||
724 | } | |||
725 | 1815 | case OpType::CZ: | ||
726 | case OpType::CRz: | |||
727 | case OpType::CU1: | |||
728 | case OpType::PhaseGadget: | |||
729 | case OpType::ZZMax: | |||
730 | case OpType::ZZPhase: | |||
731 | case OpType::CnZ: { | |||
732 | 1815 | return Pauli::Z; | ||
733 | } | |||
734 |
1/1✓ Decision 'true' taken 339 times.
|
339 | case OpType::NPhasedX: { | |
735 | 339 | return std::nullopt; | ||
736 | } | |||
737 |
1/1✓ Decision 'true' taken 10912 times.
|
10912 | case OpType::TK2: { | |
738 |
1/2✓ Branch 2 taken 10912 times.
✗ Branch 3 not taken.
|
10912 | return tk2_commuting_basis(params_); | |
739 | } | |||
740 | 4 | case OpType::CH: | ||
741 | case OpType::CU3: | |||
742 | case OpType::CSWAP: { | |||
743 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 1 times.
|
4 | if (i == 0) { |
744 | 3 | return Pauli::Z; | ||
745 | } else { | |||
746 | 1 | return std::nullopt; | ||
747 | } | |||
748 | } | |||
749 |
1/1✓ Decision 'true' taken 20 times.
|
20 | case OpType::BRIDGE: { | |
750 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
2/2✓ Decision 'true' taken 10 times.
✓ Decision 'false' taken 10 times.
|
20 | if (i == 0) { |
751 | 10 | return Pauli::Z; | ||
752 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
|
2/2✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 6 times.
|
10 | } else if (i == 2) { |
753 | 4 | return Pauli::X; | ||
754 | } else { | |||
755 | 6 | return Pauli::I; | ||
756 | } | |||
757 | } | |||
758 | 43460 | case OpType::CV: | ||
759 | case OpType::CVdg: | |||
760 | case OpType::CSX: | |||
761 | case OpType::CSXdg: | |||
762 | case OpType::CRx: | |||
763 | case OpType::CX: | |||
764 | case OpType::CCX: | |||
765 | case OpType::CnX: { | |||
766 |
2/2✓ Branch 0 taken 27144 times.
✓ Branch 1 taken 16316 times.
|
2/2✓ Decision 'true' taken 27144 times.
✓ Decision 'false' taken 16316 times.
|
43460 | if (i == n_q - 1) { |
767 | 27144 | return Pauli::X; | ||
768 | } else { | |||
769 | 16316 | return Pauli::Z; | ||
770 | } | |||
771 | } | |||
772 |
1/1✓ Decision 'true' taken 405 times.
|
405 | case OpType::ECR: { | |
773 |
2/2✓ Branch 0 taken 207 times.
✓ Branch 1 taken 198 times.
|
2/2✓ Decision 'true' taken 207 times.
✓ Decision 'false' taken 198 times.
|
405 | if (i == 1) { |
774 | 207 | return Pauli::X; | ||
775 | } else { | |||
776 | 198 | return std::nullopt; | ||
777 | } | |||
778 | } | |||
779 | 34 | case OpType::CY: | ||
780 | case OpType::CRy: | |||
781 | case OpType::CnRy: | |||
782 | case OpType::CnY: { | |||
783 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 24 times.
|
2/2✓ Decision 'true' taken 10 times.
✓ Decision 'false' taken 24 times.
|
34 | if (i == n_q - 1) { |
784 | 10 | return Pauli::Y; | ||
785 | } else { | |||
786 | 24 | return Pauli::Z; | ||
787 | } | |||
788 | } | |||
789 |
1/1✓ Decision 'true' taken 25 times.
|
25 | default: { | |
790 | 25 | return std::nullopt; | ||
791 | } | |||
792 | } | |||
793 | } | |||
794 | ||||
795 | 28618 | bool Gate::commutes_with_basis( | ||
796 | const std::optional<Pauli>& colour, unsigned i) const { | |||
797 |
1/2✓ Branch 1 taken 28618 times.
✗ Branch 2 not taken.
|
28618 | const std::optional<Pauli> my_colour = commuting_basis(i); | |
798 |
6/6✓ Branch 1 taken 22953 times.
✓ Branch 2 taken 5665 times.
✓ Branch 4 taken 3193 times.
✓ Branch 5 taken 19760 times.
✓ Branch 6 taken 8858 times.
✓ Branch 7 taken 19760 times.
|
2/2✓ Decision 'true' taken 8858 times.
✓ Decision 'false' taken 19760 times.
|
28618 | if (!colour || !my_colour) { |
799 | // Nothing can commute with std::nullopt | |||
800 | 8858 | return false; | ||
801 | } else { | |||
802 |
6/6✓ Branch 1 taken 19757 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 19754 times.
✓ Branch 5 taken 3 times.
✓ Branch 7 taken 8547 times.
✓ Branch 8 taken 11207 times.
|
19760 | return colour == Pauli::I || my_colour == Pauli::I || colour == my_colour; | |
803 | } | |||
804 | } | |||
805 | ||||
806 | 3067177 | op_signature_t Gate::get_signature() const { | ||
807 |
1/2✓ Branch 1 taken 3067177 times.
✗ Branch 2 not taken.
|
3067177 | std::optional<op_signature_t> sig = desc_.signature(); | |
808 |
2/2✓ Branch 1 taken 3062607 times.
✓ Branch 2 taken 4570 times.
|
2/2✓ Decision 'true' taken 3062607 times.
✓ Decision 'false' taken 4570 times.
|
3067177 | if (sig) |
809 |
1/2✓ Branch 2 taken 3062607 times.
✗ Branch 3 not taken.
|
3062607 | return *sig; | |
810 | else | |||
811 |
1/2✓ Branch 2 taken 4570 times.
✗ Branch 3 not taken.
|
9140 | return op_signature_t(n_qubits_, EdgeType::Quantum); | |
812 | 3067177 | } | ||
813 | ||||
814 | 62 | nlohmann::json Gate::serialize() const { | ||
815 | 62 | nlohmann::json j; | ||
816 | 62 | OpType optype = get_type(); | ||
817 |
2/4✓ Branch 1 taken 62 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 62 times.
✗ Branch 5 not taken.
|
62 | j["type"] = optype; | |
818 | // if type has a fixed signature, don't store number of qubits | |||
819 |
4/6✓ Branch 1 taken 62 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 62 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 60 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 60 times.
|
62 | if (!optypeinfo().at(optype).signature) { |
820 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | j["n_qb"] = n_qubits(); | |
821 | } | |||
822 |
1/2✓ Branch 1 taken 62 times.
✗ Branch 2 not taken.
|
62 | std::vector<Expr> params = get_params(); | |
823 |
2/2✓ Branch 1 taken 14 times.
✓ Branch 2 taken 48 times.
|
2/2✓ Decision 'true' taken 14 times.
✓ Decision 'false' taken 48 times.
|
62 | if (!params.empty()) { |
824 |
2/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
|
14 | j["params"] = params; | |
825 | } | |||
826 | 124 | return j; | ||
827 | 62 | } | ||
828 | ||||
829 | 1842 | Op_ptr Gate::deserialize(const nlohmann::json& j) { | ||
830 |
2/4✓ Branch 1 taken 1842 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1842 times.
✗ Branch 5 not taken.
|
1842 | OpType optype = j.at("type").get<OpType>(); | |
831 | 1842 | std::vector<Expr> params; | ||
832 |
3/4✓ Branch 1 taken 1842 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 597 times.
✓ Branch 4 taken 1245 times.
|
2/2✓ Decision 'true' taken 597 times.
✓ Decision 'false' taken 1245 times.
|
1842 | if (j.contains("params")) { |
833 |
2/4✓ Branch 1 taken 597 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 597 times.
✗ Branch 5 not taken.
|
597 | params = j.at("params").get<std::vector<Expr>>(); | |
834 | } | |||
835 | // if type has fixed number of qubits use it, otherwise it should have been | |||
836 | // stored | |||
837 |
2/4✓ Branch 1 taken 1842 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1842 times.
✗ Branch 5 not taken.
|
1842 | const auto& sig = optypeinfo().at(optype).signature; | |
838 | unsigned n_qb; | |||
839 |
2/2✓ Branch 1 taken 1840 times.
✓ Branch 2 taken 2 times.
|
0/1? Decision couldn't be analyzed.
|
1842 | if (sig) { |
840 | 3081 | auto check_quantum = [](unsigned sum, const EdgeType& e) { | ||
841 |
2/2✓ Branch 0 taken 3074 times.
✓ Branch 1 taken 7 times.
|
3081 | return sum + (e == EdgeType::Quantum ? 1 : 0); | |
842 | }; | |||
843 | 1840 | n_qb = std::accumulate(sig->begin(), sig->end(), 0, check_quantum); | ||
844 | } else { | |||
845 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | n_qb = j.at("n_qb").get<unsigned>(); | |
846 | } | |||
847 |
1/2✓ Branch 1 taken 1842 times.
✗ Branch 2 not taken.
|
3684 | return get_op_ptr(optype, params, n_qb); | |
848 | 1842 | } | ||
849 | ||||
850 | 2352 | Eigen::MatrixXcd Gate::get_unitary() const { | ||
851 | try { | |||
852 |
1/2✓ Branch 1 taken 2349 times.
✗ Branch 2 not taken.
|
4701 | return GateUnitaryMatrix::get_unitary(*this); | |
853 | ✗ | } catch (const GateUnitaryMatrixError& e) { | ||
854 | ✗ | switch (e.cause) { | ||
855 |
0/1✗ Decision 'true' not taken.
|
✗ | case GateUnitaryMatrixError::Cause::GATE_NOT_IMPLEMENTED: | |
856 | ✗ | throw BadOpType(get_type()); | ||
857 |
0/1✗ Decision 'true' not taken.
|
✗ | case GateUnitaryMatrixError::Cause::SYMBOLIC_PARAMETERS: | |
858 | ✗ | throw SymbolsNotSupported(); | ||
859 |
0/1✗ Decision 'true' not taken.
|
✗ | default: | |
860 | ✗ | throw e; | ||
861 | } | |||
862 | } | |||
863 | } | |||
864 | ||||
865 | 1234482 | Gate::Gate(OpType type, const std::vector<Expr>& params, unsigned n_qubits) | ||
866 |
1/2✓ Branch 2 taken 1234482 times.
✗ Branch 3 not taken.
|
1234482 | : Op(type), params_(params), n_qubits_(n_qubits) { | |
867 |
2/4✓ Branch 1 taken 1234482 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1234482 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1234482 times.
|
1234482 | if (!is_gate_type(type)) { |
868 | ✗ | throw BadOpType(type); | ||
869 | } | |||
870 |
4/6✓ Branch 2 taken 1234482 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1234482 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1234481 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 1234481 times.
|
1234482 | if (params.size() != optypeinfo().at(type).n_params()) { |
871 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | throw InvalidParameterCount(); | |
872 | } | |||
873 | 1234483 | } | ||
874 | ||||
875 | ✗ | Gate::Gate() : Op(OpType::noop), params_() {} | ||
876 | ||||
877 | } // namespace tket | |||
878 |