GCC Code Coverage Report


Directory: ./
File: Gate/GateUnitaryMatrix.cpp
Date: 2022-10-15 05:10:18
Warnings: 1 unchecked decisions!
Exec Total Coverage
Lines: 96 96 100.0%
Functions: 5 5 100.0%
Branches: 122 175 69.7%
Decisions: 7 9 77.8%

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 "GateUnitaryMatrix.hpp"
16
17 #include <cmath>
18 #include <sstream>
19 #include <tkassert/Assert.hpp>
20
21 #include "Gate/Gate.hpp"
22 #include "GateUnitaryMatrixError.hpp"
23 #include "GateUnitaryMatrixImplementations.hpp"
24 #include "GateUnitaryMatrixUtils.hpp"
25 #include "GateUnitaryMatrixVariableQubits.hpp"
26 #include "GateUnitarySparseMatrix.hpp"
27 #include "OpType/OpTypeInfo.hpp"
28
29 // This is just for the main Gate -> matrix function, so the only part
30 // which actually uses the rest of tket. This is nothing but a wrapper around
31 // the basic named functions like x(), etc. (with extra error checks).
32
33 // NOTE: MatrixXcd objects are returned by a series of functions;
34 // if the OpType is unrecognised, it returns a 0x0 matrix.
35 // Eventually, when it is recognised, a nonempty matrix will be returned,
36 // or an error thrown if nothing recognises it.
37
38 namespace tket {
39
40 using internal::GateUnitaryMatrixImplementations;
41 using internal::GateUnitaryMatrixUtils;
42
43 #ifdef CASE_RETURN_0P
44 #error "Macro already defined!"
45 #endif
46 #define CASE_RETURN_0P(function_name) \
47 case OpType::function_name: \
48 GateUnitaryMatrixUtils::check_and_throw_upon_wrong_number_of_parameters( \
49 OpType::function_name, number_of_qubits, parameters, 0); \
50 return GateUnitaryMatrixImplementations::function_name();
51
52 #ifdef CASE_RETURN_1P
53 #error "Macro already defined!"
54 #endif
55 #define CASE_RETURN_1P(function_name) \
56 case OpType::function_name: \
57 GateUnitaryMatrixUtils::check_and_throw_upon_wrong_number_of_parameters( \
58 OpType::function_name, number_of_qubits, parameters, 1); \
59 return GateUnitaryMatrixImplementations::function_name(parameters[0]);
60
61 #ifdef CASE_RETURN_2P
62 #error "Macro already defined!"
63 #endif
64 #define CASE_RETURN_2P(function_name) \
65 case OpType::function_name: \
66 GateUnitaryMatrixUtils::check_and_throw_upon_wrong_number_of_parameters( \
67 OpType::function_name, number_of_qubits, parameters, 2); \
68 return GateUnitaryMatrixImplementations::function_name( \
69 parameters[0], parameters[1]);
70
71 #ifdef CASE_RETURN_3P
72 #error "Macro already defined!"
73 #endif
74 #define CASE_RETURN_3P(function_name) \
75 case OpType::function_name: \
76 GateUnitaryMatrixUtils::check_and_throw_upon_wrong_number_of_parameters( \
77 OpType::function_name, number_of_qubits, parameters, 3); \
78 return GateUnitaryMatrixImplementations::function_name( \
79 parameters[0], parameters[1], parameters[2]);
80
81 // Only for op types with a fixed, known number of qubits;
82 // throws if the number of parameters is wrong.
83 // However, does NOT check the number of qubits.
84 196507 static Eigen::MatrixXcd get_unitary_or_throw(
85 OpType op_type, unsigned number_of_qubits,
86 const std::vector<double>& parameters) {
87
53/53
✓ Branch 0 taken 1405 times.
✓ Branch 1 taken 532 times.
✓ Branch 2 taken 1208 times.
✓ Branch 3 taken 733 times.
✓ Branch 4 taken 372 times.
✓ Branch 5 taken 918 times.
✓ Branch 6 taken 676 times.
✓ Branch 7 taken 1125 times.
✓ Branch 8 taken 839 times.
✓ Branch 9 taken 19957 times.
✓ Branch 10 taken 44 times.
✓ Branch 11 taken 43 times.
✓ Branch 12 taken 50 times.
✓ Branch 13 taken 136 times.
✓ Branch 14 taken 49 times.
✓ Branch 15 taken 40 times.
✓ Branch 16 taken 39 times.
✓ Branch 17 taken 74474 times.
✓ Branch 18 taken 54 times.
✓ Branch 19 taken 414 times.
✓ Branch 20 taken 52 times.
✓ Branch 21 taken 48 times.
✓ Branch 22 taken 46 times.
✓ Branch 23 taken 48 times.
✓ Branch 24 taken 46 times.
✓ Branch 25 taken 79 times.
✓ Branch 26 taken 128 times.
✓ Branch 27 taken 45 times.
✓ Branch 28 taken 45 times.
✓ Branch 29 taken 1 times.
✓ Branch 30 taken 10205 times.
✓ Branch 31 taken 11277 times.
✓ Branch 32 taken 12387 times.
✓ Branch 33 taken 29532 times.
✓ Branch 34 taken 5413 times.
✓ Branch 35 taken 237 times.
✓ Branch 36 taken 213 times.
✓ Branch 37 taken 158 times.
✓ Branch 38 taken 56 times.
✓ Branch 39 taken 130 times.
✓ Branch 40 taken 117 times.
✓ Branch 41 taken 151 times.
✓ Branch 42 taken 127 times.
✓ Branch 43 taken 113 times.
✓ Branch 44 taken 247 times.
✓ Branch 45 taken 172 times.
✓ Branch 46 taken 116 times.
✓ Branch 47 taken 118 times.
✓ Branch 48 taken 2496 times.
✓ Branch 49 taken 8917 times.
✓ Branch 50 taken 9270 times.
✓ Branch 51 taken 1386 times.
✓ Branch 52 taken 23 times.
196507 switch (op_type) {
88 1405 CASE_RETURN_0P(X)
89 532 CASE_RETURN_0P(Y)
90 1208 CASE_RETURN_0P(Z)
91 733 CASE_RETURN_0P(S)
92 372 CASE_RETURN_0P(Sdg)
93 918 CASE_RETURN_0P(T)
94 676 CASE_RETURN_0P(Tdg)
95 1125 CASE_RETURN_0P(V)
96 839 CASE_RETURN_0P(Vdg)
97 19957 CASE_RETURN_0P(H)
98 44 CASE_RETURN_0P(BRIDGE)
99 43 CASE_RETURN_0P(noop)
100 50 CASE_RETURN_0P(ECR)
101 136 CASE_RETURN_0P(SX)
102 49 CASE_RETURN_0P(SXdg)
103 40 CASE_RETURN_0P(CSWAP)
104 39 CASE_RETURN_0P(CCX)
105 74474 CASE_RETURN_0P(CX)
106 54 CASE_RETURN_0P(CY)
107 414 CASE_RETURN_0P(CZ)
108 52 CASE_RETURN_0P(CH)
109 48 CASE_RETURN_0P(CV)
110 46 CASE_RETURN_0P(CVdg)
111 48 CASE_RETURN_0P(CSX)
112 46 CASE_RETURN_0P(CSXdg)
113 79 CASE_RETURN_0P(SWAP)
114 128 CASE_RETURN_0P(ZZMax)
115 45 CASE_RETURN_0P(Sycamore)
116 45 CASE_RETURN_0P(ISWAPMax)
117 #undef CASE_RETURN_0P
118
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 CASE_RETURN_1P(Phase)
119
1/2
✓ Branch 4 taken 10175 times.
✗ Branch 5 not taken.
20380 CASE_RETURN_1P(Rx)
120
1/2
✓ Branch 4 taken 11247 times.
✗ Branch 5 not taken.
22524 CASE_RETURN_1P(Ry)
121
1/2
✓ Branch 4 taken 12357 times.
✗ Branch 5 not taken.
24744 CASE_RETURN_1P(Rz)
122
1/2
✓ Branch 4 taken 29502 times.
✗ Branch 5 not taken.
59034 CASE_RETURN_1P(U1)
123
1/2
✓ Branch 4 taken 5383 times.
✗ Branch 5 not taken.
10796 CASE_RETURN_1P(CRx)
124
1/2
✓ Branch 4 taken 207 times.
✗ Branch 5 not taken.
444 CASE_RETURN_1P(CRy)
125
1/2
✓ Branch 4 taken 183 times.
✗ Branch 5 not taken.
396 CASE_RETURN_1P(CRz)
126
1/2
✓ Branch 4 taken 128 times.
✗ Branch 5 not taken.
286 CASE_RETURN_1P(CU1)
127
1/2
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
82 CASE_RETURN_1P(ISWAP)
128
1/2
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
230 CASE_RETURN_1P(XXPhase)
129
1/2
✓ Branch 4 taken 87 times.
✗ Branch 5 not taken.
204 CASE_RETURN_1P(YYPhase)
130
1/2
✓ Branch 4 taken 121 times.
✗ Branch 5 not taken.
272 CASE_RETURN_1P(ZZPhase)
131
1/2
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
224 CASE_RETURN_1P(XXPhase3)
132
1/2
✓ Branch 4 taken 83 times.
✗ Branch 5 not taken.
196 CASE_RETURN_1P(ESWAP)
133 #undef CASE_RETURN_1P
134
1/2
✓ Branch 5 taken 217 times.
✗ Branch 6 not taken.
464 CASE_RETURN_2P(U2)
135
1/2
✓ Branch 5 taken 142 times.
✗ Branch 6 not taken.
314 CASE_RETURN_2P(PhasedX)
136
1/2
✓ Branch 5 taken 86 times.
✗ Branch 6 not taken.
202 CASE_RETURN_2P(PhasedISWAP)
137
1/2
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
206 CASE_RETURN_2P(FSim)
138 #undef CASE_RETURN_2P
139
1/2
✓ Branch 6 taken 2466 times.
✗ Branch 7 not taken.
4962 CASE_RETURN_3P(CU3)
140
1/2
✓ Branch 6 taken 8887 times.
✗ Branch 7 not taken.
17804 CASE_RETURN_3P(U3)
141
1/2
✓ Branch 6 taken 9240 times.
✗ Branch 7 not taken.
18510 CASE_RETURN_3P(TK1)
142
1/2
✓ Branch 6 taken 1356 times.
✗ Branch 7 not taken.
2742 CASE_RETURN_3P(TK2)
143 #undef CASE_RETURN_3P
144
1/1
✓ Decision 'true' taken 23 times.
23 default: {
145
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 std::stringstream ss;
146
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
46 ss << GateUnitaryMatrixUtils::get_error_prefix(
147 op_type, number_of_qubits, parameters)
148
2/4
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23 times.
✗ Branch 5 not taken.
23 << "unrecognised Op type";
149
2/4
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 23 times.
✗ Branch 6 not taken.
23 throw BadOpType(ss.str(), op_type);
150 23 }
151 }
152 }
153
154 // It's already been checked not to be one of the special cases
155 // having a variable number of qubits.
156 196507 static Eigen::MatrixXcd get_unitary_for_ordinary_fixed_size_case(
157 OpType op_type, unsigned number_of_qubits,
158 const std::vector<double>& parameters) {
159 const Eigen::MatrixXcd matr =
160
2/2
✓ Branch 1 taken 194954 times.
✓ Branch 2 taken 1553 times.
196507 get_unitary_or_throw(op_type, number_of_qubits, parameters);
161
162 TKET_ASSERT(matr.cols() == matr.rows());
163
1/2
✓ Branch 2 taken 194954 times.
✗ Branch 3 not taken.
194954 const auto expected_number_of_qubits = get_number_of_qubits(matr.cols());
164
2/2
✓ Branch 0 taken 194699 times.
✓ Branch 1 taken 255 times.
0/1
? Decision couldn't be analyzed.
194954 if (expected_number_of_qubits == number_of_qubits) {
165 389398 return matr;
166 }
167
1/2
✓ Branch 1 taken 255 times.
✗ Branch 2 not taken.
255 std::stringstream ss;
168
1/2
✓ Branch 1 taken 255 times.
✗ Branch 2 not taken.
510 ss << GateUnitaryMatrixUtils::get_error_prefix(
169 op_type, number_of_qubits, parameters)
170
4/8
✓ Branch 1 taken 255 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 255 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 255 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 255 times.
✗ Branch 11 not taken.
255 << "wrong number of qubits (expected " << expected_number_of_qubits << ")";
171
1/2
✓ Branch 1 taken 255 times.
✗ Branch 2 not taken.
255 throw GateUnitaryMatrixError(
172
1/2
✓ Branch 2 taken 255 times.
✗ Branch 3 not taken.
510 ss.str(), GateUnitaryMatrixError::Cause::INPUT_ERROR);
173 510 }
174
175 197293 Eigen::MatrixXcd GateUnitaryMatrix::get_unitary(
176 OpType op_type, unsigned number_of_qubits,
177 const std::vector<double>& parameters) {
178
1/2
✓ Branch 1 taken 197293 times.
✗ Branch 2 not taken.
197293 const internal::GateUnitaryMatrixVariableQubits variable_qubits_data(op_type);
179
3/4
✓ Branch 1 taken 197293 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 196507 times.
✓ Branch 4 taken 786 times.
2/2
✓ Decision 'true' taken 196507 times.
✓ Decision 'false' taken 786 times.
197293 if (!variable_qubits_data.is_known_type()) {
180 return get_unitary_for_ordinary_fixed_size_case(
181
2/2
✓ Branch 1 taken 194699 times.
✓ Branch 2 taken 1808 times.
196507 op_type, number_of_qubits, parameters);
182 }
183 const auto expected_number_of_parameters =
184
1/2
✓ Branch 1 taken 786 times.
✗ Branch 2 not taken.
786 variable_qubits_data.get_number_of_parameters();
185
2/2
✓ Branch 1 taken 396 times.
✓ Branch 2 taken 390 times.
2/2
✓ Decision 'true' taken 396 times.
✓ Decision 'false' taken 390 times.
786 if (parameters.size() == expected_number_of_parameters) {
186
2/2
✓ Branch 1 taken 388 times.
✓ Branch 2 taken 8 times.
396 return variable_qubits_data.get_dense_unitary(number_of_qubits, parameters);
187 }
188
1/2
✓ Branch 1 taken 390 times.
✗ Branch 2 not taken.
390 std::stringstream ss;
189
1/2
✓ Branch 1 taken 390 times.
✗ Branch 2 not taken.
780 ss << GateUnitaryMatrixUtils::get_error_prefix(
190 op_type, number_of_qubits, parameters)
191
3/6
✓ Branch 1 taken 390 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 390 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 390 times.
✗ Branch 8 not taken.
390 << "wrong number of parameters (expected " << expected_number_of_parameters
192
1/2
✓ Branch 1 taken 390 times.
✗ Branch 2 not taken.
390 << ")";
193
1/2
✓ Branch 1 taken 390 times.
✗ Branch 2 not taken.
390 throw GateUnitaryMatrixError(
194
1/2
✓ Branch 2 taken 390 times.
✗ Branch 3 not taken.
780 ss.str(), GateUnitaryMatrixError::Cause::INPUT_ERROR);
195 390 }
196
197 194374 Eigen::MatrixXcd GateUnitaryMatrix::get_unitary(const Gate& gate) {
198
1/2
✓ Branch 1 taken 194374 times.
✗ Branch 2 not taken.
194374 const auto parameters = GateUnitaryMatrixUtils::get_checked_parameters(gate);
199
3/4
✓ Branch 1 taken 194374 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 194371 times.
✓ Branch 6 taken 3 times.
388745 return get_unitary(gate.get_type(), gate.n_qubits(), parameters);
200 194374 }
201
202 191456 std::vector<TripletCd> GateUnitaryMatrix::get_unitary_triplets(
203 const Gate& gate, double abs_epsilon) {
204 auto triplets = internal::GateUnitarySparseMatrix::get_unitary_triplets(
205 191456 gate, abs_epsilon);
206
2/2
✓ Branch 1 taken 191262 times.
✓ Branch 2 taken 194 times.
2/2
✓ Decision 'true' taken 191262 times.
✓ Decision 'false' taken 194 times.
191456 if (triplets.empty()) {
207 // Not recognised as a specific sparse type, so just get the dense matrix
208
1/2
✓ Branch 1 taken 191262 times.
✗ Branch 2 not taken.
191262 const auto unitary_matr = get_unitary(gate);
209
1/2
✓ Branch 1 taken 191262 times.
✗ Branch 2 not taken.
191262 triplets = get_triplets(unitary_matr, abs_epsilon);
210 191262 }
211 191456 return triplets;
212 }
213
214 } // namespace tket
215