GCC Code Coverage Report


Directory: ./
File: Characterisation/Cycles.cpp
Date: 2022-10-15 05:10:18
Warnings: 5 unchecked decisions!
Exec Total Coverage
Lines: 151 167 90.4%
Functions: 14 16 87.5%
Branches: 161 294 54.8%
Decisions: 57 78 73.1%

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 "Cycles.hpp"
16
17 #include <numeric>
18
19 namespace tket {
20
21 class CycleError : public std::logic_error {
22 public:
23 explicit CycleError(const std::string& message) : std::logic_error(message) {}
24 };
25
26 854 unsigned Cycle::size() const { return boundary_edges_.size(); }
27
28 44 void Cycle::add_vertex_pair(const std::pair<Vertex, Vertex>& verts) {
29 44 frame_vertices.push_back(verts);
30 44 }
31
32 778 std::vector<std::pair<Vertex, Vertex>> Cycle::get_frame() const {
33 778 return frame_vertices;
34 }
35
36 461 UnitID CycleFinder::unitid_from_unit_frontier(
37 const std::shared_ptr<unit_frontier_t>& u_frontier, const Edge& e) const {
38
4/8
✓ Branch 5 taken 898 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 437 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 898 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 898 times.
✗ Branch 14 not taken.
0/1
? Decision couldn't be analyzed.
898 for (const std::pair<UnitID, Edge>& pair : u_frontier->get<TagKey>()) {
39
3/4
✓ Branch 1 taken 898 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 461 times.
✓ Branch 4 taken 437 times.
2/2
✓ Decision 'true' taken 461 times.
✓ Decision 'false' taken 437 times.
898 if (pair.second == e) {
40 461 return pair.first;
41 }
42 }
43 throw CycleError(std::string("Edge not in unit_frontier_t object."));
44 }
45
46 461 void CycleFinder::update_cycle_out_edges(const UnitID& uid, const Edge& e) {
47
1/2
✓ Branch 5 taken 976 times.
✗ Branch 6 not taken.
1/2
✓ Decision 'true' taken 976 times.
✗ Decision 'false' not taken.
976 for (std::pair<const Edge, UnitID>& pair : cycle_out_edges) {
48
3/4
✓ Branch 1 taken 976 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 461 times.
✓ Branch 4 taken 515 times.
2/2
✓ Decision 'true' taken 461 times.
✓ Decision 'false' taken 515 times.
976 if (pair.second == uid) {
49
1/2
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
461 cycle_out_edges.erase(pair.first);
50
1/2
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
461 cycle_out_edges[e] = uid;
51 461 return;
52 }
53 }
54 throw CycleError(std::string(
55 "UnitID " + uid.repr() + " not in std::map<Edge, UnitID> object."));
56 return;
57 }
58
59 void Cycle::update_boundary(
60 const Edge& source_edge, const Edge& replacement_edge) {
61
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
for (unsigned i = 0; i < boundary_edges_.size(); i++) {
62
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (boundary_edges_[i].second == source_edge) {
63 boundary_edges_[i].second = replacement_edge;
64 return;
65 }
66 }
67 throw CycleError("Source Edge matches no edges in boundary to cycle.");
68 return;
69 }
70
71 154 void CycleFinder::erase_keys(
72 const unsigned& to_erase, std::set<unsigned>& erase_from) const {
73 154 std::set<unsigned> all_erased;
74
2/2
✓ Branch 5 taken 155 times.
✓ Branch 6 taken 154 times.
2/2
✓ Decision 'true' taken 155 times.
✓ Decision 'false' taken 154 times.
309 for (const unsigned& key : erase_from) {
75
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 1 times.
2/2
✓ Decision 'true' taken 154 times.
✓ Decision 'false' taken 1 times.
155 if (key <= to_erase) {
76
1/2
✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
154 all_erased.insert(key);
77 }
78 }
79
3/4
✓ Branch 4 taken 154 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 154 times.
✓ Branch 9 taken 154 times.
0/1
? Decision couldn't be analyzed.
308 for (const unsigned& key : all_erased) erase_from.erase(key);
80 154 }
81
82 // Adds a new cycle to bt.key_to_cycle
83 323 std::pair<unsigned, std::set<unsigned>> CycleFinder::make_cycle(
84 const Vertex& v, const EdgeVec& out_edges, const CutFrontier& cut) {
85 // Make a new boundary, add it to "all_boundaries", update "boundary_key" map
86 323 std::vector<edge_pair_t> new_cycle_boundary;
87 323 std::vector<UnitID> new_boundary_uids;
88 323 std::set<unsigned> old_boundary_keys;
89 323 std::set<unsigned> banned_keys;
90
91 // Get UnitID, add to uids for new boundary, keep note of all old boundary
92 // keys for merging set new boundary key, add new edges to new boundary update
93 // cycle out edges if the edge can't be found
94
2/2
✓ Branch 5 taken 461 times.
✓ Branch 6 taken 323 times.
2/2
✓ Decision 'true' taken 461 times.
✓ Decision 'false' taken 323 times.
784 for (const Edge& e : out_edges) {
95
1/2
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
461 UnitID uid = unitid_from_unit_frontier(cut.u_frontier, e);
96
1/2
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
461 new_boundary_uids.push_back(uid);
97
2/4
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 461 times.
✗ Branch 5 not taken.
461 old_boundary_keys.insert(bt.uid_to_key[uid]);
98
99 // boundary key associated with given edge e not included
100 // i.e. e's associated in edge isn't a cycle out edge
101 // i.e. some other non-cycle gate has been passed
102
2/4
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 461 times.
✗ Branch 5 not taken.
2/2
✓ Decision 'true' taken 155 times.
✓ Decision 'false' taken 306 times.
461 if (cycle_out_edges.find(circ.get_last_edge(v, e)) ==
103
2/2
✓ Branch 1 taken 155 times.
✓ Branch 2 taken 306 times.
922 cycle_out_edges.end()) {
104
2/4
✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
155 banned_keys.insert(bt.uid_to_key[uid]);
105 }
106
1/2
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
461 bt.uid_to_key[uid] = bt.key;
107
2/4
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 461 times.
✗ Branch 6 not taken.
461 new_cycle_boundary.push_back({circ.get_last_edge(v, e), e});
108
1/2
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
461 update_cycle_out_edges(uid, e);
109 461 }
110
111
1/2
✓ Branch 3 taken 323 times.
✗ Branch 4 not taken.
323 std::vector<unsigned> op_indices(out_edges.size());
112 323 std::iota(op_indices.begin(), op_indices.end(), 0);
113 // Edges in port ordering
114 Cycle new_cycle(
115
4/8
✓ Branch 1 taken 323 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 323 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 323 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 323 times.
✗ Branch 12 not taken.
969 new_cycle_boundary, {{circ.get_OpType_from_Vertex(v), op_indices, v}});
116
2/4
✓ Branch 1 taken 323 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 323 times.
✗ Branch 5 not taken.
323 bt.key_to_cycle[bt.key] = {new_cycle};
117
118
1/2
✓ Branch 1 taken 323 times.
✗ Branch 2 not taken.
323 bt.history.push_back(new_boundary_uids);
119
2/2
✓ Branch 5 taken 154 times.
✓ Branch 6 taken 323 times.
2/2
✓ Decision 'true' taken 154 times.
✓ Decision 'false' taken 323 times.
477 for (const unsigned& key : banned_keys) {
120
1/2
✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
154 erase_keys(key, old_boundary_keys);
121 }
122 std::pair<unsigned, std::set<unsigned>> return_keys = {
123
1/2
✓ Branch 1 taken 323 times.
✗ Branch 2 not taken.
323 bt.key, old_boundary_keys};
124 323 bt.key++;
125 646 return return_keys;
126 323 }
127
128 // "old_keys" returned gives keys for boundaries to be merged together
129 // these "old_keys" are keys corresponding to boundaries UnitIDs in new boundary
130 // were in previously if two keys in passed old_keys have overlapping UnitIDs,
131 // then they cannot be merged in this case, remove the 'earlier' boundary from
132 // keys to be merged
133 170 void CycleFinder::order_keys(
134 unsigned& new_key, std::set<unsigned>& old_keys) const {
135 170 std::set<unsigned> bad_keys;
136
2/2
✓ Branch 3 taken 300 times.
✓ Branch 4 taken 170 times.
2/2
✓ Decision 'true' taken 300 times.
✓ Decision 'false' taken 170 times.
470 for (std::set<unsigned>::iterator it = old_keys.begin(); it != old_keys.end();
137 300 ++it) {
138 300 std::set<unsigned>::iterator jt = it;
139
1/2
✓ Branch 1 taken 300 times.
✗ Branch 2 not taken.
300 std::advance(jt, 1);
140 // if either std::vector<UnitID> has common UnitIDs then one is causally
141 // blocked. remove smaller key from keys from set as not a candidate for
142 // merging into
143
2/2
✓ Branch 3 taken 130 times.
✓ Branch 4 taken 300 times.
2/2
✓ Decision 'true' taken 130 times.
✓ Decision 'false' taken 300 times.
430 for (; jt != old_keys.end(); ++jt)
144
2/2
✓ Branch 7 taken 391 times.
✓ Branch 8 taken 130 times.
2/2
✓ Decision 'true' taken 391 times.
✓ Decision 'false' taken 130 times.
521 for (const UnitID& u0 : bt.history[*it])
145
2/2
✓ Branch 7 taken 415 times.
✓ Branch 8 taken 391 times.
2/2
✓ Decision 'true' taken 415 times.
✓ Decision 'false' taken 391 times.
806 for (const UnitID& u1 : bt.history[*jt])
146
2/4
✓ Branch 1 taken 415 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 415 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 415 times.
415 if (u0 == u1) {
147 bad_keys.insert(*it);
148 goto new_loop;
149 }
150
151 300 new_loop : {}
152 }
153
154
1/4
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 170 times.
0/1
? Decision couldn't be analyzed.
170 for (const unsigned& key : bad_keys) old_keys.erase(key);
155
1/2
✓ Branch 1 taken 170 times.
✗ Branch 2 not taken.
170 old_keys.insert(new_key);
156 170 }
157
158 300 void Cycle::update_coms_indices(
159 const std::map<unsigned, unsigned>& new_indices) {
160
2/2
✓ Branch 5 taken 306 times.
✓ Branch 6 taken 300 times.
2/2
✓ Decision 'true' taken 306 times.
✓ Decision 'false' taken 300 times.
606 for (CycleCom& com : coms_) {
161
2/2
✓ Branch 4 taken 412 times.
✓ Branch 5 taken 306 times.
2/2
✓ Decision 'true' taken 412 times.
✓ Decision 'false' taken 306 times.
718 for (unsigned& index : com.indices) {
162
1/2
✓ Branch 1 taken 412 times.
✗ Branch 2 not taken.
412 index = new_indices.at(index);
163 }
164 }
165 300 }
166
167 // new cycle is made
168 // it may need to be immediately merged into other cycles
169 // 1) check for overlap of UnitID between cycles of "old_keys"
170 // if overlap, remove lowest value key from set
171 // 2) add "new_key" to "old_keys", merge all boundaries into corresponding
172 // boundary to highest value "old_key"
173 300 void Cycle::merge(Cycle& new_cycle) {
174 // iterate through edges in boundary of new_cycle
175 300 std::map<unsigned, unsigned> new_indices;
176
2/2
✓ Branch 1 taken 436 times.
✓ Branch 2 taken 300 times.
2/2
✓ Decision 'true' taken 436 times.
✓ Decision 'false' taken 300 times.
736 for (unsigned i = 0; i < new_cycle.boundary_edges_.size(); i++) {
177 436 bool match = false;
178
2/2
✓ Branch 1 taken 838 times.
✓ Branch 2 taken 131 times.
2/2
✓ Decision 'true' taken 838 times.
✓ Decision 'false' taken 131 times.
969 for (unsigned j = 0; j < boundary_edges_.size(); j++) {
179 // if in edge of boundary of new_cycle matches out of edge *this, update
180 // *this out edge
181
3/4
✓ Branch 3 taken 838 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 305 times.
✓ Branch 6 taken 533 times.
2/2
✓ Decision 'true' taken 305 times.
✓ Decision 'false' taken 533 times.
838 if (boundary_edges_[j].second == new_cycle.boundary_edges_[i].first) {
182 305 boundary_edges_[j].second = new_cycle.boundary_edges_[i].second;
183 // As CycleCom are labelled by basic indexing system, where indexing is
184 // related to position edge has in boundary Update CycleCom in new_cycle
185 // s.t. edges with index i now have index j update commands in new_cycle
186 // to match edgesindexing of *this for now, store new indexing
187
1/2
✓ Branch 1 taken 305 times.
✗ Branch 2 not taken.
305 new_indices[i] = j;
188 305 match = true;
189 305 break;
190 }
191 }
192
2/2
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 305 times.
2/2
✓ Decision 'true' taken 131 times.
✓ Decision 'false' taken 305 times.
436 if (!match) {
193
1/2
✓ Branch 2 taken 131 times.
✗ Branch 3 not taken.
131 boundary_edges_.push_back(new_cycle.boundary_edges_[i]);
194
1/2
✓ Branch 2 taken 131 times.
✗ Branch 3 not taken.
131 new_indices[i] = boundary_edges_.size() - 1;
195 }
196 }
197 // update CycleCom indices in new_cycle
198
1/2
✓ Branch 1 taken 300 times.
✗ Branch 2 not taken.
300 new_cycle.update_coms_indices(new_indices);
199
1/2
✓ Branch 5 taken 300 times.
✗ Branch 6 not taken.
300 coms_.insert(coms_.end(), new_cycle.coms_.begin(), new_cycle.coms_.end());
200 300 }
201
202 170 void CycleFinder::merge_cycles(unsigned new_key, std::set<unsigned>& old_keys) {
203 // boundary_keys is a std::set<unsigned> so is ordered
204
1/2
✓ Branch 1 taken 170 times.
✗ Branch 2 not taken.
170 order_keys(new_key, old_keys);
205 // all cycles corresponding to keys in boundary_keys should be merged into
206 // boundary with smallest value
207 170 std::set<unsigned>::iterator it = old_keys.begin();
208 170 unsigned base_key = *it;
209
1/2
✓ Branch 1 taken 170 times.
✗ Branch 2 not taken.
170 std::advance(it, 1);
210
2/2
✓ Branch 3 taken 300 times.
✓ Branch 4 taken 170 times.
2/2
✓ Decision 'true' taken 300 times.
✓ Decision 'false' taken 170 times.
470 for (; it != old_keys.end(); ++it) {
211 300 unsigned merge_key = *it;
212
3/6
✓ Branch 1 taken 300 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 300 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 300 times.
✗ Branch 8 not taken.
300 bt.key_to_cycle[base_key].merge(bt.key_to_cycle[merge_key]);
213
1/2
✓ Branch 1 taken 300 times.
✗ Branch 2 not taken.
300 bt.key_to_cycle.erase(merge_key);
214 // update bt.history for "base_key"
215
2/2
✓ Branch 6 taken 442 times.
✓ Branch 7 taken 300 times.
2/2
✓ Decision 'true' taken 442 times.
✓ Decision 'false' taken 300 times.
742 for (const UnitID& u0 : bt.history[merge_key]) {
216
1/2
✓ Branch 1 taken 442 times.
✗ Branch 2 not taken.
442 bt.uid_to_key[u0] = base_key;
217
2/2
✓ Branch 6 taken 1338 times.
✓ Branch 7 taken 131 times.
2/2
✓ Decision 'true' taken 1338 times.
✓ Decision 'false' taken 131 times.
1469 for (const UnitID& u1 : bt.history[base_key])
218
3/4
✓ Branch 1 taken 1338 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 311 times.
✓ Branch 4 taken 1027 times.
2/2
✓ Decision 'true' taken 442 times.
✓ Decision 'false' taken 896 times.
1338 if (u0 == u1) break;
219
1/2
✓ Branch 2 taken 442 times.
✗ Branch 3 not taken.
442 bt.history[base_key].push_back(u0);
220 }
221 }
222 170 }
223
224 204 void CycleFinder::extend_cycles(const CutFrontier& cut) {
225 // For each vertex in slice
226 // Make a new "cycle"
227 // If any in edge to new cycle matches an out edge to a previous cycle,
228 // attempt to merge cycles together
229
2/2
✓ Branch 6 taken 323 times.
✓ Branch 7 taken 204 times.
2/2
✓ Decision 'true' taken 323 times.
✓ Decision 'false' taken 204 times.
527 for (const Vertex& v : *cut.slice) {
230
1/2
✓ Branch 1 taken 323 times.
✗ Branch 2 not taken.
323 EdgeVec in_edges = circ.get_in_edges_of_type(v, EdgeType::Quantum);
231
1/2
✓ Branch 1 taken 323 times.
✗ Branch 2 not taken.
323 EdgeVec out_edges = circ.get_out_edges_of_type(v, EdgeType::Quantum);
232 // Compare EdgeType::Quantum "in_edges" of vertex in slice to collection of
233 // out edges from "active" boundaries If an "in_edge" is not equivalent to
234 // an out edge from "active" boundary, implies vertex needs to start a new
235 // boundary
236 std::pair<unsigned, std::set<unsigned>> all_keys =
237
1/2
✓ Branch 1 taken 323 times.
✗ Branch 2 not taken.
323 make_cycle(v, out_edges, cut);
238
2/2
✓ Branch 1 taken 170 times.
✓ Branch 2 taken 153 times.
2/2
✓ Decision 'true' taken 170 times.
✓ Decision 'false' taken 153 times.
323 if (all_keys.second.size() > 0) {
239
1/2
✓ Branch 1 taken 170 times.
✗ Branch 2 not taken.
170 merge_cycles(all_keys.first, all_keys.second);
240 }
241 323 }
242 204 }
243
244 19 std::vector<Cycle> CycleFinder::get_cycles() {
245 923 std::function<bool(Op_ptr)> skip_func = [&](Op_ptr op) {
246
1/2
✓ Branch 4 taken 923 times.
✗ Branch 5 not taken.
923 return (cycle_types_.find(op->get_type()) == cycle_types_.end());
247 19 };
248
249
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 Circuit::SliceIterator slice_iter(circ, skip_func);
250 19 bt.key = 0;
251
252 // initialization
253
2/4
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 19 times.
✗ Branch 6 not taken.
1/2
✓ Decision 'true' taken 19 times.
✗ Decision 'false' not taken.
19 if (!(*slice_iter).empty()) {
254 19 for (const std::pair<UnitID, Edge>& pair :
255
5/8
✓ Branch 5 taken 49 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 49 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 68 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 49 times.
✓ Branch 14 taken 19 times.
87 slice_iter.cut_.u_frontier->get<TagKey>()) {
256 49 Edge in_edge = pair.second;
257
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✗ Branch 4 not taken.
1/2
✓ Decision 'true' taken 49 times.
✗ Decision 'false' not taken.
49 if (circ.get_edgetype(in_edge) != EdgeType::Classical) {
258
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 Vertex in_vert = circ.source(pair.second);
259
260 // if vertex is type from types, then vertex is in slice and need
261 // in_edge. else can ignore.
262
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
2/2
✓ Decision 'true' taken 36 times.
✓ Decision 'false' taken 13 times.
49 if (cycle_types_.find(circ.get_OpType_from_Vertex(in_vert)) !=
263
2/2
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 13 times.
98 cycle_types_.end()) {
264
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 in_edge = circ.get_last_edge(in_vert, pair.second);
265 }
266
267
1/2
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
49 cycle_out_edges.insert({in_edge, pair.first});
268
1/2
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
49 bt.uid_to_key.insert({pair.first, bt.key});
269
3/6
✓ Branch 3 taken 49 times.
✗ Branch 4 not taken.
✓ Branch 8 taken 49 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 49 times.
✗ Branch 12 not taken.
147 Cycle new_cycle({{in_edge, in_edge}}, {{}});
270
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
49 bt.key_to_cycle[bt.key] = new_cycle;
271
4/8
✓ Branch 3 taken 49 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 49 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 49 times.
✓ Branch 11 taken 49 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
98 bt.history.push_back({pair.first});
272 49 bt.key++;
273 49 }
274 }
275 // extend cycles automatically merges cycles that can be merge due to
276 // overlapping multi-qubit gates
277
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 extend_cycles(slice_iter.cut_);
278
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 cycle_out_edges = {};
279 19 for (const std::pair<UnitID, Edge>& pair :
280
4/6
✓ Branch 5 taken 49 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 68 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 49 times.
✓ Branch 11 taken 19 times.
87 slice_iter.cut_.u_frontier->get<TagKey>()) {
281
2/4
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 49 times.
✗ Branch 7 not taken.
49 cycle_out_edges.insert({pair.second, pair.first});
282 }
283 }
284
3/4
✓ Branch 1 taken 205 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 186 times.
✓ Branch 4 taken 19 times.
0/1
? Decision couldn't be analyzed.
205 while (!slice_iter.finished()) {
285
1/2
✓ Branch 3 taken 186 times.
✗ Branch 4 not taken.
372 slice_iter.cut_ = circ.next_cut(
286 186 slice_iter.cut_.u_frontier, slice_iter.cut_.b_frontier, skip_func);
287
3/4
✓ Branch 1 taken 186 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 185 times.
✓ Branch 6 taken 1 times.
2/2
✓ Decision 'true' taken 185 times.
✓ Decision 'false' taken 1 times.
186 if (!(*slice_iter).empty()) {
288
1/2
✓ Branch 1 taken 185 times.
✗ Branch 2 not taken.
185 extend_cycles(slice_iter.cut_);
289 }
290 }
291
292 // Skim Cycle type from CycleHistory.key_to_cycle
293 // Discard any Cycles with only Input Gates
294 19 std::vector<Cycle> output_cycles;
295
3/4
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 72 times.
✓ Branch 9 taken 19 times.
0/1
? Decision couldn't be analyzed.
91 for (std::pair<unsigned, Cycle> entry : bt.key_to_cycle) {
296
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 72 times.
72 if (entry.second.coms_.size() == 0) {
297 throw CycleError(std::string("Cycle with no internal gates."));
298 }
299
2/4
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 72 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 72 times.
72 if (entry.second.boundary_edges_[0].first ==
300 72 entry.second.boundary_edges_[0].second) {
301 continue;
302 }
303
3/6
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 72 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 72 times.
72 if (entry.second.size() > circ.n_qubits()) {
304 throw CycleError(
305 std::string("Cycle has a larger frame than Circuit has qubits."));
306 }
307
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 output_cycles.push_back(entry.second);
308
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 }
309 38 return output_cycles;
310 19 }
311 } // namespace tket
312