GCC Code Coverage Report


Directory: ./
File: Converters/UnitaryTableauConverters.cpp
Date: 2022-10-15 05:10:18
Warnings: 1 unchecked decisions!
Exec Total Coverage
Lines: 112 116 96.6%
Functions: 2 2 100.0%
Branches: 173 306 56.5%
Decisions: 40 50 80.0%

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 <stdexcept>
16
17 #include "Converters.hpp"
18
19 namespace tket {
20
21 13 UnitaryTableau circuit_to_unitary_tableau(const Circuit& circ) {
22
1/2
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
13 UnitaryTableau tab(circ.all_qubits());
23
6/10
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 125 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 124 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 125 times.
✓ Branch 14 taken 12 times.
0/1
? Decision couldn't be analyzed.
137 for (const Command& com : circ) {
24
1/2
✓ Branch 1 taken 125 times.
✗ Branch 2 not taken.
125 auto args = com.get_args();
25
1/2
✓ Branch 4 taken 125 times.
✗ Branch 5 not taken.
125 qubit_vector_t qbs = {args.begin(), args.end()};
26
2/2
✓ Branch 4 taken 124 times.
✓ Branch 5 taken 1 times.
126 tab.apply_gate_at_end(com.get_op_ptr()->get_type(), qbs);
27 141 }
28 12 return tab;
29 1 }
30
31 4 Circuit unitary_tableau_to_circuit(const UnitaryTableau& tab) {
32
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 SymplecticTableau tabl(tab.tab_);
33
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 unsigned size = tabl.get_n_qubits();
34
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 Circuit c(size);
35 /*
36 * Aaronson-Gottesman: Improved Simulation of Stabilizer Circuits, Theorem 8
37 * Any unitary stabilizer circuit has an equivalent circuit in canonical form
38 * (H-C-P-C-P-C-H-P-C-P-C).
39 * Produces a circuit realising the tableau, but consumes the tableau in the
40 * process.
41 */
42
43 /*
44 * Step 1: Use Hadamards (in our case, Vs) to make C (z rows of xmat_) have
45 * full rank
46 */
47
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 MatrixXb echelon = tabl.xmat_.block(size, 0, size, size);
48 4 std::map<unsigned, unsigned> leading_val_to_col;
49
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
2/2
✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 4 times.
16 for (unsigned i = 0; i < size; i++) {
50
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 8 times.
2/2
✓ Decision 'true' taken 30 times.
✓ Decision 'false' taken 8 times.
38 for (unsigned j = 0; j < size; j++) {
51
3/4
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 22 times.
2/2
✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 22 times.
30 if (echelon(j, i)) {
52
3/4
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 4 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 4 times.
8 if (leading_val_to_col.find(j) == leading_val_to_col.end()) {
53
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 leading_val_to_col.insert({j, i});
54 4 break;
55 } else {
56
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 unsigned l = leading_val_to_col.at(j);
57
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
2/2
✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 4 times.
16 for (unsigned k = 0; k < size; k++) {
58
2/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
12 echelon(k, i) ^= echelon(k, l);
59 }
60 }
61 }
62 }
63
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 8 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 8 times.
12 if (leading_val_to_col.size() > i)
64 4 continue; // Independent of previous cols
65
2/4
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
8 c.add_op<unsigned>(OpType::V, {i});
66
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 tabl.apply_V(i);
67
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 tabl.apply_V(i);
68
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 tabl.apply_V(i);
69
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 echelon.col(i) = tabl.zmat_.block(size, i, size, 1);
70
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 18 times.
✗ Decision 'false' not taken.
18 for (unsigned j = 0; j < size; j++) {
71
3/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 10 times.
2/2
✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 10 times.
18 if (echelon(j, i)) {
72
2/4
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
1/2
✓ Decision 'true' taken 8 times.
✗ Decision 'false' not taken.
8 if (leading_val_to_col.find(j) == leading_val_to_col.end()) {
73
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 leading_val_to_col.insert({j, i});
74 8 break;
75 } else {
76 unsigned l = leading_val_to_col.at(j);
77
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
for (unsigned k = 0; k < size; k++) {
78 echelon(k, i) ^= echelon(k, l);
79 }
80 }
81 }
82 }
83
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 8 times.
8 if (leading_val_to_col.size() == i)
84 throw std::invalid_argument("Stabilisers are not mutually independent");
85 }
86
87 /*
88 * Step 2: Use CXs to perform Gaussian elimination on C (zpauli_x), producing
89 * / A B \
90 * \ I D /
91 */
92
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 MatrixXb to_reduce = tabl.xmat_.block(size, 0, size, size);
93 4 for (const std::pair<unsigned, unsigned>& qbs :
94
3/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 18 times.
✓ Branch 9 taken 4 times.
26 gaussian_elimination_col_ops(to_reduce)) {
95
2/4
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
18 c.add_op<unsigned>(OpType::CX, {qbs.first, qbs.second});
96
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 tabl.apply_CX(qbs.first, qbs.second);
97 4 }
98
99 /*
100 * Step 3: Commutativity of the stabilizer implies that ID^T is symmetric,
101 * therefore D is symmetric, and we can apply phase (S) gates to add a
102 * diagonal matrix to D and use Lemma 7 to convert D to the form D = MM^T
103 * for some invertible M.
104 */
105 std::pair<MatrixXb, MatrixXb> zp_z_llt =
106
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
4 binary_LLT_decomposition(tabl.zmat_.block(size, 0, size, size));
107
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
2/2
✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 4 times.
16 for (unsigned i = 0; i < size; i++) {
108
3/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 10 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 10 times.
12 if (zp_z_llt.second(i, i)) {
109
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 c.add_op<unsigned>(OpType::S, {i});
110
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 tabl.apply_S(i);
111
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 tabl.apply_S(i);
112
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 tabl.apply_S(i);
113 }
114 }
115
116 /*
117 * Step 4: Use CXs to produce
118 * / A B \
119 * \ M M /
120 * Note that when we map I to IM, we also map D to D(M^T)^{-1} = M.
121 */
122 std::vector<std::pair<unsigned, unsigned>> m_to_i =
123
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 gaussian_elimination_col_ops(zp_z_llt.first);
124
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
1/2
✓ Decision 'true' taken 6 times.
✗ Decision 'false' not taken.
10 for (std::vector<std::pair<unsigned, unsigned>>::reverse_iterator it =
125 4 m_to_i.rbegin();
126
3/4
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 4 times.
10 it != m_to_i.rend(); it++) {
127
4/8
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
6 c.add_op<unsigned>(OpType::CX, {it->first, it->second});
128
3/6
✓ 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.
6 tabl.apply_CX(it->first, it->second);
129 }
130
131 /*
132 * Step 5: Apply phases to all n qubits to obtain
133 * / A B \
134 * \ M 0 /
135 * Since M is full rank, there exists some subset S of qubits such that
136 * applying two phases in succession (Z) to every a \in S will preserve
137 * the tableau, but set r_{n+1} = ... = r_{2n} = 0 (zpauli_phase = 0^n).
138 * Apply two phases (Z) to every a \in S. DELAYED UNTIL END
139 */
140
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
2/2
✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 4 times.
16 for (unsigned i = 0; i < size; i++) {
141
2/4
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
12 c.add_op<unsigned>(OpType::S, {i});
142
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 tabl.apply_S(i);
143
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 tabl.apply_S(i);
144
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 tabl.apply_S(i);
145 }
146
147 /*
148 * Step 6: Use CXs to perform Gaussian elimination on M, producing
149 * / A B \
150 * \ I 0 /
151 * By commutativity relations, IB^T = A0^T + I, therefore B = I.
152 */
153
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 to_reduce = tabl.xmat_.block(size, 0, size, size);
154 4 for (const std::pair<unsigned, unsigned>& qbs :
155
3/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 4 times.
14 gaussian_elimination_col_ops(to_reduce)) {
156
2/4
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
6 c.add_op<unsigned>(OpType::CX, {qbs.first, qbs.second});
157
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 tabl.apply_CX(qbs.first, qbs.second);
158 4 }
159
160 /*
161 * Step 7: Use Hadamards to produce
162 * / I A \
163 * \ 0 I /
164 */
165
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
2/2
✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 4 times.
16 for (unsigned i = 0; i < size; i++) {
166
2/4
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
12 c.add_op<unsigned>(OpType::H, {i});
167
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 tabl.apply_S(i);
168
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 tabl.apply_V(i);
169
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 tabl.apply_S(i);
170 }
171
172 /*
173 * Step 8: Now commutativity of the destabilizer implies that A is symmetric,
174 * therefore we can again use phase (S) gates and Lemma 7 to make A = NN^T for
175 * some invertible N.
176 */
177 std::pair<MatrixXb, MatrixXb> xp_z_llt =
178
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
4 binary_LLT_decomposition(tabl.zmat_.block(0, 0, size, size));
179
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
2/2
✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 4 times.
16 for (unsigned i = 0; i < size; i++) {
180
3/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 8 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 8 times.
12 if (xp_z_llt.second(i, i)) {
181
2/4
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
4 c.add_op<unsigned>(OpType::S, {i});
182
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 tabl.apply_S(i);
183
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 tabl.apply_S(i);
184
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 tabl.apply_S(i);
185 }
186 }
187
188 /*
189 * Step 9: Use CXs to produce
190 * / N N \
191 * \ 0 C /
192 */
193 std::vector<std::pair<unsigned, unsigned>> n_to_i =
194
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 gaussian_elimination_col_ops(xp_z_llt.first);
195
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
1/2
✓ Decision 'true' taken 2 times.
✗ Decision 'false' not taken.
6 for (std::vector<std::pair<unsigned, unsigned>>::reverse_iterator it =
196 4 n_to_i.rbegin();
197
3/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 4 times.
6 it != n_to_i.rend(); it++) {
198
4/8
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
2 c.add_op<unsigned>(OpType::CX, {it->first, it->second});
199
3/6
✓ 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.
2 tabl.apply_CX(it->first, it->second);
200 }
201
202 /*
203 * Step 10: Use phases (S) to produce
204 * / N 0 \
205 * \ 0 C /
206 * then by commutativity relations NC^T = I. Next apply two phases (Z) each to
207 * some subset of qubits in order to preserve the above tableau, but set
208 * r_1 = ... = r_n = 0 (xpauli_phase = 0^n). DELAYED UNTIL END
209 */
210
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
2/2
✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 4 times.
16 for (unsigned i = 0; i < size; i++) {
211
2/4
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
12 c.add_op<unsigned>(OpType::S, {i});
212
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 tabl.apply_S(i);
213
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 tabl.apply_S(i);
214
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 tabl.apply_S(i);
215 }
216
217 /*
218 * Step 11: Use CXs to produce
219 * / I 0 \
220 * \ 0 I /
221 */
222 4 for (const std::pair<unsigned, unsigned>& qbs :
223
5/8
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 15 taken 2 times.
✓ Branch 16 taken 4 times.
10 gaussian_elimination_col_ops(tabl.xmat_.block(0, 0, size, size))) {
224
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 c.add_op<unsigned>(OpType::CX, {qbs.first, qbs.second});
225
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 tabl.apply_CX(qbs.first, qbs.second);
226 4 }
227
228 /*
229 * DELAYED STEPS: Set all phases to 0 by applying Z or X gates
230 */
231
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
2/2
✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 4 times.
16 for (unsigned i = 0; i < size; i++) {
232
3/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 5 times.
2/2
✓ Decision 'true' taken 7 times.
✓ Decision 'false' taken 5 times.
12 if (tabl.phase_(i)) {
233
2/4
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
7 c.add_op<unsigned>(OpType::Z, {i});
234
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 tabl.apply_S(i);
235
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 tabl.apply_S(i);
236 }
237
3/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 10 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 10 times.
12 if (tabl.phase_(i + size)) {
238
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 c.add_op<unsigned>(OpType::X, {i});
239
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 tabl.apply_V(i);
240
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 tabl.apply_V(i);
241 }
242 }
243
244 /*
245 * Rename qubits
246 */
247 4 unit_map_t rename_map;
248
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
1/2
✓ Decision 'true' taken 4 times.
✗ Decision 'false' not taken.
8 for (boost::bimap<Qubit, unsigned>::const_iterator iter = tab.qubits_.begin(),
249
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 iend = tab.qubits_.end();
250
3/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 4 times.
16 iter != iend; ++iter) {
251
5/10
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 16 taken 12 times.
✗ Branch 17 not taken.
12 rename_map.insert({Qubit(iter->right), iter->left});
252 }
253
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 c.rename_units(rename_map);
254
255
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 return c.transpose();
256 4 }
257
258 } // namespace tket
259