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 |