GCC Code Coverage Report


Directory: ./
File: Gate/Gate.cpp
Date: 2022-10-15 05:10:18
Warnings: 2 unchecked decisions!
Exec Total Coverage
Lines: 375 434 86.4%
Functions: 27 28 96.4%
Branches: 634 1227 51.7%
Decisions: 139 180 77.2%

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