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 "SingleQubitSquash.hpp" | |||
16 | ||||
17 | #include "Circuit/Circuit.hpp" | |||
18 | #include "Circuit/DAGDefs.hpp" | |||
19 | #include "Gate/Gate.hpp" | |||
20 | ||||
21 | namespace tket { | |||
22 | ||||
23 | 10 | SingleQubitSquash::SingleQubitSquash(const SingleQubitSquash &other) | ||
24 | 10 | : squasher_(other.squasher_->clone()), | ||
25 | 10 | circ_(other.circ_), | ||
26 | 10 | reversed_(other.reversed_) {} | ||
27 | ||||
28 | ✗ | SingleQubitSquash &SingleQubitSquash::operator=( | ||
29 | const SingleQubitSquash &other) { | |||
30 | ✗ | squasher_ = other.squasher_->clone(); | ||
31 | ✗ | circ_ = other.circ_; | ||
32 | ✗ | reversed_ = other.reversed_; | ||
33 | ✗ | return *this; | ||
34 | } | |||
35 | ||||
36 | ✗ | SingleQubitSquash::SingleQubitSquash(SingleQubitSquash &&other) | ||
37 | ✗ | : squasher_(std::move(other.squasher_)), | ||
38 | ✗ | circ_(other.circ_), | ||
39 | ✗ | reversed_(other.reversed_) {} | ||
40 | ||||
41 | ✗ | SingleQubitSquash &SingleQubitSquash::operator=(SingleQubitSquash &&other) { | ||
42 | ✗ | squasher_ = std::move(other.squasher_); | ||
43 | ✗ | circ_ = other.circ_; | ||
44 | ✗ | reversed_ = other.reversed_; | ||
45 | ✗ | return *this; | ||
46 | } | |||
47 | ||||
48 | 6370 | bool SingleQubitSquash::squash() { | ||
49 | 6370 | bool success = false; | ||
50 | ||||
51 |
1/2✓ Branch 1 taken 6370 times.
✗ Branch 2 not taken.
|
6370 | VertexVec inputs = circ_.q_inputs(); | |
52 |
1/2✓ Branch 1 taken 6370 times.
✗ Branch 2 not taken.
|
6370 | VertexVec outputs = circ_.q_outputs(); | |
53 |
3/4✓ Branch 1 taken 15798 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9428 times.
✓ Branch 4 taken 6370 times.
|
0/1? Decision couldn't be analyzed.
|
15798 | for (unsigned i = 0; i < circ_.n_qubits(); ++i) { |
54 |
1/2✓ Branch 2 taken 9428 times.
✗ Branch 3 not taken.
|
9428 | Edge in = circ_.get_nth_out_edge(inputs[i], 0); | |
55 |
1/2✓ Branch 2 taken 9428 times.
✗ Branch 3 not taken.
|
9428 | Edge out = circ_.get_nth_in_edge(outputs[i], 0); | |
56 |
2/2✓ Branch 0 taken 9393 times.
✓ Branch 1 taken 35 times.
|
2/2✓ Decision 'true' taken 9393 times.
✓ Decision 'false' taken 35 times.
|
9428 | if (reversed_) { |
57 |
1/2✓ Branch 1 taken 9393 times.
✗ Branch 2 not taken.
|
9393 | success |= squash_between(out, in); | |
58 | } else { | |||
59 |
1/2✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
|
35 | success |= squash_between(in, out); | |
60 | } | |||
61 | } | |||
62 | ||||
63 | 6370 | return success; | ||
64 | 6370 | } | ||
65 | ||||
66 | 9723 | bool SingleQubitSquash::squash_between(const Edge &in, const Edge &out) { | ||
67 |
1/2✓ Branch 2 taken 9723 times.
✗ Branch 3 not taken.
|
9723 | squasher_->clear(); | |
68 | 9723 | Edge e = in; | ||
69 |
1/2✓ Branch 1 taken 9723 times.
✗ Branch 2 not taken.
|
9723 | Vertex v = next_vertex(e); | |
70 | 9723 | std::vector<Gate_ptr> single_chain; | ||
71 | 9723 | VertexVec bin; | ||
72 | 9723 | bool success = false; | ||
73 | 9723 | Condition condition = std::nullopt; | ||
74 | while (true) { | |||
75 |
1/2✓ Branch 1 taken 256609 times.
✗ Branch 2 not taken.
|
256609 | Op_ptr v_op = circ_.get_Op_ptr_from_Vertex(v); | |
76 | 256609 | OpType v_type = v_op->get_type(); | ||
77 | 256609 | bool move_to_next_vertex = false; | ||
78 | 256609 | bool reset_search = false; | ||
79 | 256609 | Condition this_condition = std::nullopt; | ||
80 | ||||
81 |
2/2✓ Branch 0 taken 278 times.
✓ Branch 1 taken 256331 times.
|
2/2✓ Decision 'true' taken 278 times.
✓ Decision 'false' taken 256331 times.
|
256609 | if (v_type == OpType::Conditional) { |
82 | // => deal with conditional case | |||
83 |
1/2✓ Branch 1 taken 278 times.
✗ Branch 2 not taken.
|
278 | this_condition = get_condition(v); | |
84 |
1/2✓ Branch 2 taken 278 times.
✗ Branch 3 not taken.
|
278 | v_op = static_cast<const Conditional &>(*v_op).get_op(); | |
85 | 278 | v_type = v_op->get_type(); | ||
86 | ||||
87 |
2/2✓ Branch 1 taken 230 times.
✓ Branch 2 taken 48 times.
|
2/2✓ Decision 'true' taken 230 times.
✓ Decision 'false' taken 48 times.
|
278 | if (single_chain.empty()) { |
88 |
1/2✓ Branch 1 taken 230 times.
✗ Branch 2 not taken.
|
230 | condition = this_condition; | |
89 | } | |||
90 | } | |||
91 | ||||
92 | 715947 | bool is_squashable = circ_.n_in_edges_of_type(v, EdgeType::Quantum) == 1 && | ||
93 |
6/8✓ Branch 1 taken 256609 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 202729 times.
✓ Branch 4 taken 53880 times.
✓ Branch 6 taken 202729 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 202488 times.
✓ Branch 9 taken 241 times.
|
459097 | is_gate_type(v_type) && | |
94 |
8/14✓ Branch 3 taken 202488 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 202488 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 202228 times.
✓ Branch 9 taken 260 times.
✓ Branch 10 taken 202488 times.
✓ Branch 11 taken 54121 times.
✓ Branch 13 taken 202488 times.
✓ Branch 14 taken 54121 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
|
459097 | squasher_->accepts(as_gate_ptr(v_op)); | |
95 | ||||
96 |
10/12✓ Branch 1 taken 256609 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 247031 times.
✓ Branch 4 taken 9578 times.
✓ Branch 6 taken 247031 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 246992 times.
✓ Branch 9 taken 39 times.
✓ Branch 10 taken 202216 times.
✓ Branch 11 taken 44776 times.
✓ Branch 12 taken 202216 times.
✓ Branch 13 taken 54393 times.
|
2/2✓ Decision 'true' taken 202216 times.
✓ Decision 'false' taken 54393 times.
|
256609 | if (e != out && condition == this_condition && is_squashable) { |
97 | // => add gate to current squash | |||
98 |
5/8✓ Branch 1 taken 201648 times.
✓ Branch 2 taken 568 times.
✓ Branch 5 taken 201648 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 202216 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 202216 times.
✗ Branch 13 not taken.
|
202216 | squasher_->append(as_gate_ptr(reversed_ ? v_op->dagger() : v_op)); | |
99 | 202216 | move_to_next_vertex = true; | ||
100 | } else { | |||
101 | // => squash and reset | |||
102 | 54393 | reset_search = true; | ||
103 |
2/2✓ Branch 1 taken 17044 times.
✓ Branch 2 taken 37349 times.
|
2/2✓ Decision 'true' taken 17044 times.
✓ Decision 'false' taken 37349 times.
|
54393 | if (single_chain.empty()) { |
104 | // => nothing to do, move on | |||
105 | 17044 | move_to_next_vertex = true; | ||
106 | } else { | |||
107 |
1/2✓ Branch 1 taken 37349 times.
✗ Branch 2 not taken.
|
37349 | Circuit sub; | |
108 | 37349 | std::optional<Pauli> commutation_colour = std::nullopt; | ||
109 |
8/10✓ Branch 1 taken 37349 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28561 times.
✓ Branch 4 taken 8788 times.
✓ Branch 7 taken 28561 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 28518 times.
✓ Branch 10 taken 43 times.
✓ Branch 11 taken 28518 times.
✓ Branch 12 taken 8831 times.
|
2/2✓ Decision 'true' taken 28518 times.
✓ Decision 'false' taken 8831 times.
|
37349 | if (is_gate_type(v_type) && v_op->n_qubits() > 1) { |
110 | commutation_colour = | |||
111 |
2/4✓ Branch 1 taken 28518 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28518 times.
✗ Branch 5 not taken.
|
28518 | circ_.commuting_basis(v, PortType::Target, next_port(e)); | |
112 | 28518 | move_to_next_vertex = true; | ||
113 | } | |||
114 |
1/2✓ Branch 2 taken 37349 times.
✗ Branch 3 not taken.
|
37349 | auto pair = squasher_->flush(commutation_colour); | |
115 |
1/2✓ Branch 1 taken 37349 times.
✗ Branch 2 not taken.
|
37349 | sub = pair.first; | |
116 | 37349 | Gate_ptr left_over_gate = pair.second; | ||
117 |
2/2✓ Branch 1 taken 161 times.
✓ Branch 2 taken 37188 times.
|
2/2✓ Decision 'true' taken 161 times.
✓ Decision 'false' taken 37188 times.
|
37349 | if (left_over_gate != nullptr) { |
118 | // => commute leftover through before squashing | |||
119 |
2/4✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 161 times.
✗ Branch 6 not taken.
|
161 | insert_left_over_gate(left_over_gate, next_edge(v, e), condition); | |
120 | 161 | left_over_gate = nullptr; | ||
121 | } | |||
122 |
2/2✓ Branch 0 taken 37049 times.
✓ Branch 1 taken 300 times.
|
2/2✓ Decision 'true' taken 37049 times.
✓ Decision 'false' taken 300 times.
|
37349 | if (reversed_) { |
123 |
2/4✓ Branch 1 taken 37049 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 37049 times.
✗ Branch 5 not taken.
|
37049 | sub = sub.dagger(); | |
124 | } | |||
125 | ||||
126 | // we squash if the replacement is at least as good as the original | |||
127 | // (and it's not a no-op) | |||
128 |
4/6✓ Branch 1 taken 37349 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 37349 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 29483 times.
✓ Branch 8 taken 7866 times.
|
2/2✓ Decision 'true' taken 29483 times.
✓ Decision 'false' taken 7866 times.
|
37349 | if (sub_is_better(sub, single_chain)) { |
129 |
1/2✓ Branch 1 taken 29483 times.
✗ Branch 2 not taken.
|
29483 | substitute(sub, bin, e, condition); | |
130 | 29483 | success = true; | ||
131 | } | |||
132 | 37349 | } | ||
133 | } | |||
134 |
8/10✓ Branch 1 taken 256609 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 253807 times.
✓ Branch 4 taken 2802 times.
✓ Branch 6 taken 253807 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6921 times.
✓ Branch 9 taken 246886 times.
✓ Branch 10 taken 9723 times.
✓ Branch 11 taken 246886 times.
|
2/2✓ Decision 'true' taken 9723 times.
✓ Decision 'false' taken 246886 times.
|
256609 | if (e == out || is_last_optype(v_type)) { |
135 |
1/2✓ Branch 2 taken 9723 times.
✗ Branch 3 not taken.
|
9723 | squasher_->clear(); | |
136 | 9723 | break; | ||
137 | } | |||
138 |
2/2✓ Branch 0 taken 246839 times.
✓ Branch 1 taken 47 times.
|
2/2✓ Decision 'true' taken 246839 times.
✓ Decision 'false' taken 47 times.
|
246886 | if (move_to_next_vertex) { |
139 |
3/4✓ Branch 1 taken 246839 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 246835 times.
✓ Branch 4 taken 4 times.
|
2/2✓ Decision 'true' taken 246835 times.
✓ Decision 'false' taken 4 times.
|
246839 | if (is_gate_type(v_type)) { |
140 |
1/2✓ Branch 1 taken 246835 times.
✗ Branch 2 not taken.
|
246835 | bin.push_back(v); | |
141 |
2/4✓ Branch 2 taken 246835 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 246835 times.
✗ Branch 6 not taken.
|
246835 | single_chain.push_back(as_gate_ptr(v_op)); | |
142 | } | |||
143 |
1/2✓ Branch 1 taken 246839 times.
✗ Branch 2 not taken.
|
246839 | e = next_edge(v, e); | |
144 |
1/2✓ Branch 1 taken 246839 times.
✗ Branch 2 not taken.
|
246839 | v = next_vertex(e); | |
145 | } | |||
146 |
2/2✓ Branch 0 taken 44670 times.
✓ Branch 1 taken 202216 times.
|
2/2✓ Decision 'true' taken 44670 times.
✓ Decision 'false' taken 202216 times.
|
246886 | if (reset_search) { |
147 | 44670 | bin.clear(); | ||
148 | 44670 | single_chain.clear(); | ||
149 |
1/2✓ Branch 2 taken 44670 times.
✗ Branch 3 not taken.
|
44670 | squasher_->clear(); | |
150 | 44670 | condition = std::nullopt; | ||
151 | } | |||
152 |
4/4✓ Branch 1 taken 246886 times.
✓ Branch 2 taken 9723 times.
✓ Branch 4 taken 246886 times.
✓ Branch 5 taken 9723 times.
|
513218 | } | |
153 | 9723 | return success; | ||
154 | 9723 | } | ||
155 | ||||
156 | 29483 | void SingleQubitSquash::substitute( | ||
157 | const Circuit &sub, const VertexVec &single_chain, Edge &e, | |||
158 | const Condition &condition) { | |||
159 | // backup edge | |||
160 |
2/4✓ Branch 1 taken 29483 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 29483 times.
✗ Branch 5 not taken.
|
29483 | VertPort backup = {next_vertex(e), next_port(e)}; | |
161 | ||||
162 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 29473 times.
|
2/2✓ Decision 'true' taken 10 times.
✓ Decision 'false' taken 29473 times.
|
29483 | if (condition) { |
163 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | circ_.substitute_conditional( | |
164 | 10 | sub, single_chain.front(), Circuit::VertexDeletion::No); | ||
165 | } else { | |||
166 |
1/2✓ Branch 2 taken 29473 times.
✗ Branch 3 not taken.
|
29473 | circ_.substitute(sub, single_chain.front(), Circuit::VertexDeletion::No); | |
167 | } | |||
168 |
1/2✓ Branch 1 taken 29483 times.
✗ Branch 2 not taken.
|
29483 | circ_.remove_vertices( | |
169 |
1/2✓ Branch 4 taken 29483 times.
✗ Branch 5 not taken.
|
58966 | VertexSet{single_chain.begin(), single_chain.end()}, | |
170 | Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::Yes); | |||
171 | ||||
172 | // restore backup | |||
173 |
1/2✓ Branch 1 taken 29483 times.
✗ Branch 2 not taken.
|
29483 | e = prev_edge(backup); | |
174 | 29483 | } | ||
175 | ||||
176 | 161 | void SingleQubitSquash::insert_left_over_gate( | ||
177 | Op_ptr left_over, const Edge &e, const Condition &condition) { | |||
178 |
2/2✓ Branch 0 taken 148 times.
✓ Branch 1 taken 13 times.
|
2/2✓ Decision 'true' taken 148 times.
✓ Decision 'false' taken 13 times.
|
161 | if (reversed_) { |
179 |
1/2✓ Branch 2 taken 148 times.
✗ Branch 3 not taken.
|
148 | left_over = left_over->dagger(); | |
180 | } | |||
181 | 161 | EdgeVec preds; | ||
182 | 161 | op_signature_t sigs; | ||
183 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 156 times.
|
2/2✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 156 times.
|
161 | if (condition) { |
184 | 5 | left_over = std::make_shared<Conditional>( | ||
185 |
1/2✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
|
10 | left_over, (unsigned)condition->first.size(), condition->second); | |
186 | } | |||
187 |
1/2✓ Branch 3 taken 161 times.
✗ Branch 4 not taken.
|
161 | Vertex new_v = circ_.add_vertex(left_over); | |
188 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 156 times.
|
2/2✓ Decision 'true' taken 10 times.
✓ Decision 'false' taken 151 times.
|
161 | if (condition) { |
189 |
2/2✓ Branch 5 taken 5 times.
✓ Branch 6 taken 5 times.
|
2/2✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 5 times.
|
10 | for (const VertPort &vp : condition->first) { |
190 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
|
5 | preds.push_back(circ_.get_nth_out_edge(vp.first, vp.second)); | |
191 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | sigs.push_back(EdgeType::Boolean); | |
192 | } | |||
193 | } | |||
194 |
1/2✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
|
161 | preds.push_back(e); | |
195 |
1/2✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
|
161 | sigs.push_back(EdgeType::Quantum); | |
196 |
1/2✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
|
161 | circ_.rewire(new_v, preds, sigs); | |
197 | 161 | } | ||
198 | ||||
199 | 37349 | bool SingleQubitSquash::sub_is_better( | ||
200 | const Circuit &sub, const std::vector<Gate_ptr> chain) const { | |||
201 | 37349 | const unsigned n_gates = sub.n_gates(); | ||
202 |
4/4✓ Branch 1 taken 7961 times.
✓ Branch 2 taken 29388 times.
✓ Branch 3 taken 7893 times.
✓ Branch 4 taken 68 times.
|
53203 | return n_gates < chain.size() || | |
203 |
2/2✓ Branch 2 taken 95 times.
✓ Branch 3 taken 7798 times.
|
53203 | (n_gates == chain.size() && !is_equal(sub, chain, reversed_)); | |
204 | } | |||
205 | ||||
206 | // returns a description of the condition of current vertex | |||
207 | 278 | SingleQubitSquash::Condition SingleQubitSquash::get_condition(Vertex v) const { | ||
208 |
1/2✓ Branch 1 taken 278 times.
✗ Branch 2 not taken.
|
278 | Op_ptr v_op = circ_.get_Op_ptr_from_Vertex(v); | |
209 | 278 | OpType v_type = v_op->get_type(); | ||
210 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 278 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 278 times.
|
278 | if (v_type != OpType::Conditional) { |
211 | ✗ | throw BadOpType("Cannot get condition from non-conditional OpType", v_type); | ||
212 | } | |||
213 | 278 | const Conditional &cond_op = static_cast<const Conditional &>(*v_op); | ||
214 |
1/2✓ Branch 1 taken 278 times.
✗ Branch 2 not taken.
|
278 | EdgeVec ins = circ_.get_in_edges(v); | |
215 | 278 | Condition cond = std::pair<std::list<VertPort>, unsigned>(); | ||
216 |
3/4✓ Branch 1 taken 664 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 386 times.
✓ Branch 4 taken 278 times.
|
0/1? Decision couldn't be analyzed.
|
664 | for (port_t p = 0; p < cond_op.get_width(); ++p) { |
217 |
1/2✓ Branch 1 taken 386 times.
✗ Branch 2 not taken.
|
386 | Edge in_p = ins.at(p); | |
218 |
2/4✓ Branch 1 taken 386 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 386 times.
✗ Branch 5 not taken.
|
386 | VertPort vp = {circ_.source(in_p), circ_.get_source_port(in_p)}; | |
219 |
1/2✓ Branch 2 taken 386 times.
✗ Branch 3 not taken.
|
386 | cond->first.push_back(vp); | |
220 | } | |||
221 |
1/2✓ Branch 1 taken 278 times.
✗ Branch 2 not taken.
|
278 | cond->second = cond_op.get_value(); | |
222 | 556 | return cond; | ||
223 | 278 | } | ||
224 | ||||
225 | // simple utils respecting reversed boolean | |||
226 | 286045 | Vertex SingleQubitSquash::next_vertex(const Edge &e) const { | ||
227 |
2/2✓ Branch 0 taken 284938 times.
✓ Branch 1 taken 1107 times.
|
286045 | return reversed_ ? circ_.source(e) : circ_.target(e); | |
228 | } | |||
229 | ||||
230 | 58001 | port_t SingleQubitSquash::next_port(const Edge &e) const { | ||
231 |
2/2✓ Branch 0 taken 57774 times.
✓ Branch 1 taken 227 times.
|
58001 | return reversed_ ? circ_.get_source_port(e) : circ_.get_target_port(e); | |
232 | } | |||
233 | ||||
234 | 29483 | Edge SingleQubitSquash::prev_edge(const VertPort &pair) const { | ||
235 | 29376 | return reversed_ ? circ_.get_nth_out_edge(pair.first, pair.second) | ||
236 |
2/2✓ Branch 0 taken 29376 times.
✓ Branch 1 taken 107 times.
|
29483 | : circ_.get_nth_in_edge(pair.first, pair.second); | |
237 | } | |||
238 | ||||
239 | 247000 | Edge SingleQubitSquash::next_edge(const Vertex &v, const Edge &e) const { | ||
240 |
2/2✓ Branch 0 taken 246317 times.
✓ Branch 1 taken 683 times.
|
247000 | return reversed_ ? circ_.get_last_edge(v, e) : circ_.get_next_edge(v, e); | |
241 | } | |||
242 | ||||
243 | 253807 | bool SingleQubitSquash::is_last_optype(OpType type) const { | ||
244 |
4/4✓ Branch 0 taken 253084 times.
✓ Branch 1 taken 723 times.
✓ Branch 3 taken 246207 times.
✓ Branch 4 taken 6877 times.
|
500737 | return (reversed_ && is_initial_q_type(type)) || | |
245 |
4/4✓ Branch 0 taken 723 times.
✓ Branch 1 taken 246207 times.
✓ Branch 3 taken 44 times.
✓ Branch 4 taken 679 times.
|
500737 | (!reversed_ && is_final_q_type(type)); | |
246 | } | |||
247 | ||||
248 | 15634 | bool SingleQubitSquash::is_equal( | ||
249 | const Circuit &circ, const std::vector<Gate_ptr> &gates, bool reversed) { | |||
250 |
2/2✓ Branch 0 taken 7741 times.
✓ Branch 1 taken 7893 times.
|
2/2✓ Decision 'true' taken 7741 times.
✓ Decision 'false' taken 7893 times.
|
15634 | if (reversed) { |
251 |
2/4✓ Branch 4 taken 7741 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 7741 times.
✗ Branch 8 not taken.
|
7741 | return is_equal(circ, {gates.rbegin(), gates.rend()}); | |
252 | } | |||
253 |
2/4✓ Branch 1 taken 7893 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 7893 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 7893 times.
|
7893 | if (circ.n_qubits() != 1) { |
254 | ✗ | throw CircuitInvalidity("Only circuits with one qubit are supported"); | ||
255 | } | |||
256 | ||||
257 |
1/2✓ Branch 1 taken 7893 times.
✗ Branch 2 not taken.
|
7893 | auto it1 = circ.begin(); | |
258 | 7893 | auto it2 = gates.cbegin(); | ||
259 | ||||
260 |
7/12✓ Branch 1 taken 26280 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18482 times.
✓ Branch 5 taken 7798 times.
✓ Branch 8 taken 18482 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 26280 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 18482 times.
✓ Branch 14 taken 7798 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
0/1? Decision couldn't be analyzed.
|
26280 | while (it1 != circ.end() && it2 != gates.end()) { |
261 |
1/2✓ Branch 3 taken 18482 times.
✗ Branch 4 not taken.
|
18482 | const Gate_ptr op1 = as_gate_ptr(it1->get_op_ptr()); | |
262 |
1/2✓ Branch 3 taken 18482 times.
✗ Branch 4 not taken.
|
18482 | const Gate_ptr op2 = as_gate_ptr(*it2); | |
263 |
3/4✓ Branch 3 taken 18482 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 95 times.
✓ Branch 6 taken 18387 times.
|
2/2✓ Decision 'true' taken 95 times.
✓ Decision 'false' taken 18387 times.
|
18482 | if (!(*op1 == *op2)) { |
264 | 95 | return false; | ||
265 | } | |||
266 |
1/2✓ Branch 1 taken 18387 times.
✗ Branch 2 not taken.
|
18387 | ++it1; | |
267 | 18387 | ++it2; | ||
268 |
4/4✓ Branch 1 taken 18387 times.
✓ Branch 2 taken 95 times.
✓ Branch 4 taken 18387 times.
✓ Branch 5 taken 95 times.
|
18577 | } | |
269 | ||||
270 |
5/12✓ Branch 1 taken 7798 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7798 times.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 7798 times.
✓ Branch 10 taken 7798 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 7798 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 7798 times.
|
7798 | if (it1 != circ.end() || it2 != gates.cend()) { |
271 | ✗ | return false; | ||
272 | } | |||
273 | 7798 | return true; | ||
274 | 7893 | } | ||
275 | ||||
276 | } // namespace tket | |||
277 |