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 "CliffordOptimisation.hpp" | |||
16 | ||||
17 | #include <vector> | |||
18 | ||||
19 | #include "BasicOptimisation.hpp" | |||
20 | #include "Circuit/CircPool.hpp" | |||
21 | #include "Circuit/DAGDefs.hpp" | |||
22 | #include "Decomposition.hpp" | |||
23 | #include "Transform.hpp" | |||
24 | ||||
25 | namespace tket { | |||
26 | ||||
27 | namespace Transforms { | |||
28 | ||||
29 | static bool multiq_clifford_match(Circuit &circ, bool allow_swaps); | |||
30 | static bool copy_pi_through_CX_method(Circuit &circ); | |||
31 | ||||
32 | 16 | Transform multiq_clifford_replacement(bool allow_swaps) { | ||
33 | 16 | return Transform([allow_swaps](Circuit &circ) { | ||
34 | 16 | return multiq_clifford_match(circ, allow_swaps); | ||
35 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | }); | |
36 | } | |||
37 | ||||
38 | 16 | static bool multiq_clifford_match(Circuit &circ, bool allow_swaps) { | ||
39 | 16 | bool success = false; | ||
40 | // map from vertex/port to qubit number | |||
41 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | std::map<Vertex, unit_set_t> v_to_qb = circ.vertex_unit_map(); | |
42 | // map from vertex to its depth from slices/reverse_slices | |||
43 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | std::map<Vertex, unsigned> v_to_depth = circ.vertex_depth_map(); | |
44 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | std::map<Vertex, unsigned> v_to_rev_depth = circ.vertex_rev_depth_map(); | |
45 | // Analysis complete, we can now go through and actually do the transformation | |||
46 | 16 | VertexList bin; | ||
47 |
7/8✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 313 times.
✓ Branch 6 taken 16 times.
✓ Branch 8 taken 313 times.
✓ Branch 9 taken 16 times.
✓ Branch 11 taken 16 times.
✓ Branch 12 taken 16 times.
|
345 | BGL_FORALL_VERTICES(v, circ.dag, DAG) { | |
48 |
5/6✓ Branch 1 taken 313 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 76 times.
✓ Branch 4 taken 237 times.
✓ Branch 5 taken 56 times.
✓ Branch 6 taken 257 times.
|
2/2✓ Decision 'true' taken 56 times.
✓ Decision 'false' taken 333 times.
|
389 | if (circ.get_OpType_from_Vertex(v) == OpType::CX && |
49 |
3/4✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 56 times.
✓ Branch 4 taken 20 times.
|
76 | circ.n_out_edges(v) == 2) { | |
50 | // Walk to next CX on the same pair | |||
51 |
2/4✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
|
56 | unit_set_t cx_units = v_to_qb.at(v); | |
52 |
1/2✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
|
56 | qubit_vector_t qbs(cx_units.begin(), cx_units.end()); | |
53 | 56 | QPathDetailed path0; | ||
54 | 56 | QPathDetailed path1; | ||
55 | 56 | bool found_cnot = false; | ||
56 |
1/2✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 | Edge e0 = circ.get_nth_out_edge(v, 0); | |
57 |
1/2✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 | Vertex v0 = circ.target(e0); | |
58 |
1/2✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 | port_t port = circ.get_target_port(e0); | |
59 | while (true) { | |||
60 |
1/2✓ Branch 1 taken 135 times.
✗ Branch 2 not taken.
|
135 | OpType v_type = circ.get_OpType_from_Vertex(v0); | |
61 |
3/4✓ Branch 1 taken 135 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 108 times.
|
2/2✓ Decision 'true' taken 27 times.
✓ Decision 'false' taken 108 times.
|
135 | if (is_final_q_type(v_type)) { |
62 | 27 | break; | ||
63 |
8/10✓ Branch 0 taken 44 times.
✓ Branch 1 taken 64 times.
✓ Branch 3 taken 44 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 44 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 29 times.
✓ Branch 9 taken 15 times.
✓ Branch 10 taken 29 times.
✓ Branch 11 taken 79 times.
|
2/2✓ Decision 'true' taken 29 times.
✓ Decision 'false' taken 79 times.
|
108 | } else if (v_type == OpType::CX && v_to_qb.at(v0) == cx_units) { |
64 | 29 | found_cnot = true; | ||
65 | 29 | break; | ||
66 | } | |||
67 |
1/2✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
|
79 | path0.push_back({v0, port}); | |
68 |
1/2✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
|
79 | e0 = circ.get_next_edge(v0, e0); | |
69 |
1/2✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
|
79 | v0 = circ.target(e0); | |
70 |
1/2✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
|
79 | port = circ.get_target_port(e0); | |
71 | 79 | } | ||
72 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 29 times.
|
2/2✓ Decision 'true' taken 27 times.
✓ Decision 'false' taken 29 times.
|
56 | if (!found_cnot) { |
73 | 27 | continue; | ||
74 | } | |||
75 |
1/2✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
|
29 | Edge e1 = circ.get_nth_out_edge(v, 1); | |
76 |
1/2✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
|
29 | Vertex v1 = circ.target(e1); | |
77 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 29 times.
|
2/2✓ Decision 'true' taken 55 times.
✓ Decision 'false' taken 29 times.
|
84 | while (v1 != v0) { |
78 |
2/4✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 55 times.
✗ Branch 6 not taken.
|
55 | path1.push_back({v1, circ.get_target_port(e1)}); | |
79 |
1/2✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
|
55 | e1 = circ.get_next_edge(v1, e1); | |
80 |
1/2✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
|
55 | v1 = circ.target(e1); | |
81 | } | |||
82 | 29 | unsigned path0_length = path0.size(); | ||
83 | 29 | unsigned path1_length = path1.size(); | ||
84 | 29 | unsigned front0_index = 0; | ||
85 | 29 | unsigned front1_index = 0; | ||
86 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 11 times.
|
2/2✓ Decision 'true' taken 22 times.
✓ Decision 'false' taken 11 times.
|
55 | while (front0_index < path0_length && |
87 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 18 times.
|
22 | circ.commutes_with_basis( | |
88 |
3/4✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 29 times.
|
55 | path0[front0_index].first, Pauli::Z, PortType::Target, | |
89 | 22 | path0[front0_index].second)) { | ||
90 | 4 | front0_index++; | ||
91 | } | |||
92 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 12 times.
|
2/2✓ Decision 'true' taken 26 times.
✓ Decision 'false' taken 12 times.
|
64 | while (front1_index < path1_length && |
93 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 17 times.
|
26 | circ.commutes_with_basis( | |
94 |
3/4✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✓ Branch 6 taken 29 times.
|
64 | path1[front1_index].first, Pauli::X, PortType::Target, | |
95 | 26 | path1[front1_index].second)) { | ||
96 | 9 | front1_index++; | ||
97 | } | |||
98 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 15 times.
|
2/2✓ Decision 'true' taken 14 times.
✓ Decision 'false' taken 15 times.
|
29 | if (port == 0) { |
99 | // CXs have same orientation | |||
100 | // We walk back from the end of the path | |||
101 | // unsigned is used as this is semantically an index and the check for | |||
102 | // -1 functions the same as if it were signed | |||
103 | 14 | unsigned back0_index = path0_length - 1; | ||
104 |
4/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 7 times.
|
0/1? Decision couldn't be analyzed.
|
21 | while (back0_index != front0_index && back0_index != (unsigned)-1 && |
105 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | circ.commutes_with_basis( | |
106 |
3/4✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 14 times.
|
21 | path0[back0_index].first, Pauli::Z, PortType::Target, | |
107 | 4 | path0[back0_index].second)) { | ||
108 | 3 | back0_index--; | ||
109 | } | |||
110 | 14 | unsigned back1_index = path1_length - 1; | ||
111 |
4/4✓ Branch 0 taken 16 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 7 times.
|
0/1? Decision couldn't be analyzed.
|
30 | while (back1_index != front1_index && back1_index != (unsigned)-1 && |
112 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
|
9 | circ.commutes_with_basis( | |
113 |
3/4✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 14 times.
|
30 | path1[back1_index].first, Pauli::X, PortType::Target, | |
114 | 9 | path1[back1_index].second)) { | ||
115 | 7 | back1_index--; | ||
116 | } | |||
117 | // Check for valid causal ordering | |||
118 | Vertex front0pre = | |||
119 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13 times.
|
14 | (front0_index == 0) ? v : path0[front0_index - 1].first; | |
120 | Vertex front0post = | |||
121 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | (front0_index == path0_length) ? v0 : path0[front0_index].first; | |
122 | Vertex front1pre = | |||
123 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10 times.
|
14 | (front1_index == 0) ? v : path1[front1_index - 1].first; | |
124 | Vertex front1post = | |||
125 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | (front1_index == path1_length) ? v0 : path1[front1_index].first; | |
126 | Vertex back0pre = | |||
127 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | (back0_index == (unsigned)-1) ? v : path0[back0_index].first; | |
128 | 14 | Vertex back0post = (back0_index == path0_length - 1) | ||
129 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
|
16 | ? v0 | |
130 | 2 | : path0[back0_index + 1].first; | ||
131 | Vertex back1pre = | |||
132 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | (back1_index == (unsigned)-1) ? v : path1[back1_index].first; | |
133 | 14 | Vertex back1post = (back1_index == path1_length - 1) | ||
134 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10 times.
|
18 | ? v0 | |
135 | 4 | : path1[back1_index + 1].first; | ||
136 |
3/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 13 times.
|
14 | if (circ.in_causal_order( | |
137 | front1pre, front0post, true, v_to_depth, v_to_qb)) | |||
138 | 4 | continue; | ||
139 |
2/4✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
|
13 | if (circ.in_causal_order( | |
140 | front0pre, front1post, true, v_to_depth, v_to_qb)) | |||
141 | ✗ | continue; | ||
142 |
2/4✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
|
13 | if (circ.in_causal_order( | |
143 | back1post, back0pre, false, v_to_rev_depth, v_to_qb)) | |||
144 | ✗ | continue; | ||
145 |
3/4✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 12 times.
|
13 | if (circ.in_causal_order( | |
146 | back0post, back1pre, false, v_to_rev_depth, v_to_qb)) | |||
147 | 1 | continue; | ||
148 | // Identify which pattern to replace | |||
149 | 12 | bool v_on_q0 = false; | ||
150 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
|
12 | if (front0_index != path0_length) { | |
151 |
2/4✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
|
5 | if (circ.get_OpType_from_Vertex(path0[front0_index].first) != | |
152 | OpType::V) { | |||
153 | // The only non-empty pattern we can recognise is from a V | |||
154 | ✗ | continue; | ||
155 | } | |||
156 | 5 | v_on_q0 = true; | ||
157 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (back0_index != front0_index) { | |
158 | // There are some ops after the V that we cannot commute past the CX | |||
159 | ✗ | continue; | ||
160 | } | |||
161 | } | |||
162 | 12 | bool s_on_q1 = false; | ||
163 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | if (front1_index != path1_length) { | |
164 |
3/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 5 times.
|
6 | if (circ.get_OpType_from_Vertex(path1[front1_index].first) != | |
165 | OpType::S) { | |||
166 | // The only non-empty pattern we can recognise is from a S | |||
167 | 1 | continue; | ||
168 | } | |||
169 | 5 | s_on_q1 = true; | ||
170 | 11 | if (back1_index == front1_index + 2 && | ||
171 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | circ.get_OpType_from_Vertex(path1[front1_index + 1].first) == | |
172 |
4/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
|
6 | OpType::V && | |
173 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | circ.get_OpType_from_Vertex(path1[front1_index + 2].first) == | |
174 | OpType::S) { | |||
175 | /* --C-- ... --C-- --C-- ... --C-- */ | |||
176 | /* | | => | | */ | |||
177 | /* --X--S--V--S--X-- --X--V--S--V--X-- */ | |||
178 |
3/6✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
1 | circ.dag[path1[front1_index].first] = {get_op_ptr(OpType::V)}; | |
179 |
3/6✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
1 | circ.dag[path1[front1_index + 1].first] = {get_op_ptr(OpType::S)}; | |
180 |
3/6✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
1 | circ.dag[path1[front1_index + 2].first] = {get_op_ptr(OpType::V)}; | |
181 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | circ.add_phase(0.25); | |
182 | 1 | front1_index++; | ||
183 | 1 | back1_index--; | ||
184 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | } else if (back1_index != front1_index) { | |
185 | // There are some ops after the S that we cannot commute past the CX | |||
186 | ✗ | continue; | ||
187 | } | |||
188 | } | |||
189 |
4/6✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
|
11 | if (!allow_swaps && v_on_q0 && s_on_q1) { | |
190 | ✗ | continue; | ||
191 | } | |||
192 | 11 | success = true; | ||
193 | // Always remove the CX pair, saving the new edges from the second | |||
194 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | Edge next_e0 = circ.get_nth_out_edge(v0, 0); | |
195 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | Edge next_e1 = circ.get_nth_out_edge(v0, 1); | |
196 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | Vertex next_v0 = circ.target(next_e0); | |
197 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | Vertex next_v1 = circ.target(next_e1); | |
198 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | port_t next_p0 = circ.get_target_port(next_e0); | |
199 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | port_t next_p1 = circ.get_target_port(next_e1); | |
200 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | bin.push_back(v); | |
201 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | bin.push_back(v0); | |
202 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | circ.remove_vertex( | |
203 | v, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No); | |||
204 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | circ.remove_vertex( | |
205 | v0, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No); | |||
206 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | Edge default_h0 = circ.get_nth_in_edge(next_v0, next_p0); | |
207 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | Edge default_h1 = circ.get_nth_in_edge(next_v1, next_p1); | |
208 | ||||
209 | 11 | Subcircuit sub; | ||
210 | const Circuit *replacement; | |||
211 |
2/4✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
|
11 | Qubit q0, q1; | |
212 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
|
11 | if (v_on_q0) { | |
213 | 5 | Vertex v_gate = path0[front0_index].first; | ||
214 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
|
5 | q0 = Qubit(*v_to_qb.at(v_gate).begin()); | |
215 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | q1 = qbs.at(0); | |
216 |
3/6✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
|
5 | if (q0 == q1) q1 = qbs.at(1); | |
217 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (s_on_q1) { | |
218 | /* --C--V--C-- --Z--S--V--X--S--\ /-- */ | |||
219 | /* | | => | \ */ | |||
220 | /* --X--S--X-- --X--V--S--C--V--/ \-- */ | |||
221 | ✗ | Vertex s_gate = path1[front1_index].first; | ||
222 | ✗ | bin.push_back(v_gate); | ||
223 | ✗ | bin.push_back(s_gate); | ||
224 | sub = { | |||
225 | ✗ | {circ.get_nth_in_edge(v_gate, 0), | ||
226 | ✗ | circ.get_nth_in_edge(s_gate, 0)}, | ||
227 | ✗ | {circ.get_nth_out_edge(v_gate, 0), | ||
228 | ✗ | circ.get_nth_out_edge(s_gate, 0)}, | ||
229 | ✗ | {v_gate, s_gate}}; | ||
230 | ✗ | replacement = &CircPool::CX_VS_CX_reduced(); | ||
231 | } else { | |||
232 | /* --C--V--C-- --X--V--S--V--C--V--S-- */ | |||
233 | /* | | => | */ | |||
234 | /* --X-----X-- --V-----------X-------- */ | |||
235 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | bin.push_back(v_gate); | |
236 | sub = { | |||
237 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | {circ.get_nth_in_edge(v_gate, 0), default_h1}, | |
238 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | {circ.get_nth_out_edge(v_gate, 0), default_h1}, | |
239 |
4/8✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
|
10 | {v_gate}}; | |
240 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | replacement = &CircPool::CX_V_CX_reduced(); | |
241 | } | |||
242 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
|
6 | } else if (s_on_q1) { | |
243 | /* --C-----C-- --S-----------C-------- */ | |||
244 | /* | | => | */ | |||
245 | /* --X--S--X-- --Z--S--V--S--X--S--V-- */ | |||
246 | 5 | Vertex s_gate = path1[front1_index].first; | ||
247 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
|
5 | q1 = Qubit(*v_to_qb.at(s_gate).begin()); | |
248 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | q0 = qbs.at(0); | |
249 |
2/6✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
5 | if (q0 == q1) q0 = qbs.at(1); | |
250 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | bin.push_back(s_gate); | |
251 | sub = { | |||
252 | ✗ | {default_h0, circ.get_nth_in_edge(s_gate, 0)}, | ||
253 | ✗ | {default_h0, circ.get_nth_out_edge(s_gate, 0)}, | ||
254 |
6/12✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 5 times.
✗ Branch 20 not taken.
|
5 | {s_gate}}; | |
255 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | replacement = &CircPool::CX_S_CX_reduced(); | |
256 | } else { | |||
257 | /* --C--C-- ---- */ | |||
258 | /* | | => */ | |||
259 | /* --X--X-- ---- */ | |||
260 | 1 | continue; | ||
261 | } | |||
262 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | Vertex b0 = circ.source(sub.q_in_hole[0]); | |
263 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | port_t p0 = circ.get_source_port(sub.q_in_hole[0]); | |
264 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | Vertex b1 = circ.source(sub.q_in_hole[1]); | |
265 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | port_t p1 = circ.get_source_port(sub.q_in_hole[1]); | |
266 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | Vertex a0 = circ.target(sub.q_out_hole[0]); | |
267 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | Vertex a1 = circ.target(sub.q_out_hole[1]); | |
268 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | circ.substitute(*replacement, sub, Circuit::VertexDeletion::No); | |
269 | // Scan through hole and add vertices to v_to_qb | |||
270 | // and give estimates of depth and rev_depth | |||
271 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | unsigned new_depth = std::min(v_to_depth[a0], v_to_depth[a1]); | |
272 | unsigned new_rev_depth = | |||
273 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | std::min(v_to_rev_depth[b0], v_to_rev_depth[b1]); | |
274 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | Edge ei0 = circ.get_nth_out_edge(b0, p0); | |
275 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | Vertex vi0 = circ.target(ei0); | |
276 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 10 times.
|
55 | while (vi0 != a0) { | |
277 |
5/10✓ Branch 3 taken 45 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 45 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 45 times.
✗ Branch 10 not taken.
✓ Branch 14 taken 45 times.
✓ Branch 15 taken 45 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
90 | v_to_qb.insert({vi0, {q0}}); | |
278 |
1/2✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
|
45 | v_to_depth[vi0] = new_depth; | |
279 |
1/2✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
|
45 | v_to_rev_depth[vi0] = new_rev_depth; | |
280 |
1/2✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
|
45 | ei0 = circ.get_next_edge(vi0, ei0); | |
281 |
1/2✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
|
45 | vi0 = circ.target(ei0); | |
282 | } | |||
283 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | Edge ei1 = circ.get_nth_out_edge(b1, p1); | |
284 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | Vertex vi1 = circ.target(ei1); | |
285 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 10 times.
|
55 | while (vi1 != a1) { | |
286 |
3/4✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 35 times.
✓ Branch 6 taken 10 times.
|
45 | if (v_to_qb.find(vi1) == v_to_qb.end()) | |
287 |
5/10✓ Branch 3 taken 35 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 35 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 35 times.
✗ Branch 10 not taken.
✓ Branch 14 taken 35 times.
✓ Branch 15 taken 35 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
70 | v_to_qb.insert({vi1, {q1}}); | |
288 | else | |||
289 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | v_to_qb.at(vi1).insert(q1); | |
290 |
1/2✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
|
45 | v_to_depth[vi1] = new_depth; | |
291 |
1/2✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
|
45 | v_to_rev_depth[vi1] = new_rev_depth; | |
292 |
1/2✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
|
45 | ei1 = circ.get_next_edge(vi1, ei1); | |
293 |
1/2✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
|
45 | vi1 = circ.target(ei1); | |
294 | } | |||
295 |
6/6✓ Branch 1 taken 10 times.
✓ Branch 2 taken 1 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 1 times.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 1 times.
|
13 | } else { | |
296 | // CXs have different orientation | |||
297 | 15 | unsigned back0_index = path0_length - 1; | ||
298 |
4/4✓ Branch 0 taken 19 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 4 times.
|
36 | while (back0_index >= front0_index && back0_index != (unsigned)-1 && | |
299 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
|
15 | circ.commutes_with_basis( | |
300 |
3/4✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 15 times.
|
36 | path0[back0_index].first, Pauli::X, PortType::Target, | |
301 | 15 | path0[back0_index].second)) { | ||
302 | 6 | back0_index--; | ||
303 | } | |||
304 | 15 | unsigned back1_index = path1_length - 1; | ||
305 |
4/4✓ Branch 0 taken 17 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 4 times.
|
32 | while (back1_index >= front1_index && back1_index != (unsigned)-1 && | |
306 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
|
13 | circ.commutes_with_basis( | |
307 |
3/4✓ Branch 3 taken 13 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 15 times.
|
32 | path1[back1_index].first, Pauli::Z, PortType::Target, | |
308 | 13 | path1[back1_index].second)) { | ||
309 | 4 | back1_index--; | ||
310 | } | |||
311 | Vertex front0pre = | |||
312 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13 times.
|
15 | (front0_index == 0) ? v : path0[front0_index - 1].first; | |
313 | Vertex front0post = | |||
314 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
|
15 | (front0_index == path0_length) ? v0 : path0[front0_index].first; | |
315 | Vertex front1pre = | |||
316 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13 times.
|
15 | (front1_index == 0) ? v : path1[front1_index - 1].first; | |
317 | Vertex front1post = | |||
318 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
|
15 | (front1_index == path1_length) ? v0 : path1[front1_index].first; | |
319 | Vertex back0pre = | |||
320 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
|
15 | (back0_index == (unsigned)-1) ? v : path0[back0_index].first; | |
321 | 15 | Vertex back0post = (back0_index == path0_length - 1) | ||
322 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 11 times.
|
19 | ? v0 | |
323 | 4 | : path0[back0_index + 1].first; | ||
324 | Vertex back1pre = | |||
325 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
|
15 | (back1_index == (unsigned)-1) ? v : path1[back1_index].first; | |
326 | 15 | Vertex back1post = (back1_index == path1_length - 1) | ||
327 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12 times.
|
18 | ? v0 | |
328 | 3 | : path1[back1_index + 1].first; | ||
329 |
3/4✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 14 times.
|
15 | if (circ.in_causal_order( | |
330 | front1pre, front0post, true, v_to_depth, v_to_qb)) | |||
331 | 8 | continue; | ||
332 |
2/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
|
14 | if (circ.in_causal_order( | |
333 | front0pre, front1post, true, v_to_depth, v_to_qb)) | |||
334 | ✗ | continue; | ||
335 |
2/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
|
14 | if (circ.in_causal_order( | |
336 | back1post, back0pre, false, v_to_rev_depth, v_to_qb)) | |||
337 | ✗ | continue; | ||
338 |
2/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
|
14 | if (circ.in_causal_order( | |
339 | back0post, back1pre, false, v_to_rev_depth, v_to_qb)) | |||
340 | ✗ | continue; | ||
341 | // Identify which pattern | |||
342 | 14 | bool vs_on_q0 = false; | ||
343 |
4/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 3 times.
|
14 | if (back0_index >= front0_index && back0_index != (unsigned)-1) { | |
344 |
4/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 6 times.
|
17 | if (!(back0_index == front0_index + 1 && | |
345 |
3/4✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 2 times.
|
8 | circ.get_OpType_from_Vertex(path0[front0_index].first) == | |
346 | OpType::V && | |||
347 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
|
6 | circ.get_OpType_from_Vertex(path0[back0_index].first) == | |
348 | OpType::S)) { | |||
349 | // The only non-empty pattern we can recognise is from VS | |||
350 | 3 | continue; | ||
351 | } | |||
352 | 6 | vs_on_q0 = true; | ||
353 | } | |||
354 | 11 | bool sv_on_q1 = false; | ||
355 |
4/4✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 4 times.
|
11 | if (back1_index >= front1_index && back1_index != (unsigned)-1) { | |
356 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5 times.
|
11 | if (!(back1_index == front1_index + 1 && | |
357 |
2/4✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
|
5 | circ.get_OpType_from_Vertex(path1[front1_index].first) == | |
358 | OpType::S && | |||
359 |
2/4✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
|
5 | circ.get_OpType_from_Vertex(path1[back1_index].first) == | |
360 | OpType::V)) { | |||
361 | // The only non-empty pattern we can recognise is from SV | |||
362 | 1 | continue; | ||
363 | } | |||
364 | 5 | sv_on_q1 = true; | ||
365 | } | |||
366 |
6/6✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
|
10 | if (!allow_swaps && !vs_on_q0 && !sv_on_q1) { | |
367 | 1 | continue; | ||
368 | } | |||
369 | 9 | success = true; | ||
370 | // Always remove the CX pair, saving the edges to insert the replacement | |||
371 | // circuit | |||
372 | Vertex before0, before1, after0, after1; | |||
373 | port_t pb0, pb1, pa0, pa1; | |||
374 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
|
9 | if (front0_index > 0) { | |
375 | 1 | before0 = path0[front0_index - 1].first; | ||
376 | 1 | pb0 = path0[front0_index - 1].second; | ||
377 | } else { | |||
378 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | Edge pre0 = circ.get_nth_in_edge(v, 0); | |
379 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | before0 = circ.source(pre0); | |
380 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | pb0 = circ.get_source_port(pre0); | |
381 | } | |||
382 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
|
9 | if (front1_index > 0) { | |
383 | 1 | before1 = path1[front1_index - 1].first; | ||
384 | 1 | pb1 = path1[front1_index - 1].second; | ||
385 | } else { | |||
386 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | Edge pre1 = circ.get_nth_in_edge(v, 1); | |
387 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | before1 = circ.source(pre1); | |
388 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | pb1 = circ.get_source_port(pre1); | |
389 | } | |||
390 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
|
9 | if (back0_index + 1 < path0_length) { | |
391 | 2 | after0 = path0[back0_index + 1].first; | ||
392 | 2 | pa0 = path0[back0_index + 1].second; | ||
393 | } else { | |||
394 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | Edge post0 = circ.get_nth_out_edge(v0, 1); | |
395 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | after0 = circ.target(post0); | |
396 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | pa0 = circ.get_target_port(post0); | |
397 | } | |||
398 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
|
9 | if (back1_index + 1 < path1_length) { | |
399 | 2 | after1 = path1[back1_index + 1].first; | ||
400 | 2 | pa1 = path1[back1_index + 1].second; | ||
401 | } else { | |||
402 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | Edge post1 = circ.get_nth_out_edge(v0, 0); | |
403 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | after1 = circ.target(post1); | |
404 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | pa1 = circ.get_target_port(post1); | |
405 | } | |||
406 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | bin.push_back(v); | |
407 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | bin.push_back(v0); | |
408 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | circ.remove_vertex( | |
409 | v, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No); | |||
410 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | circ.remove_vertex( | |
411 | v0, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No); | |||
412 | 9 | VertexSet to_remove; | ||
413 | const Circuit *replacement; | |||
414 |
2/4✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
|
9 | Qubit q0, q1; | |
415 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
|
9 | if (vs_on_q0) { | |
416 | 5 | Vertex v_gate = path0[front0_index].first; | ||
417 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
|
5 | q0 = Qubit(*v_to_qb.at(v_gate).begin()); | |
418 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | q1 = qbs.at(0); | |
419 |
3/6✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
|
5 | if (q0 == q1) q1 = qbs.at(1); | |
420 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
|
5 | if (sv_on_q1) { | |
421 | /* --C--V--S--X-- --V--S-- */ | |||
422 | /* | | => */ | |||
423 | /* --X--S--V--C-- --S--V-- */ | |||
424 | 2 | continue; | ||
425 | } else { | |||
426 | /* --C--V--S--X-- --S-----C--V--S-- */ | |||
427 | /* | | => | */ | |||
428 | /* --X--------C-- --Z--S--X--S----- */ | |||
429 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | replacement = &CircPool::CX_V_S_XC_reduced(); | |
430 | } | |||
431 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | bin.push_back(path0[front0_index].first); | |
432 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | bin.push_back(path0[back0_index].first); | |
433 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | to_remove.insert(path0[front0_index].first); | |
434 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | to_remove.insert(path0[back0_index].first); | |
435 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | } else if (sv_on_q1) { | |
436 | /* --C--------X-- --X--V--C--V----- */ | |||
437 | /* | | => | */ | |||
438 | /* --X--S--V--C-- --V-----X--S--V-- */ | |||
439 | 3 | Vertex s_gate = path1[front1_index].first; | ||
440 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
3 | q1 = Qubit(*v_to_qb.at(s_gate).begin()); | |
441 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | q0 = qbs.at(0); | |
442 |
4/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
3 | if (q0 == q1) q0 = qbs.at(1); | |
443 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | replacement = &CircPool::CX_S_V_XC_reduced(); | |
444 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | bin.push_back(path1[front1_index].first); | |
445 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | bin.push_back(path1[back1_index].first); | |
446 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | to_remove.insert(path1[front1_index].first); | |
447 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | to_remove.insert(path1[back1_index].first); | |
448 | } else { | |||
449 | /* --C--X-- --X--\ /-- */ | |||
450 | /* | | => | \ */ | |||
451 | /* --X--C-- --C--/ \-- */ | |||
452 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | q0 = qbs.at(0); | |
453 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | q1 = qbs.at(1); | |
454 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | replacement = &CircPool::CX_XC_reduced(); | |
455 | } | |||
456 | Subcircuit sub = { | |||
457 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | {circ.get_nth_out_edge(before0, pb0), | |
458 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | circ.get_nth_out_edge(before1, pb1)}, | |
459 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | {circ.get_nth_in_edge(after0, pa0), | |
460 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | circ.get_nth_in_edge(after1, pa1)}, | |
461 |
3/6✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 10 not taken.
|
21 | to_remove}; | |
462 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | Vertex b0 = circ.source(sub.q_in_hole[0]); | |
463 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | port_t p0 = circ.get_source_port(sub.q_in_hole[0]); | |
464 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | Vertex b1 = circ.source(sub.q_in_hole[1]); | |
465 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | port_t p1 = circ.get_source_port(sub.q_in_hole[1]); | |
466 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | Vertex a0 = circ.target(sub.q_out_hole[0]); | |
467 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | Vertex a1 = circ.target(sub.q_out_hole[1]); | |
468 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | circ.substitute(*replacement, sub, Circuit::VertexDeletion::No); | |
469 | // Scan through hole and add vertices to v_to_qb | |||
470 |
2/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
7 | unsigned new_depth = std::min(v_to_depth[a0], v_to_depth[a1]); | |
471 | unsigned new_rev_depth = | |||
472 |
2/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
7 | std::min(v_to_rev_depth[b0], v_to_rev_depth[b1]); | |
473 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | Edge ei0 = circ.get_nth_out_edge(b0, p0); | |
474 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | Vertex vi0 = circ.target(ei0); | |
475 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 7 times.
|
33 | while (vi0 != a0) { | |
476 |
5/10✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 26 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 26 times.
✗ Branch 10 not taken.
✓ Branch 14 taken 26 times.
✓ Branch 15 taken 26 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
52 | v_to_qb.insert({vi0, {q0}}); | |
477 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | v_to_depth[vi0] = new_depth; | |
478 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | v_to_rev_depth[vi0] = new_rev_depth; | |
479 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | ei0 = circ.get_next_edge(vi0, ei0); | |
480 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | vi0 = circ.target(ei0); | |
481 | } | |||
482 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | Edge ei1 = circ.get_nth_out_edge(b1, p1); | |
483 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | Vertex vi1 = circ.target(ei1); | |
484 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 7 times.
|
33 | while (vi1 != a1) { | |
485 |
3/4✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 8 times.
|
26 | if (v_to_qb.find(vi1) == v_to_qb.end()) | |
486 |
5/10✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 18 times.
✗ Branch 10 not taken.
✓ Branch 14 taken 18 times.
✓ Branch 15 taken 18 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
36 | v_to_qb.insert({vi1, {q1}}); | |
487 | else | |||
488 |
2/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
8 | v_to_qb.at(vi1).insert(q1); | |
489 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | v_to_depth[vi1] = new_depth; | |
490 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | v_to_rev_depth[vi1] = new_rev_depth; | |
491 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | ei1 = circ.get_next_edge(vi1, ei1); | |
492 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | vi1 = circ.target(ei1); | |
493 | } | |||
494 |
6/6✓ Branch 2 taken 7 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 2 times.
✓ Branch 8 taken 7 times.
✓ Branch 9 taken 2 times.
|
13 | } | |
495 |
8/8✓ Branch 1 taken 17 times.
✓ Branch 2 taken 39 times.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 39 times.
✓ Branch 7 taken 17 times.
✓ Branch 8 taken 39 times.
✓ Branch 10 taken 17 times.
✓ Branch 11 taken 39 times.
|
173 | } | |
496 | } | |||
497 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
|
16 | if (allow_swaps) { | |
498 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | circ.replace_SWAPs(); | |
499 | } | |||
500 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | circ.remove_vertices( | |
501 | bin, Circuit::GraphRewiring::No, Circuit::VertexDeletion::Yes); | |||
502 | 16 | return success; | ||
503 | 16 | } | ||
504 | ||||
505 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | Transform copy_pi_through_CX() { return Transform(copy_pi_through_CX_method); } | |
506 | ||||
507 | // TODO:: Copy classical-controls and any controls from CX | |||
508 | 5 | static bool copy_pi_through_CX_method(Circuit &circ) { | ||
509 | 5 | bool success = false; | ||
510 | 5 | VertexList bin; | ||
511 |
7/8✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 41 times.
✓ Branch 6 taken 5 times.
✓ Branch 8 taken 41 times.
✓ Branch 9 taken 5 times.
✓ Branch 11 taken 5 times.
✓ Branch 12 taken 5 times.
|
51 | BGL_FORALL_VERTICES(vert, circ.dag, DAG) { | |
512 |
5/6✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 32 times.
✓ Branch 5 taken 9 times.
✓ Branch 6 taken 32 times.
|
50 | if (circ.get_OpType_from_Vertex(vert) == OpType::CX && | |
513 |
2/4✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
|
9 | circ.n_out_edges(vert) == 2) { | |
514 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | Edge e0 = circ.get_nth_out_edge(vert, 0); | |
515 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | Vertex v0 = circ.target(e0); | |
516 |
3/4✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 7 times.
|
9 | if (circ.get_OpType_from_Vertex(v0) == OpType::X) { | |
517 | 2 | success = true; | ||
518 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | Edge afterX = circ.get_next_edge(v0, e0); | |
519 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | Edge after1 = circ.get_nth_out_edge(vert, 1); | |
520 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | Vertex v_after1 = circ.target(after1); | |
521 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | port_t pa1 = circ.get_target_port(after1); | |
522 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | bin.push_back(vert); | |
523 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | circ.remove_vertex( | |
524 | vert, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No); | |||
525 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | after1 = circ.get_nth_in_edge(v_after1, pa1); | |
526 |
3/6✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
|
4 | Subcircuit sub = {{afterX, after1}, {afterX, after1}}; | |
527 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | circ.substitute(CircPool::X1_CX(), sub, Circuit::VertexDeletion::No); | |
528 | 2 | continue; | ||
529 | 2 | } | ||
530 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | Edge e1 = circ.get_nth_out_edge(vert, 1); | |
531 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | Vertex v1 = circ.target(e1); | |
532 |
3/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 6 times.
|
7 | if (circ.get_OpType_from_Vertex(v1) == OpType::Z) { | |
533 | 1 | success = true; | ||
534 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Edge afterZ = circ.get_next_edge(v1, e1); | |
535 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Edge after0 = circ.get_nth_out_edge(vert, 0); | |
536 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Vertex v_after0 = circ.target(after0); | |
537 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | port_t pa0 = circ.get_target_port(after0); | |
538 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | bin.push_back(vert); | |
539 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | circ.remove_vertex( | |
540 | vert, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No); | |||
541 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | after0 = circ.get_nth_in_edge(v_after0, pa0); | |
542 |
3/6✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
2 | Subcircuit sub = {{after0, afterZ}, {after0, afterZ}}; | |
543 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | circ.substitute(CircPool::Z0_CX(), sub, Circuit::VertexDeletion::No); | |
544 | 1 | } | ||
545 | } | |||
546 | } | |||
547 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | circ.remove_vertices( | |
548 | bin, Circuit::GraphRewiring::No, Circuit::VertexDeletion::Yes); | |||
549 | 5 | return success; | ||
550 | 5 | } | ||
551 | ||||
552 | // TODO:: Detect classical controls and stop simplification | |||
553 | 3530 | static bool singleq_clifford_from_edge( | ||
554 | Circuit &circ, Edge &e, VertexList &bin) { | |||
555 | 3530 | VertexSet single_vs; | ||
556 | 3530 | Edge ei = e; | ||
557 |
1/2✓ Branch 1 taken 3530 times.
✗ Branch 2 not taken.
|
3530 | Vertex vi = circ.target(ei); | |
558 | // stuff to check if it is already in standard form | |||
559 | // 6 = not consumed anything, 5=Z, 4=X, 3=first S, 2=V, 1=second S, 0=other | |||
560 | 3530 | unsigned cliff_last = 6; | ||
561 |
3/4✓ Branch 1 taken 19160 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15630 times.
✓ Branch 4 taken 3530 times.
|
19160 | while (circ.detect_singleq_unitary_op(vi)) { | |
562 | // i.e. we have a single qubit unitary | |||
563 |
1/2✓ Branch 1 taken 15630 times.
✗ Branch 2 not taken.
|
15630 | single_vs.insert(vi); | |
564 | ||||
565 | // keep track of clifford standard form | |||
566 |
6/7✓ Branch 1 taken 15630 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2027 times.
✓ Branch 4 taken 2831 times.
✓ Branch 5 taken 3296 times.
✓ Branch 6 taken 3646 times.
✓ Branch 7 taken 3830 times.
|
15630 | switch (circ.get_OpType_from_Vertex(vi)) { | |
567 | 2027 | case OpType::Z: { | ||
568 |
2/2✓ Branch 0 taken 473 times.
✓ Branch 1 taken 1554 times.
|
2027 | cliff_last = (cliff_last > 5) ? 5 : 0; | |
569 | 2027 | break; | ||
570 | } | |||
571 | 2831 | case OpType::X: { | ||
572 |
2/2✓ Branch 0 taken 634 times.
✓ Branch 1 taken 2197 times.
|
2831 | cliff_last = (cliff_last > 4) ? 4 : 0; | |
573 | 2831 | break; | ||
574 | } | |||
575 | 3296 | case OpType::S: { | ||
576 |
2/2✓ Branch 0 taken 633 times.
✓ Branch 1 taken 2663 times.
|
3296 | if (cliff_last > 3) | |
577 | 633 | cliff_last = 3; | ||
578 |
2/2✓ Branch 0 taken 641 times.
✓ Branch 1 taken 2022 times.
|
2663 | else if (cliff_last == 2) | |
579 | 641 | cliff_last = 1; | ||
580 | else | |||
581 | 2022 | cliff_last = 0; | ||
582 | 3296 | break; | ||
583 | } | |||
584 | 3646 | case OpType::V: { | ||
585 |
2/2✓ Branch 0 taken 1402 times.
✓ Branch 1 taken 2244 times.
|
3646 | cliff_last = (cliff_last > 2) ? 2 : 0; | |
586 | 3646 | break; | ||
587 | } | |||
588 | 3830 | default: { | ||
589 | 3830 | cliff_last = 0; | ||
590 | 3830 | break; | ||
591 | } | |||
592 | } | |||
593 | ||||
594 |
1/2✓ Branch 1 taken 15630 times.
✗ Branch 2 not taken.
|
15630 | ei = circ.get_next_edge(vi, ei); | |
595 |
1/2✓ Branch 1 taken 15630 times.
✗ Branch 2 not taken.
|
15630 | vi = circ.target(ei); | |
596 | } | |||
597 | // if the sequence is not in the standard form, replace it | |||
598 |
2/2✓ Branch 0 taken 2502 times.
✓ Branch 1 taken 1028 times.
|
3530 | if (cliff_last == 0) { | |
599 |
3/6✓ Branch 2 taken 2502 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2502 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2502 times.
✗ Branch 10 not taken.
|
5004 | Subcircuit s = {{e}, {ei}, single_vs}; | |
600 |
1/2✓ Branch 1 taken 2502 times.
✗ Branch 2 not taken.
|
2502 | Circuit sub = circ.subcircuit(s); | |
601 |
4/8✓ Branch 1 taken 2502 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2502 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2502 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2502 times.
✗ Branch 11 not taken.
|
7506 | bool reduced = (decompose_single_qubits_TK1() >> squash_1qb_to_tk1() >> | |
602 |
1/2✓ Branch 1 taken 2502 times.
✗ Branch 2 not taken.
|
5004 | decompose_cliffords_std()) | |
603 |
1/2✓ Branch 1 taken 2502 times.
✗ Branch 2 not taken.
|
2502 | .apply(sub); | |
604 |
1/2✓ Branch 0 taken 2502 times.
✗ Branch 1 not taken.
|
2502 | if (reduced) { | |
605 |
1/2✓ Branch 1 taken 2502 times.
✗ Branch 2 not taken.
|
2502 | circ.substitute(sub, s, Circuit::VertexDeletion::No); | |
606 |
1/2✓ Branch 5 taken 2502 times.
✗ Branch 6 not taken.
|
2502 | bin.insert(bin.end(), single_vs.begin(), single_vs.end()); | |
607 | 2502 | return true; | ||
608 | } | |||
609 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 2502 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2502 times.
|
5004 | } | |
610 | 1028 | return false; | ||
611 | 3530 | } | ||
612 | ||||
613 | 171 | Transform singleq_clifford_sweep() { | ||
614 | 174 | return Transform([](Circuit &circ) { | ||
615 | 174 | bool success = false; | ||
616 | 174 | VertexList bin; | ||
617 |
1/2✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
|
174 | std::vector<Vertex> vertices = circ.vertices_in_order(); | |
618 |
3/4✓ Branch 4 taken 16029 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15855 times.
✓ Branch 7 taken 174 times.
|
16029 | for (auto it = vertices.crbegin(); it != vertices.crend(); ++it) { | |
619 | 15855 | const Vertex &v = *it; | ||
620 |
3/4✓ Branch 1 taken 15855 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1518 times.
✓ Branch 4 taken 14337 times.
|
15855 | if (circ.get_OpType_from_Vertex(v) == OpType::CX) { | |
621 |
2/2✓ Branch 0 taken 3036 times.
✓ Branch 1 taken 1518 times.
|
4554 | for (port_t p = 0; p < 2; p++) { | |
622 | // put both subsequent single qubit sequences into normal form | |||
623 | // stuff for obtaining next single qubit subcircuit | |||
624 |
1/2✓ Branch 1 taken 3036 times.
✗ Branch 2 not taken.
|
3036 | Edge e = circ.get_nth_out_edge(v, p); | |
625 |
5/6✓ Branch 1 taken 3036 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 929 times.
✓ Branch 4 taken 2107 times.
✓ Branch 5 taken 800 times.
✓ Branch 6 taken 129 times.
|
3036 | success = singleq_clifford_from_edge(circ, e, bin) || success; | |
626 | } | |||
627 | // commute Z, X and whatever else we can through | |||
628 |
1/2✓ Branch 1 taken 1518 times.
✗ Branch 2 not taken.
|
1518 | Edge e0 = circ.get_nth_out_edge(v, 0); | |
629 |
1/2✓ Branch 1 taken 1518 times.
✗ Branch 2 not taken.
|
1518 | Vertex v0 = circ.target(e0); | |
630 | ||||
631 |
3/4✓ Branch 1 taken 1518 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 214 times.
✓ Branch 4 taken 1304 times.
|
1518 | if (circ.get_OpType_from_Vertex(v0) == OpType::Z) { | |
632 |
1/2✓ Branch 1 taken 214 times.
✗ Branch 2 not taken.
|
214 | circ.remove_vertex( | |
633 | v0, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No); | |||
634 |
1/2✓ Branch 1 taken 214 times.
✗ Branch 2 not taken.
|
214 | Edge in_e = circ.get_nth_in_edge(v, 0); | |
635 |
3/6✓ Branch 2 taken 214 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 214 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 214 times.
✗ Branch 10 not taken.
|
214 | circ.rewire(v0, {in_e}, {EdgeType::Quantum}); | |
636 | 214 | success = true; | ||
637 |
1/2✓ Branch 1 taken 214 times.
✗ Branch 2 not taken.
|
214 | e0 = circ.get_nth_out_edge(v, 0); | |
638 |
1/2✓ Branch 1 taken 214 times.
✗ Branch 2 not taken.
|
214 | v0 = circ.target(e0); | |
639 | } | |||
640 |
3/4✓ Branch 1 taken 1518 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 352 times.
✓ Branch 4 taken 1166 times.
|
1518 | if (circ.get_OpType_from_Vertex(v0) == OpType::X) { | |
641 |
1/2✓ Branch 1 taken 352 times.
✗ Branch 2 not taken.
|
352 | circ.remove_vertex( | |
642 | v0, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No); | |||
643 |
1/2✓ Branch 1 taken 352 times.
✗ Branch 2 not taken.
|
352 | Edge in_e = circ.get_nth_in_edge(v, 0); | |
644 |
3/6✓ Branch 2 taken 352 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 352 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 352 times.
✗ Branch 10 not taken.
|
352 | circ.rewire(v0, {in_e}, {EdgeType::Quantum}); | |
645 |
1/2✓ Branch 2 taken 352 times.
✗ Branch 3 not taken.
|
352 | Vertex new_v = circ.add_vertex(OpType::X); | |
646 |
1/2✓ Branch 1 taken 352 times.
✗ Branch 2 not taken.
|
352 | in_e = circ.get_nth_in_edge(v, 1); | |
647 |
3/6✓ Branch 2 taken 352 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 352 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 352 times.
✗ Branch 10 not taken.
|
352 | circ.rewire(new_v, {in_e}, {EdgeType::Quantum}); | |
648 | 352 | success = true; | ||
649 |
1/2✓ Branch 1 taken 352 times.
✗ Branch 2 not taken.
|
352 | e0 = circ.get_nth_out_edge(v, 0); | |
650 |
1/2✓ Branch 1 taken 352 times.
✗ Branch 2 not taken.
|
352 | v0 = circ.target(e0); | |
651 | } | |||
652 |
3/4✓ Branch 1 taken 1518 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 355 times.
✓ Branch 4 taken 1163 times.
|
1518 | if (circ.get_OpType_from_Vertex(v0) == OpType::S) { | |
653 |
1/2✓ Branch 1 taken 355 times.
✗ Branch 2 not taken.
|
355 | circ.remove_vertex( | |
654 | v0, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No); | |||
655 |
1/2✓ Branch 1 taken 355 times.
✗ Branch 2 not taken.
|
355 | Edge in_e = circ.get_nth_in_edge(v, 0); | |
656 |
3/6✓ Branch 2 taken 355 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 355 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 355 times.
✗ Branch 10 not taken.
|
355 | circ.rewire(v0, {in_e}, {EdgeType::Quantum}); | |
657 | 355 | success = true; | ||
658 | } | |||
659 |
1/2✓ Branch 1 taken 1518 times.
✗ Branch 2 not taken.
|
1518 | Edge e1 = circ.get_nth_out_edge(v, 1); | |
660 |
1/2✓ Branch 1 taken 1518 times.
✗ Branch 2 not taken.
|
1518 | Vertex v1 = circ.target(e1); | |
661 |
3/4✓ Branch 1 taken 1518 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 266 times.
✓ Branch 4 taken 1252 times.
|
1518 | if (circ.get_OpType_from_Vertex(v1) == OpType::Z) { | |
662 |
1/2✓ Branch 1 taken 266 times.
✗ Branch 2 not taken.
|
266 | circ.remove_vertex( | |
663 | v1, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No); | |||
664 |
1/2✓ Branch 1 taken 266 times.
✗ Branch 2 not taken.
|
266 | Edge in_e = circ.get_nth_in_edge(v, 1); | |
665 |
3/6✓ Branch 2 taken 266 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 266 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 266 times.
✗ Branch 10 not taken.
|
266 | circ.rewire(v1, {in_e}, {EdgeType::Quantum}); | |
666 |
1/2✓ Branch 2 taken 266 times.
✗ Branch 3 not taken.
|
266 | Vertex new_v = circ.add_vertex(OpType::Z); | |
667 |
1/2✓ Branch 1 taken 266 times.
✗ Branch 2 not taken.
|
266 | in_e = circ.get_nth_in_edge(v, 0); | |
668 |
3/6✓ Branch 2 taken 266 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 266 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 266 times.
✗ Branch 10 not taken.
|
266 | circ.rewire(new_v, {in_e}, {EdgeType::Quantum}); | |
669 | 266 | success = true; | ||
670 |
1/2✓ Branch 1 taken 266 times.
✗ Branch 2 not taken.
|
266 | e1 = circ.get_nth_out_edge(v, 1); | |
671 |
1/2✓ Branch 1 taken 266 times.
✗ Branch 2 not taken.
|
266 | v1 = circ.target(e1); | |
672 | } | |||
673 |
3/4✓ Branch 1 taken 1518 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 360 times.
✓ Branch 4 taken 1158 times.
|
1518 | if (circ.get_OpType_from_Vertex(v1) == OpType::X) { | |
674 |
1/2✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
|
360 | circ.remove_vertex( | |
675 | v1, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No); | |||
676 |
1/2✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
|
360 | Edge in_e = circ.get_nth_in_edge(v, 1); | |
677 |
3/6✓ Branch 2 taken 360 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 360 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 360 times.
✗ Branch 10 not taken.
|
360 | circ.rewire(v1, {in_e}, {EdgeType::Quantum}); | |
678 | 360 | success = true; | ||
679 |
1/2✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
|
360 | e1 = circ.get_nth_out_edge(v, 1); | |
680 |
1/2✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
|
360 | v1 = circ.target(e1); | |
681 | } | |||
682 |
3/4✓ Branch 1 taken 1518 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 164 times.
✓ Branch 4 taken 1354 times.
|
1518 | if (circ.get_OpType_from_Vertex(v1) == OpType::V) { | |
683 |
1/2✓ Branch 1 taken 164 times.
✗ Branch 2 not taken.
|
164 | circ.remove_vertex( | |
684 | v1, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No); | |||
685 |
1/2✓ Branch 1 taken 164 times.
✗ Branch 2 not taken.
|
164 | Edge in_e = circ.get_nth_in_edge(v, 1); | |
686 |
3/6✓ Branch 2 taken 164 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 164 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 164 times.
✗ Branch 10 not taken.
|
164 | circ.rewire(v1, {in_e}, {EdgeType::Quantum}); | |
687 | 164 | success = true; | ||
688 | } | |||
689 | } | |||
690 | } | |||
691 | // clean up the start of the circuit | |||
692 |
3/4✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 494 times.
✓ Branch 8 taken 174 times.
|
668 | for (const Vertex &i : circ.q_inputs()) { | |
693 |
1/2✓ Branch 1 taken 494 times.
✗ Branch 2 not taken.
|
494 | Edge e = circ.get_nth_out_edge(i, 0); | |
694 |
5/6✓ Branch 1 taken 494 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 99 times.
✓ Branch 4 taken 395 times.
✓ Branch 5 taken 80 times.
✓ Branch 6 taken 19 times.
|
494 | success = singleq_clifford_from_edge(circ, e, bin) || success; | |
695 | 174 | } | ||
696 |
1/2✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
|
174 | circ.remove_vertices( | |
697 | bin, Circuit::GraphRewiring::No, Circuit::VertexDeletion::Yes); | |||
698 | 174 | return success; | ||
699 |
1/2✓ Branch 2 taken 171 times.
✗ Branch 3 not taken.
|
345 | }); | |
700 | } | |||
701 | ||||
702 | } // namespace Transforms | |||
703 | ||||
704 | } // namespace tket | |||
705 |