GCC Code Coverage Report


Directory: ./
File: Transformations/PauliOptimisation.cpp
Date: 2022-10-15 05:10:18
Warnings: 3 unchecked decisions!
Exec Total Coverage
Lines: 152 157 96.8%
Functions: 6 6 100.0%
Branches: 189 337 56.1%
Decisions: 29 38 76.3%

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 "PauliOptimisation.hpp"
16
17 #include "Converters/Converters.hpp"
18 #include "Converters/PauliGadget.hpp"
19 #include "Decomposition.hpp"
20 #include "OpType/OpType.hpp"
21 #include "OpType/OpTypeInfo.hpp"
22 #include "Ops/Op.hpp"
23 #include "OptimisationPass.hpp"
24 #include "PauliGraph/PauliGraph.hpp"
25 #include "Transform.hpp"
26
27 namespace tket {
28
29 namespace Transforms {
30
31 13 Transform pairwise_pauli_gadgets(CXConfigType cx_config) {
32 12 return Transform([=](Circuit &circ) {
33
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 Expr t = circ.get_phase();
34
7/8
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 256 times.
✓ Branch 6 taken 11 times.
✓ Branch 8 taken 256 times.
✓ Branch 9 taken 11 times.
✓ Branch 11 taken 12 times.
✓ Branch 12 taken 11 times.
278 BGL_FORALL_VERTICES(v, circ.dag, DAG) {
35
1/2
✓ Branch 1 taken 256 times.
✗ Branch 2 not taken.
256 Op_ptr op = circ.get_Op_ptr_from_Vertex(v);
36 256 OpType optype = op->get_type();
37
3/4
✓ Branch 1 taken 256 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 250 times.
2/2
✓ Decision 'true' taken 250 times.
✓ Decision 'false' taken 6 times.
256 if (is_boundary_c_type(optype)) continue;
38
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 249 times.
2/2
✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 249 times.
250 if (optype == OpType::Conditional)
39
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 throw CircuitInvalidity(
40 "Cannot currently do `pauli_gadgets` optimisation on a "
41 2 "circuit with conditional gates");
42
3/6
✓ Branch 2 taken 249 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 249 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 249 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 249 times.
249 if (op->get_desc().is_box())
43 throw CircuitInvalidity(
44 "Cannot currently do `pauli_gadgets` optimisation on a "
45 "circuit with boxes");
46
3/4
✓ Branch 0 taken 248 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 248 times.
2/2
✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 248 times.
249 if (optype == OpType::Measure || optype == OpType::Collapse) {
47
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 VertexVec q_suc = circ.get_successors_of_type(v, EdgeType::Quantum);
48
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 2 times.
2 if (q_suc.size() != 1 ||
49
3/6
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 !is_final_q_type(circ.get_OpType_from_Vertex(q_suc[0])))
50 throw CircuitInvalidity(
51 "Cannot currently do `pauli_gadgets` optimisation "
52 "on a circuit with a measure in the middle of the "
53 "circuit");
54 1 }
55
2/2
✓ Branch 1 taken 249 times.
✓ Branch 2 taken 6 times.
256 }
56
3/6
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
22 Transform setup = decompose_multi_qubits_CX() >> decompose_ZX() >>
57
2/4
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
22 decompose_ZX_to_cliffords();
58
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 setup.apply(circ);
59 // We effectively commute non-Clifford rotations to the front of the circuit
60 // This gives a sequence of just Pauli gadgets (gadget_circ), followed by
61 // all of the Clifford operations (clifford_circ)
62 11 std::vector<std::pair<QubitPauliTensor, Expr>> pauli_gadgets;
63 // rx_pauli[i] specifies which Pauli gadget would be built by applying an Rx
64 // rotation on qubit i and then pushing it through the Cliffords to the
65 // front of the circuit. Likewise for rz_pauli with Rz rotations. Clifford
66 // operations will update these and non-Clifford rotations will introduce
67 // Pauli gadgets accordingly
68
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 Circuit gadget_circ;
69
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 Circuit clifford_circ;
70 11 std::map<Qubit, QubitPauliTensor> rx_pauli;
71 11 std::map<Qubit, QubitPauliTensor> rz_pauli;
72
3/4
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 33 times.
✓ Branch 8 taken 11 times.
0/1
? Decision couldn't be analyzed.
44 for (const Qubit &qb : circ.all_qubits()) {
73
1/2
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
33 gadget_circ.add_qubit(qb);
74
1/2
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
33 clifford_circ.add_qubit(qb);
75
2/4
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 33 times.
✗ Branch 6 not taken.
33 rx_pauli.insert({qb, QubitPauliTensor(qb, Pauli::X)});
76
2/4
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 33 times.
✗ Branch 6 not taken.
33 rz_pauli.insert({qb, QubitPauliTensor(qb, Pauli::Z)});
77 11 }
78
3/4
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 11 times.
0/1
? Decision couldn't be analyzed.
13 for (const Bit &cb : circ.all_bits()) {
79
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 gadget_circ.add_bit(cb);
80
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 clifford_circ.add_bit(cb);
81 11 }
82 // Identify Pauli Gadgets and build Clifford circuit
83
6/10
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 228 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 227 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 228 times.
✓ Branch 14 taken 10 times.
0/1
? Decision couldn't be analyzed.
238 for (const Command &c : circ) {
84 228 const Op_ptr op_ptr = c.get_op_ptr();
85
1/2
✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
228 unit_vector_t args = c.get_args();
86 228 OpType type = op_ptr->get_type();
87
11/11
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 28 times.
✓ Branch 6 taken 68 times.
✓ Branch 7 taken 14 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
228 switch (type) {
88 // Update rx_pauli and rz_pauli
89
1/1
✓ Decision 'true' taken 54 times.
54 case OpType::S: {
90
1/2
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
54 Qubit q(args[0]);
91
5/10
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 54 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 54 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 54 times.
✗ Branch 14 not taken.
54 rx_pauli[q] = i_ * rz_pauli[q] * rx_pauli[q];
92 54 break;
93 54 }
94
1/1
✓ Decision 'true' taken 55 times.
55 case OpType::V: {
95
1/2
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
55 Qubit q(args[0]);
96
5/10
✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 55 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 55 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 55 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 55 times.
✗ Branch 14 not taken.
55 rz_pauli[q] = i_ * rx_pauli[q] * rz_pauli[q];
97 55 break;
98 55 }
99
1/1
✓ Decision 'true' taken 2 times.
2 case OpType::Z: {
100
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 Qubit q(args[0]);
101
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
2 rx_pauli[q] = -1. * rx_pauli[q];
102 2 break;
103 2 }
104
1/1
✓ Decision 'true' taken 2 times.
2 case OpType::X: {
105
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 Qubit q(args[0]);
106
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
2 rz_pauli[q] = -1. * rz_pauli[q];
107 2 break;
108 2 }
109
1/1
✓ Decision 'true' taken 1 times.
1 case OpType::Sdg: {
110
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 Qubit q(args[0]);
111
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
1 rx_pauli[q] = -i_ * rz_pauli[q] * rx_pauli[q];
112 1 break;
113 1 }
114
1/1
✓ Decision 'true' taken 28 times.
28 case OpType::Vdg: {
115
1/2
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
28 Qubit q(args[0]);
116
5/10
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 28 times.
✗ Branch 15 not taken.
28 rz_pauli[q] = -i_ * rx_pauli[q] * rz_pauli[q];
117 28 break;
118 28 }
119
1/1
✓ Decision 'true' taken 68 times.
68 case OpType::CX: {
120
1/2
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
68 Qubit q_ctrl(args[0]);
121
1/2
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
68 Qubit q_trgt(args[1]);
122
4/8
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 68 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 68 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 68 times.
✗ Branch 11 not taken.
68 rx_pauli[q_ctrl] = rx_pauli[q_ctrl] * rx_pauli[q_trgt];
123
4/8
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 68 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 68 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 68 times.
✗ Branch 11 not taken.
68 rz_pauli[q_trgt] = rz_pauli[q_ctrl] * rz_pauli[q_trgt];
124 68 break;
125 68 }
126 // Introduce a Pauli gadget
127
1/1
✓ Decision 'true' taken 14 times.
14 case OpType::Rz: {
128
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 Qubit q(args[0]);
129
2/4
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
14 Expr angle = (op_ptr)->get_params()[0];
130
3/6
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
14 pauli_gadgets.push_back({rz_pauli[q], angle});
131 14 break;
132 14 }
133
1/1
✓ Decision 'true' taken 2 times.
2 case OpType::Rx: {
134
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 Qubit q(args[0]);
135
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 Expr angle = (op_ptr)->get_params()[0];
136
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 pauli_gadgets.push_back({rx_pauli[q], angle});
137 2 break;
138 2 }
139 1 case OpType::noop:
140 case OpType::Phase:
141 case OpType::Measure:
142 case OpType::Collapse:
143 case OpType::Reset:
144 1 break;
145 1 default: {
146 std::string error_gate =
147 "Cannot perform pairwise Pauli gadget optimisation using: " +
148
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 op_ptr->get_name();
149
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 throw BadOpType(error_gate, type);
150 1 }
151 }
152 // Add Clifford gates to the back of the circuit to recreate the final
153 // combination at the outputs
154
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 211 times.
227 switch (type) {
155 16 case OpType::Rz:
156 case OpType::Rx: {
157 16 break;
158 }
159
1/1
✓ Decision 'true' taken 211 times.
211 default: {
160
1/2
✓ Branch 2 taken 211 times.
✗ Branch 3 not taken.
211 clifford_circ.add_op(op_ptr, args);
161 }
162 }
163 242 }
164 // Synthesise pairs of Pauli Gadgets
165 10 unsigned g = 0;
166
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 10 times.
2/2
✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 10 times.
16 while (g + 1 < pauli_gadgets.size()) {
167
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 auto [pauli0, angle0] = pauli_gadgets[g];
168
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 auto [pauli1, angle1] = pauli_gadgets[g + 1];
169
4/8
✓ 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.
6 append_pauli_gadget_pair(
170
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 gadget_circ, pauli0, angle0, pauli1, angle1, cx_config);
171 6 g += 2;
172 6 }
173 // As we synthesised Pauli gadgets 2 at a time, if there were an odd
174 // number, we will have one left over, so add that one on its own
175
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 6 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 6 times.
10 if (g < pauli_gadgets.size()) {
176
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 auto [pauli, angle] = pauli_gadgets[g];
177
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 append_single_pauli_gadget(gadget_circ, pauli, angle, cx_config);
178 4 }
179 // Stitch gadget circuit and Clifford circuit together
180
2/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
10 circ = gadget_circ >> clifford_circ;
181
2/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
10 circ.add_phase(t);
182
2/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
10 clifford_simp().apply(circ);
183 10 return true;
184
1/2
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
31 });
185 }
186
187 26 Transform synthesise_pauli_graph(
188 PauliSynthStrat strat, CXConfigType cx_config) {
189 23 return Transform([=](Circuit &circ) {
190
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 Expr t = circ.get_phase();
191
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 PauliGraph pg = circuit_to_pauli_graph(circ);
192
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
23 switch (strat) {
193
1/1
✓ Decision 'true' taken 4 times.
4 case PauliSynthStrat::Individual: {
194
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 circ = pauli_graph_to_circuit_individually(pg, cx_config);
195 4 break;
196 }
197
1/1
✓ Decision 'true' taken 4 times.
4 case PauliSynthStrat::Pairwise: {
198
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 circ = pauli_graph_to_circuit_pairwise(pg, cx_config);
199 4 break;
200 }
201
1/1
✓ Decision 'true' taken 15 times.
15 case PauliSynthStrat::Sets: {
202
2/4
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
15 circ = pauli_graph_to_circuit_sets(pg, cx_config);
203 15 break;
204 }
205
0/1
✗ Decision 'true' not taken.
default:
206 TKET_ASSERT(!"Unknown Pauli Synthesis Strategy");
207 }
208
2/4
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23 times.
✗ Branch 5 not taken.
23 circ.add_phase(t);
209 // always turn circuit into PauliGraph and back, so always return true
210 23 return true;
211
1/2
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
49 });
212 }
213
214 6 Transform special_UCC_synthesis(PauliSynthStrat strat, CXConfigType cx_config) {
215 5 return Transform([=](Circuit &circ) {
216
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 Transform synther = synthesise_pauli_graph(strat, cx_config);
217 // make list so we don't run into unboxing vertex issues
218 5 std::list<Vertex> circbox_verts;
219
7/8
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 105 times.
✓ Branch 6 taken 5 times.
✓ Branch 8 taken 105 times.
✓ Branch 9 taken 5 times.
✓ Branch 11 taken 5 times.
✓ Branch 12 taken 5 times.
115 BGL_FORALL_VERTICES(v, circ.dag, DAG) {
220
3/4
✓ Branch 1 taken 105 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 102 times.
2/2
✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 102 times.
105 if (circ.get_OpType_from_Vertex(v) == OpType::CircBox)
221
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 circbox_verts.push_back(v);
222 }
223
2/2
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 5 times.
2/2
✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 5 times.
8 for (Vertex v : circbox_verts) {
224
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 const Op_ptr op = circ.get_Op_ptr_from_Vertex(v);
225 std::shared_ptr<const CircBox> box_ptr =
226 3 std::dynamic_pointer_cast<const CircBox>(op);
227
2/4
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
3 Circuit inner_circ = *(box_ptr->to_circuit());
228
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 synther.apply(inner_circ);
229
4/8
✓ 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.
6 Subcircuit sub = {circ.get_in_edges(v), circ.get_all_out_edges(v), {v}};
230
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 circ.substitute(inner_circ, sub);
231 3 }
232 return !circbox_verts
233 10 .empty(); // always true if we have left Circuit formalism
234
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
11 });
235 }
236
237 } // namespace Transforms
238
239 } // namespace tket
240