GCC Code Coverage Report


Directory: ./
File: Circuit/setters_and_getters.cpp
Date: 2022-10-15 05:10:18
Warnings: 4 unchecked decisions!
Exec Total Coverage
Lines: 416 447 93.1%
Functions: 75 80 93.8%
Branches: 497 888 56.0%
Decisions: 106 138 76.8%

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 ////////////////////////////////////////////////////////
16 // ALL METHODS TO SET AND GET BASIC CIRCUIT INFORMATION//
17 ////////////////////////////////////////////////////////
18
19 #include <stdexcept>
20 #include <tkassert/Assert.hpp>
21 #include <tklog/TketLog.hpp>
22
23 #include "Circuit.hpp"
24 #include "DAGDefs.hpp"
25 #include "DAGProperties.hpp"
26 #include "OpType/OpDesc.hpp"
27 #include "OpType/OpType.hpp"
28 #include "Ops/OpPtr.hpp"
29 #include "Utils/GraphHeaders.hpp"
30
31 namespace tket {
32
33 Circuit::Circuit(const std::string &_name) : Circuit() { name = _name; }
34
35 257407 Circuit::Circuit(unsigned n, const std::optional<std::string> _name)
36 257407 : Circuit() {
37
1/2
✓ Branch 1 taken 257407 times.
✗ Branch 2 not taken.
257407 name = _name;
38
3/6
✓ Branch 1 taken 257407 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 257407 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 257407 times.
✗ Branch 8 not taken.
257407 add_q_register(q_default_reg(), n);
39 257407 }
40
41 244 Circuit::Circuit(unsigned n, unsigned m, const std::optional<std::string> _name)
42
1/2
✓ Branch 2 taken 244 times.
✗ Branch 3 not taken.
244 : Circuit(n, _name) {
43
3/6
✓ Branch 1 taken 244 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 244 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 244 times.
✗ Branch 8 not taken.
244 add_c_register(c_default_reg(), m);
44 244 }
45
46 // Copy constructor.
47 // Makes no assumptions about the graph
48 99336 Circuit::Circuit(const Circuit &circ) : Circuit() {
49
1/2
✓ Branch 1 taken 99336 times.
✗ Branch 2 not taken.
99336 copy_graph(circ);
50
1/2
✓ Branch 1 taken 99336 times.
✗ Branch 2 not taken.
99336 phase = circ.get_phase();
51
1/2
✓ Branch 1 taken 99336 times.
✗ Branch 2 not taken.
99336 name = circ.name;
52 99336 }
53
54 // copy assignment. Moves boundary pointers.
55 80844 Circuit &Circuit::operator=(const Circuit &other) // (1)
56 {
57
2/4
✓ Branch 1 taken 80844 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 80844 times.
✗ Branch 5 not taken.
80844 dag = DAG();
58
1/2
✓ Branch 2 taken 80844 times.
✗ Branch 3 not taken.
80844 boundary = boundary_t();
59 80844 copy_graph(other);
60 80844 phase = other.get_phase();
61 80844 name = other.name;
62 80844 return *this;
63 }
64
65 57 void Circuit::assert_valid() const { //
66 TKET_ASSERT(is_valid(dag));
67 57 }
68
69 182 VertexVec Circuit::all_inputs() const {
70
1/2
✓ Branch 1 taken 182 times.
✗ Branch 2 not taken.
182 VertexVec ins = q_inputs();
71
1/2
✓ Branch 1 taken 182 times.
✗ Branch 2 not taken.
182 VertexVec c_ins = c_inputs();
72
1/2
✓ Branch 5 taken 182 times.
✗ Branch 6 not taken.
182 ins.insert(ins.end(), c_ins.begin(), c_ins.end());
73 364 return ins;
74 182 }
75
76 9932 VertexVec Circuit::q_inputs() const {
77 9932 VertexVec ins;
78
1/2
✓ Branch 2 taken 9932 times.
✗ Branch 3 not taken.
1/2
✓ Decision 'true' taken 9932 times.
✗ Decision 'false' not taken.
9932 for (auto [it, end] = boundary.get<TagType>().equal_range(UnitType::Qubit);
79
4/6
✓ Branch 1 taken 15228 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 25160 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15228 times.
✓ Branch 7 taken 9932 times.
25160 it != end; it++) {
80
2/4
✓ Branch 1 taken 15228 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 15228 times.
✗ Branch 5 not taken.
15228 ins.push_back(it->in_);
81 }
82 9932 return ins;
83 }
84
85 193 VertexVec Circuit::c_inputs() const {
86 193 VertexVec ins;
87
1/2
✓ Branch 2 taken 193 times.
✗ Branch 3 not taken.
1/2
✓ Decision 'true' taken 193 times.
✗ Decision 'false' not taken.
193 for (auto [it, end] = boundary.get<TagType>().equal_range(UnitType::Bit);
88
4/6
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 26 times.
✓ Branch 7 taken 193 times.
219 it != end; it++) {
89
2/4
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
26 ins.push_back(it->in_);
90 }
91 193 return ins;
92 }
93
94 9 VertexVec Circuit::all_outputs() const {
95
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 VertexVec outs = q_outputs();
96
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 VertexVec c_outs = c_outputs();
97
1/2
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
9 outs.insert(outs.end(), c_outs.begin(), c_outs.end());
98 18 return outs;
99 9 }
100
101 6564 VertexVec Circuit::q_outputs() const {
102 6564 VertexVec outs;
103
1/2
✓ Branch 2 taken 6564 times.
✗ Branch 3 not taken.
1/2
✓ Decision 'true' taken 6564 times.
✗ Decision 'false' not taken.
6564 for (auto [it, end] = boundary.get<TagType>().equal_range(UnitType::Qubit);
104
4/6
✓ Branch 1 taken 10183 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16747 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10183 times.
✓ Branch 7 taken 6564 times.
16747 it != end; it++) {
105
2/4
✓ Branch 1 taken 10183 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10183 times.
✗ Branch 5 not taken.
10183 outs.push_back(it->out_);
106 }
107 6564 return outs;
108 }
109
110 18 VertexVec Circuit::c_outputs() const {
111 18 VertexVec outs;
112
1/2
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
1/2
✓ Decision 'true' taken 18 times.
✗ Decision 'false' not taken.
18 for (auto [it, end] = boundary.get<TagType>().equal_range(UnitType::Bit);
113
4/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
✓ Branch 7 taken 18 times.
38 it != end; it++) {
114
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
20 outs.push_back(it->out_);
115 }
116 18 return outs;
117 }
118
119 133061 qubit_vector_t Circuit::all_qubits() const {
120 133061 qubit_vector_t all_qbs;
121
1/2
✓ Branch 2 taken 133061 times.
✗ Branch 3 not taken.
1/2
✓ Decision 'true' taken 133061 times.
✗ Decision 'false' not taken.
133061 for (auto [it, end] = boundary.get<TagType>().equal_range(UnitType::Qubit);
122
3/4
✓ Branch 1 taken 623071 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 490010 times.
✓ Branch 4 taken 133061 times.
623071 it != end; it++) {
123
4/8
✓ Branch 1 taken 490010 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 490010 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 490010 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 490010 times.
✗ Branch 12 not taken.
490010 all_qbs.push_back(Qubit(it->id_));
124 }
125
1/2
✓ Branch 3 taken 133061 times.
✗ Branch 4 not taken.
133061 std::sort(all_qbs.begin(), all_qbs.end());
126 133061 return all_qbs;
127 }
128
129 350 qubit_vector_t Circuit::created_qubits() const {
130 350 qubit_vector_t all_created_qbs;
131
3/4
✓ Branch 1 taken 350 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 980 times.
✓ Branch 9 taken 350 times.
0/1
? Decision couldn't be analyzed.
1330 for (const Qubit &q : all_qubits()) {
132
3/4
✓ Branch 1 taken 980 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 950 times.
2/2
✓ Decision 'true' taken 30 times.
✓ Decision 'false' taken 950 times.
980 if (is_created(q)) {
133
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 all_created_qbs.push_back(q);
134 }
135 350 }
136 350 return all_created_qbs;
137 }
138
139 348 qubit_vector_t Circuit::discarded_qubits() const {
140 348 qubit_vector_t all_discarded_qbs;
141
3/4
✓ Branch 1 taken 348 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 976 times.
✓ Branch 9 taken 348 times.
0/1
? Decision couldn't be analyzed.
1324 for (const Qubit &q : all_qubits()) {
142
3/4
✓ Branch 1 taken 976 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 968 times.
2/2
✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 968 times.
976 if (is_discarded(q)) {
143
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 all_discarded_qbs.push_back(q);
144 }
145 348 }
146 348 return all_discarded_qbs;
147 }
148
149 24905 bit_vector_t Circuit::all_bits() const {
150 24905 bit_vector_t all_bs;
151
1/2
✓ Branch 2 taken 24905 times.
✗ Branch 3 not taken.
1/2
✓ Decision 'true' taken 24905 times.
✗ Decision 'false' not taken.
24905 for (auto [it, end] = boundary.get<TagType>().equal_range(UnitType::Bit);
152
3/4
✓ Branch 1 taken 26052 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1147 times.
✓ Branch 4 taken 24905 times.
26052 it != end; it++) {
153
4/8
✓ Branch 1 taken 1147 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1147 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1147 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 1147 times.
✗ Branch 12 not taken.
1147 all_bs.push_back(Bit(it->id_));
154 }
155
1/2
✓ Branch 3 taken 24905 times.
✗ Branch 4 not taken.
24905 std::sort(all_bs.begin(), all_bs.end());
156 24905 return all_bs;
157 }
158
159 199 unit_vector_t Circuit::all_units() const {
160 199 unit_vector_t all_us;
161
5/8
✓ Branch 4 taken 1594 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1594 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1793 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1594 times.
✓ Branch 13 taken 199 times.
0/1
? Decision couldn't be analyzed.
1793 for (const BoundaryElement &el : boundary.get<TagID>()) {
162
1/2
✓ Branch 1 taken 1594 times.
✗ Branch 2 not taken.
1594 all_us.push_back(el.id_);
163 }
164 199 return all_us;
165 }
166
167 47 std::map<Bit, unsigned> Circuit::bit_readout() const {
168 47 std::map<Bit, unsigned> res;
169
170 // Order bits to generate indices
171
1/2
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
47 bit_vector_t all_bs = all_bits();
172
1/2
✓ Branch 3 taken 47 times.
✗ Branch 4 not taken.
47 std::sort(all_bs.begin(), all_bs.end());
173 47 unsigned i = 0;
174
2/2
✓ Branch 4 taken 167 times.
✓ Branch 5 taken 47 times.
2/2
✓ Decision 'true' taken 167 times.
✓ Decision 'false' taken 47 times.
214 for (const Bit &b : all_bs) {
175
1/2
✓ Branch 2 taken 167 times.
✗ Branch 3 not taken.
167 res.insert({b, i});
176 167 i++;
177 }
178
179 94 return res;
180 47 }
181
182 46 std::map<Qubit, unsigned> Circuit::qubit_readout() const {
183 46 std::map<Qubit, unsigned> res;
184
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 std::map<Bit, unsigned> bmap = bit_readout();
185
186 // Find measurement map from qubits to index
187
1/2
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
1/2
✓ Decision 'true' taken 46 times.
✗ Decision 'false' not taken.
46 for (auto [it, end] = boundary.get<TagType>().equal_range(UnitType::Qubit);
188
4/6
✓ Branch 1 taken 163 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 209 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 163 times.
✓ Branch 7 taken 46 times.
209 it != end; it++) {
189
1/2
✓ Branch 1 taken 163 times.
✗ Branch 2 not taken.
163 Vertex q_out = it->out_;
190
2/4
✓ Branch 1 taken 163 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 163 times.
✗ Branch 5 not taken.
163 Vertex last_gate = source(get_nth_in_edge(q_out, 0));
191
3/4
✓ Branch 1 taken 163 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 162 times.
✓ Branch 4 taken 1 times.
2/2
✓ Decision 'true' taken 162 times.
✓ Decision 'false' taken 1 times.
163 if (get_OpType_from_Vertex(last_gate) == OpType::Measure) {
192
2/4
✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 162 times.
✗ Branch 5 not taken.
162 Vertex possible_c_out = target(get_nth_out_edge(last_gate, 1));
193
3/4
✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 161 times.
✓ Branch 4 taken 1 times.
2/2
✓ Decision 'true' taken 161 times.
✓ Decision 'false' taken 1 times.
162 if (get_OpType_from_Vertex(possible_c_out) == OpType::ClOutput) {
194
2/4
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 161 times.
✗ Branch 5 not taken.
161 Bit b(get_id_from_out(possible_c_out));
195
4/8
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 161 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 161 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 161 times.
✗ Branch 12 not taken.
161 res.insert({Qubit(it->id_), bmap.at(b)});
196 161 }
197 }
198 }
199
200 92 return res;
201 46 }
202
203 1 std::map<Qubit, Bit> Circuit::qubit_to_bit_map() const {
204 1 std::map<Qubit, Bit> res;
205
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1/2
✓ Decision 'true' taken 1 times.
✗ Decision 'false' not taken.
1 for (auto [it, end] = boundary.get<TagType>().equal_range(UnitType::Qubit);
206
4/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 1 times.
5 it != end; it++) {
207
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 Vertex q_out = it->out_;
208
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 Vertex last_gate = source(get_nth_in_edge(q_out, 0));
209
3/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1 times.
2/2
✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 1 times.
4 if (get_OpType_from_Vertex(last_gate) == OpType::Measure) {
210
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 Vertex possible_c_out = target(get_nth_out_edge(last_gate, 1));
211
3/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 1 times.
3 if (get_OpType_from_Vertex(possible_c_out) == OpType::ClOutput) {
212
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 Bit b(get_id_from_out(possible_c_out));
213
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
2 res.insert({Qubit(it->id_), b});
214 2 }
215 }
216 }
217
218 1 return res;
219 }
220
221 415 bool Circuit::contains_unit(const UnitID &id) const {
222
2/4
✓ Branch 4 taken 415 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 415 times.
✗ Branch 8 not taken.
415 return boundary.get<TagID>().find(id) != boundary.get<TagID>().end();
223 }
224
225 430689 Vertex Circuit::get_in(const UnitID &id) const {
226
1/2
✓ Branch 2 taken 430689 times.
✗ Branch 3 not taken.
430689 boundary_t::iterator found = boundary.get<TagID>().find(id);
227
3/4
✓ Branch 3 taken 430689 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 430685 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 430685 times.
430689 if (found == boundary.get<TagID>().end())
228
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 throw CircuitInvalidity(
229
2/4
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
8 "Circuit does not contain unit with id: " + id.repr());
230
1/2
✓ Branch 1 taken 430685 times.
✗ Branch 2 not taken.
430685 return found->in_;
231 }
232
233 1087706 Vertex Circuit::get_out(const UnitID &id) const {
234
1/2
✓ Branch 2 taken 1087706 times.
✗ Branch 3 not taken.
1087706 boundary_t::iterator found = boundary.get<TagID>().find(id);
235
2/4
✓ Branch 3 taken 1087706 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1087706 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1087706 times.
1087706 if (found == boundary.get<TagID>().end())
236 throw CircuitInvalidity(
237 "Circuit does not contain unit with id: " + id.repr());
238
1/2
✓ Branch 1 taken 1087706 times.
✗ Branch 2 not taken.
1087706 return found->out_;
239 }
240
241 20285 UnitID Circuit::get_id_from_in(const Vertex &in) const {
242 boundary_t::index<TagIn>::type::iterator found =
243
1/2
✓ Branch 2 taken 20285 times.
✗ Branch 3 not taken.
20285 boundary.get<TagIn>().find(in);
244
2/4
✓ Branch 3 taken 20285 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 20285 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 20285 times.
20285 if (found == boundary.get<TagIn>().end())
245 throw CircuitInvalidity("Input not found in Circuit");
246
1/2
✓ Branch 1 taken 20285 times.
✗ Branch 2 not taken.
40570 return found->id_;
247 }
248
249 20561 UnitID Circuit::get_id_from_out(const Vertex &out) const {
250 boundary_t::index<TagOut>::type::iterator found =
251
1/2
✓ Branch 2 taken 20561 times.
✗ Branch 3 not taken.
20561 boundary.get<TagOut>().find(out);
252
2/4
✓ Branch 3 taken 20561 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 20561 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 20561 times.
20561 if (found == boundary.get<TagOut>().end())
253 throw CircuitInvalidity("Output not found in Circuit");
254
1/2
✓ Branch 1 taken 20561 times.
✗ Branch 2 not taken.
41122 return found->id_;
255 }
256
257 1118132 opt_reg_info_t Circuit::get_reg_info(std::string reg_name) const {
258 boundary_t::index<TagReg>::type::iterator found =
259
1/2
✓ Branch 2 taken 1118132 times.
✗ Branch 3 not taken.
1118132 boundary.get<TagReg>().find(reg_name);
260
3/4
✓ Branch 3 taken 1118132 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 665088 times.
✓ Branch 6 taken 453044 times.
2/2
✓ Decision 'true' taken 665088 times.
✓ Decision 'false' taken 453044 times.
1118132 if (found == boundary.get<TagReg>().end())
261 665088 return std::nullopt;
262 else
263
2/4
✓ Branch 1 taken 453044 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 453044 times.
✗ Branch 5 not taken.
453044 return found->reg_info();
264 }
265
266 register_t Circuit::get_reg(std::string reg_name) const {
267 register_t reg;
268
0/1
? Decision couldn't be analyzed.
for (auto [it, end] = boundary.get<TagReg>().equal_range(reg_name); it != end;
269 it++) {
270
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (it->id_.reg_dim() != 1)
271 throw CircuitInvalidity("Cannot linearise register " + reg_name);
272 reg.insert({it->id_.index()[0], it->id_});
273 }
274 return reg;
275 }
276
277 // returns the total number of vertices in dag
278 // just a wrapper for a boost method.
279 // makes no assumptions about graph structure.
280 39127 unsigned Circuit::n_vertices() const { return boost::num_vertices(this->dag); }
281
282 283962 unsigned Circuit::n_qubits() const {
283
1/2
✓ Branch 2 taken 283962 times.
✗ Branch 3 not taken.
283962 return boundary.get<TagType>().count(UnitType::Qubit);
284 }
285
286 223633 unsigned Circuit::n_bits() const {
287
1/2
✓ Branch 2 taken 223633 times.
✗ Branch 3 not taken.
223633 return boundary.get<TagType>().count(UnitType::Bit);
288 }
289
290 38788 unsigned Circuit::n_units() const { return boundary.size(); }
291
292 38781 unsigned Circuit::n_gates() const { return n_vertices() - 2 * n_units(); }
293
294 86070 bool Circuit::is_created(const Qubit &id) const {
295
1/2
✓ Branch 2 taken 86070 times.
✗ Branch 3 not taken.
86070 return get_OpType_from_Vertex(get_in(id)) == OpType::Create;
296 }
297
298 86063 bool Circuit::is_discarded(const Qubit &id) const {
299
1/2
✓ Branch 2 taken 86063 times.
✗ Branch 3 not taken.
86063 return get_OpType_from_Vertex(get_out(id)) == OpType::Discard;
300 }
301
302 // given a vertex, returns a set of all its successor vertices
303 // this set can be empty, and no warnings are given if it is
304 // there are no checks to ensure the vertex exists in the graph
305 136774 VertexVec Circuit::get_successors(const Vertex &vert) const {
306
1/2
✓ Branch 1 taken 136774 times.
✗ Branch 2 not taken.
136774 EdgeVec outs = get_all_out_edges(vert);
307 136774 VertexVec children;
308 136774 std::unordered_set<Vertex> lookup;
309
2/2
✓ Branch 5 taken 163749 times.
✓ Branch 6 taken 136774 times.
2/2
✓ Decision 'true' taken 163749 times.
✓ Decision 'false' taken 136774 times.
300523 for (const Edge &e : outs) {
310
1/2
✓ Branch 1 taken 163749 times.
✗ Branch 2 not taken.
163749 Vertex succ = target(e);
311
3/4
✓ Branch 2 taken 163749 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 162427 times.
✓ Branch 6 taken 1322 times.
2/2
✓ Decision 'true' taken 162427 times.
✓ Decision 'false' taken 1322 times.
163749 if (lookup.find(succ) == lookup.end()) {
312
1/2
✓ Branch 1 taken 162427 times.
✗ Branch 2 not taken.
162427 children.push_back(succ);
313
1/2
✓ Branch 1 taken 162427 times.
✗ Branch 2 not taken.
162427 lookup.insert(succ);
314 }
315 }
316 273548 return children;
317 136774 }
318
319 18 VertexVec Circuit::get_successors_of_type(
320 const Vertex &vert, EdgeType type) const {
321
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 EdgeVec outs = get_out_edges_of_type(vert, type);
322 18 VertexVec children;
323 18 std::unordered_set<Vertex> lookup;
324
2/2
✓ Branch 5 taken 17 times.
✓ Branch 6 taken 18 times.
2/2
✓ Decision 'true' taken 17 times.
✓ Decision 'false' taken 18 times.
35 for (const Edge &e : outs) {
325
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 Vertex succ = target(e);
326
2/4
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
1/2
✓ Decision 'true' taken 17 times.
✗ Decision 'false' not taken.
17 if (lookup.find(succ) == lookup.end()) {
327
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 children.push_back(succ);
328
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 lookup.insert(succ);
329 }
330 }
331 36 return children;
332 18 }
333
334 // given a vertex, returns a set of all its predecessor vertices
335 // this set can be empty, and no warnings are given if it is
336 // there are no checks to ensure the vertex exists in the graph
337 115639 VertexVec Circuit::get_predecessors(const Vertex &vert) const {
338
1/2
✓ Branch 1 taken 115639 times.
✗ Branch 2 not taken.
115639 EdgeVec ins = get_in_edges(vert);
339 115639 VertexVec parents;
340 115639 std::unordered_set<Vertex> lookup;
341
2/2
✓ Branch 5 taken 144799 times.
✓ Branch 6 taken 115639 times.
2/2
✓ Decision 'true' taken 144799 times.
✓ Decision 'false' taken 115639 times.
260438 for (const Edge &e : ins) {
342
1/2
✓ Branch 1 taken 144799 times.
✗ Branch 2 not taken.
144799 Vertex pred = source(e);
343
3/4
✓ Branch 2 taken 144799 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 143480 times.
✓ Branch 6 taken 1319 times.
2/2
✓ Decision 'true' taken 143480 times.
✓ Decision 'false' taken 1319 times.
144799 if (lookup.find(pred) == lookup.end()) {
344
1/2
✓ Branch 1 taken 143480 times.
✗ Branch 2 not taken.
143480 parents.push_back(pred);
345
1/2
✓ Branch 1 taken 143480 times.
✗ Branch 2 not taken.
143480 lookup.insert(pred);
346 }
347 }
348 231278 return parents;
349 115639 }
350
351 14 VertexVec Circuit::get_predecessors_of_type(
352 const Vertex &vert, EdgeType type) const {
353
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 EdgeVec ins = get_in_edges_of_type(vert, type);
354 14 VertexVec parents;
355 14 std::unordered_set<Vertex> lookup;
356
2/2
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 14 times.
2/2
✓ Decision 'true' taken 14 times.
✓ Decision 'false' taken 14 times.
28 for (const Edge &e : ins) {
357
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 Vertex pred = source(e);
358
2/4
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
1/2
✓ Decision 'true' taken 14 times.
✗ Decision 'false' not taken.
14 if (lookup.find(pred) == lookup.end()) {
359
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 parents.push_back(pred);
360
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 lookup.insert(pred);
361 }
362 }
363 28 return parents;
364 14 }
365
366 // Just a wrapper for a boost method
367 3 unsigned Circuit::n_edges() const { return boost::num_edges(dag); }
368
369 unsigned Circuit::n_edges_of_type(const EdgeType &et) const {
370 unsigned count = 0;
371 BGL_FORALL_EDGES(e, dag, DAG) {
372
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (dag[e].type == et) {
373 ++count;
374 }
375 }
376 return count;
377 }
378
379 // return the ports corresponding to an edge
380 16182 std::pair<port_t, port_t> Circuit::get_ports(const Edge &edge) const {
381 16182 return dag[edge].ports;
382 }
383
384 20561260 port_t Circuit::get_source_port(const Edge &edge) const {
385 20561260 return dag[edge].ports.first;
386 }
387
388 21096799 port_t Circuit::get_target_port(const Edge &edge) const {
389 21096799 return dag[edge].ports.second;
390 }
391
392 29741843 EdgeType Circuit::get_edgetype(const Edge &edge) const {
393 29741843 return dag[edge].type;
394 }
395
396 7487376 EdgeVec Circuit::get_in_edges(const Vertex &vert) const {
397
1/2
✓ Branch 1 taken 7487376 times.
✗ Branch 2 not taken.
7487376 unsigned n = n_in_edges(vert);
398
1/2
✓ Branch 2 taken 7487376 times.
✗ Branch 3 not taken.
7487376 EdgeVec inedges(n);
399
1/2
✓ Branch 2 taken 7487376 times.
✗ Branch 3 not taken.
7487376 std::vector<bool> port_found(n, false);
400
11/16
✓ Branch 1 taken 7487376 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6785986 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20977722 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 14191738 times.
✓ Branch 10 taken 6785984 times.
✓ Branch 12 taken 14191738 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 14191738 times.
✓ Branch 15 taken 6785984 times.
✓ Branch 17 taken 14273360 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 6785986 times.
✓ Branch 20 taken 7487374 times.
28465096 BGL_FORALL_INEDGES(vert, e, dag, DAG) {
401
1/2
✓ Branch 1 taken 14191738 times.
✗ Branch 2 not taken.
14191738 port_t port = get_target_port(e);
402
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14191736 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 14191736 times.
14191738 if (port >= n) {
403
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 inedges.resize(port + 1);
404
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 port_found.resize(port + 1, false);
405
3/4
✓ Branch 1 taken 14191736 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 14191734 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 14191734 times.
14191736 } else if (port_found[port]) {
406
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 throw CircuitInvalidity("Vertex has multiple inputs on the same port");
407 }
408
1/2
✓ Branch 1 taken 14191736 times.
✗ Branch 2 not taken.
14191736 port_found[port] = true;
409
1/2
✓ Branch 2 taken 14191736 times.
✗ Branch 3 not taken.
14191736 inedges[port] = e;
410 }
411
2/2
✓ Branch 0 taken 14191734 times.
✓ Branch 1 taken 7487372 times.
2/2
✓ Decision 'true' taken 14191734 times.
✓ Decision 'false' taken 7487372 times.
21679106 for (unsigned i = 0; i < n; i++)
412
3/4
✓ Branch 1 taken 14191734 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 14191732 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 14191732 times.
14191734 if (!port_found[i]) {
413
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 throw CircuitInvalidity("Input ports on Vertex are non-contiguous");
414 }
415 14974744 return inedges;
416 7487380 }
417
418 1305722 EdgeVec Circuit::get_in_edges_of_type(const Vertex &vert, EdgeType type) const {
419
2/2
✓ Branch 1 taken 1305720 times.
✓ Branch 2 taken 2 times.
1305722 EdgeVec ins = get_in_edges(vert);
420 1305720 EdgeVec matching;
421
2/2
✓ Branch 5 taken 3178160 times.
✓ Branch 6 taken 1305720 times.
2/2
✓ Decision 'true' taken 3178160 times.
✓ Decision 'false' taken 1305720 times.
4483880 for (const Edge &e : ins) {
422
3/4
✓ Branch 1 taken 3178160 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1677808 times.
✓ Branch 4 taken 1500352 times.
2/2
✓ Decision 'true' taken 1677808 times.
✓ Decision 'false' taken 1500352 times.
3178160 if (get_edgetype(e) == type) {
423
1/2
✓ Branch 1 taken 1677808 times.
✗ Branch 2 not taken.
1677808 matching.push_back(e);
424 }
425 }
426 2611440 return matching;
427 1305720 }
428
429 512458 std::vector<std::optional<Edge>> Circuit::get_linear_out_edges(
430 const Vertex &vert) const {
431 512458 unsigned n = n_ports(vert);
432
1/2
✓ Branch 2 taken 512458 times.
✗ Branch 3 not taken.
512458 std::vector<std::optional<Edge>> outedges(n);
433
12/18
✓ Branch 1 taken 512458 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 512273 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 625688 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1137961 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 625690 times.
✓ Branch 13 taken 512271 times.
✓ Branch 15 taken 625690 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 625690 times.
✓ Branch 18 taken 512271 times.
✓ Branch 20 taken 1024729 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 512273 times.
✓ Branch 23 taken 512456 times.
1650417 BGL_FORALL_OUTEDGES(vert, e, dag, DAG) {
434
3/4
✓ Branch 1 taken 625690 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 612 times.
✓ Branch 4 taken 625078 times.
2/2
✓ Decision 'true' taken 625078 times.
✓ Decision 'false' taken 612 times.
625690 if (get_edgetype(e) == EdgeType::Boolean) continue;
435
1/2
✓ Branch 1 taken 625078 times.
✗ Branch 2 not taken.
625078 port_t port = get_source_port(e);
436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625078 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 625078 times.
625078 if (port >= n) {
437 throw CircuitInvalidity("Vertex has an output on an unexpected port");
438 }
439
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 625076 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 625076 times.
625078 if (outedges[port]) {
440
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 throw CircuitInvalidity(
441 4 "Vertex has multiple linear outputs on the same port");
442 }
443 625076 outedges[port] = e;
444 }
445 512456 return outedges;
446 2 }
447
448 3214 Edge Circuit::get_linear_edge(const Edge &e) const {
449
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3212 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 3212 times.
3214 if (get_edgetype(e) == EdgeType::Boolean) {
450
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
2 Edge linear_edge = get_nth_out_edge(source(e), get_source_port(e));
451 2 return linear_edge;
452 } else {
453 3212 return e;
454 }
455 }
456
457 231084 EdgeVec Circuit::get_all_out_edges(const Vertex &vert) const {
458
2/2
✓ Branch 1 taken 231083 times.
✓ Branch 2 taken 1 times.
231084 std::vector<std::optional<Edge>> lin_outs = get_linear_out_edges(vert);
459
1/2
✓ Branch 1 taken 231083 times.
✗ Branch 2 not taken.
231083 std::vector<EdgeVec> b_bundles = get_b_out_bundles(vert);
460 231083 EdgeVec outs;
461
2/2
✓ Branch 1 taken 267399 times.
✓ Branch 2 taken 231083 times.
2/2
✓ Decision 'true' taken 267399 times.
✓ Decision 'false' taken 231083 times.
498482 for (unsigned i = 0; i < lin_outs.size(); ++i) {
462 267399 std::optional<Edge> &l_out = lin_outs[i];
463
2/2
✓ Branch 1 taken 267321 times.
✓ Branch 2 taken 78 times.
2/2
✓ Decision 'true' taken 267321 times.
✓ Decision 'false' taken 78 times.
267399 if (l_out) {
464
1/2
✓ Branch 2 taken 267321 times.
✗ Branch 3 not taken.
267321 outs.push_back(*l_out);
465
1/2
✓ Branch 7 taken 267321 times.
✗ Branch 8 not taken.
267321 outs.insert(outs.end(), b_bundles[i].begin(), b_bundles[i].end());
466 }
467 }
468 462166 return outs;
469 231083 }
470
471 382947 EdgeVec Circuit::get_out_edges_of_type(
472 const Vertex &vert, EdgeType type) const {
473
2/2
✓ Branch 0 taken 115378 times.
✓ Branch 1 taken 267569 times.
2/2
✓ Decision 'true' taken 115378 times.
✓ Decision 'false' taken 267569 times.
382947 if (type == EdgeType::Boolean) {
474
1/2
✓ Branch 1 taken 115378 times.
✗ Branch 2 not taken.
115378 std::vector<EdgeVec> bundles = get_b_out_bundles(vert);
475 115378 EdgeVec outs;
476
2/2
✓ Branch 4 taken 139913 times.
✓ Branch 5 taken 115378 times.
2/2
✓ Decision 'true' taken 139913 times.
✓ Decision 'false' taken 115378 times.
255291 for (const EdgeVec &b : bundles) {
477
1/2
✓ Branch 5 taken 139913 times.
✗ Branch 6 not taken.
139913 outs.insert(outs.end(), b.begin(), b.end());
478 }
479 115378 return outs;
480 115378 } else {
481
2/2
✓ Branch 1 taken 267568 times.
✓ Branch 2 taken 1 times.
267569 std::vector<std::optional<Edge>> outs = get_linear_out_edges(vert);
482 267568 EdgeVec matching;
483
2/2
✓ Branch 5 taken 341124 times.
✓ Branch 6 taken 267568 times.
2/2
✓ Decision 'true' taken 341124 times.
✓ Decision 'false' taken 267568 times.
608692 for (const std::optional<Edge> &e : outs) {
484
7/8
✓ Branch 1 taken 340114 times.
✓ Branch 2 taken 1010 times.
✓ Branch 5 taken 340114 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 200570 times.
✓ Branch 8 taken 139544 times.
✓ Branch 9 taken 200570 times.
✓ Branch 10 taken 140554 times.
2/2
✓ Decision 'true' taken 200570 times.
✓ Decision 'false' taken 140554 times.
341124 if (e && get_edgetype(*e) == type) {
485
1/2
✓ Branch 2 taken 200570 times.
✗ Branch 3 not taken.
200570 matching.push_back(*e);
486 }
487 }
488 267568 return matching;
489 267568 }
490 }
491
492 1286618 std::vector<EdgeVec> Circuit::get_b_out_bundles(const Vertex &vert) const {
493 1286618 unsigned n = n_ports(vert);
494
1/2
✓ Branch 2 taken 1286618 times.
✗ Branch 3 not taken.
1286618 std::vector<EdgeVec> bundles(n);
495
12/18
✓ Branch 1 taken 1286618 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1196003 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1262732 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2458735 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1262732 times.
✓ Branch 13 taken 1196003 times.
✓ Branch 15 taken 1262732 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1262732 times.
✓ Branch 18 taken 1196003 times.
✓ Branch 20 taken 2482621 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1196003 times.
✓ Branch 23 taken 1286618 times.
3745353 BGL_FORALL_OUTEDGES(vert, e, dag, DAG) {
496
3/4
✓ Branch 1 taken 1262732 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1583 times.
✓ Branch 4 taken 1261149 times.
2/2
✓ Decision 'true' taken 1583 times.
✓ Decision 'false' taken 1261149 times.
1262732 if (get_edgetype(e) == EdgeType::Boolean) {
497
1/2
✓ Branch 1 taken 1583 times.
✗ Branch 2 not taken.
1583 port_t port = get_source_port(e);
498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1583 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1583 times.
1583 if (port > n) {
499 throw CircuitInvalidity("Vertex has an output on an unexpected port");
500 }
501
2/4
✓ Branch 1 taken 1583 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1583 times.
✗ Branch 5 not taken.
1583 bundles.at(port).push_back(e);
502 }
503 }
504 1286618 return bundles;
505 }
506
507 13545 std::vector<EdgeVec> Circuit::get_b_in_bundles(const Vertex &vert) const {
508 13545 unsigned n = n_ports(vert);
509
1/2
✓ Branch 2 taken 13545 times.
✗ Branch 3 not taken.
13545 std::vector<EdgeVec> bundles(n);
510
12/18
✓ Branch 1 taken 13545 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13545 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 31942 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 45487 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 31942 times.
✓ Branch 13 taken 13545 times.
✓ Branch 15 taken 31942 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 31942 times.
✓ Branch 18 taken 13545 times.
✓ Branch 20 taken 27090 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 13545 times.
✓ Branch 23 taken 13545 times.
59032 BGL_FORALL_INEDGES(vert, e, dag, DAG) {
511
3/4
✓ Branch 1 taken 31942 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5953 times.
✓ Branch 4 taken 25989 times.
2/2
✓ Decision 'true' taken 5953 times.
✓ Decision 'false' taken 25989 times.
31942 if (get_edgetype(e) == EdgeType::Boolean) {
512
1/2
✓ Branch 1 taken 5953 times.
✗ Branch 2 not taken.
5953 port_t port = get_target_port(e);
513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5953 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 5953 times.
5953 if (port > n) {
514 throw CircuitInvalidity("Vertex has an output on an unexpected port");
515 }
516
2/4
✓ Branch 1 taken 5953 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5953 times.
✗ Branch 5 not taken.
5953 bundles.at(port).push_back(e);
517 }
518 }
519 13545 return bundles;
520 }
521
522 // n represents the port of the edge at vert_from
523 // there are no checks to ensure the vertex exists in the graph
524 // will only return Quantum or Classical edges
525 12656281 Edge Circuit::get_nth_out_edge(const Vertex &vert_from, const port_t &n) const {
526
9/18
✓ Branch 1 taken 12656281 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12656281 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2575996 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 15232277 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 15232277 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 15232277 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 15232277 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 12656281 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 12656281 times.
✗ Branch 23 not taken.
15232277 BGL_FORALL_OUTEDGES(vert_from, e, dag, DAG) {
527
8/10
✓ Branch 1 taken 15232277 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15213754 times.
✓ Branch 4 taken 18523 times.
✓ Branch 6 taken 15213754 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12656281 times.
✓ Branch 9 taken 2557473 times.
✓ Branch 10 taken 12656281 times.
✓ Branch 11 taken 2575996 times.
2/2
✓ Decision 'true' taken 12656281 times.
✓ Decision 'false' taken 2575996 times.
15232277 if (get_edgetype(e) != EdgeType::Boolean && get_source_port(e) == n) {
528 12656281 return e;
529 }
530 }
531 throw MissingEdge();
532 }
533
534 978 EdgeVec Circuit::get_nth_b_out_bundle(
535 const Vertex &vert_from, const port_t &n) const {
536 978 EdgeVec bundle;
537
12/18
✓ Branch 1 taken 978 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 978 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5730 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 6708 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5730 times.
✓ Branch 13 taken 978 times.
✓ Branch 15 taken 5730 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 5730 times.
✓ Branch 18 taken 978 times.
✓ Branch 20 taken 1956 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 978 times.
✓ Branch 23 taken 978 times.
7686 BGL_FORALL_OUTEDGES(vert_from, e, dag, DAG) {
538
8/10
✓ Branch 1 taken 5730 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4504 times.
✓ Branch 4 taken 1226 times.
✓ Branch 6 taken 4504 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4489 times.
✓ Branch 9 taken 15 times.
✓ Branch 10 taken 4489 times.
✓ Branch 11 taken 1241 times.
2/2
✓ Decision 'true' taken 4489 times.
✓ Decision 'false' taken 1241 times.
5730 if (get_edgetype(e) == EdgeType::Boolean && get_source_port(e) == n) {
539
1/2
✓ Branch 1 taken 4489 times.
✗ Branch 2 not taken.
4489 bundle.push_back(e);
540 }
541 }
542 978 return bundle;
543 }
544
545 // n represents the port of the edge at vert_to
546 // there are no checks to ensure the vertex exists in the graph
547 1112617 Edge Circuit::get_nth_in_edge(const Vertex &vert_to, const port_t &n) const {
548
9/18
✓ Branch 1 taken 1112617 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1112617 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 52623 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1165240 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1165240 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1165240 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1165240 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1112617 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1112617 times.
✗ Branch 23 not taken.
1165240 BGL_FORALL_INEDGES(vert_to, e, dag, DAG) {
549
3/4
✓ Branch 1 taken 1165240 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1112617 times.
✓ Branch 4 taken 52623 times.
2/2
✓ Decision 'true' taken 1112617 times.
✓ Decision 'false' taken 52623 times.
1165240 if (get_target_port(e) == n) {
550 1112617 return e;
551 }
552 }
553 throw MissingEdge();
554 }
555
556 // there are no checks to ensure the vertex exists in the graph
557 8207826 unsigned Circuit::n_in_edges(const Vertex &vert) const {
558 8207826 return boost::in_degree(vert, dag);
559 }
560
561 1529114 unsigned Circuit::n_in_edges_of_type(const Vertex &vert, EdgeType et) const {
562 1529114 unsigned count = 0;
563
12/18
✓ Branch 1 taken 1529114 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1516011 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3506119 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5022130 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3506119 times.
✓ Branch 13 taken 1516011 times.
✓ Branch 15 taken 3506119 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 3506119 times.
✓ Branch 18 taken 1516011 times.
✓ Branch 20 taken 3045125 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1516011 times.
✓ Branch 23 taken 1529114 times.
6551244 BGL_FORALL_INEDGES(vert, e, dag, DAG) {
564
3/4
✓ Branch 1 taken 3506119 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2050380 times.
✓ Branch 4 taken 1455739 times.
2/2
✓ Decision 'true' taken 1529114 times.
✓ Decision 'false' taken 1977005 times.
3506119 if (get_edgetype(e) == et) ++count;
565 }
566 1529114 return count;
567 }
568
569 // there are no checks to ensure the vertex exists in the graph
570 503931 unsigned Circuit::n_out_edges(const Vertex &vert) const {
571 503931 return boost::out_degree(vert, dag);
572 }
573
574 198262 unsigned Circuit::n_out_edges_of_type(const Vertex &vert, EdgeType et) const {
575 198262 unsigned count = 0;
576
12/18
✓ Branch 1 taken 198262 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 197905 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 245349 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 443254 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 245349 times.
✓ Branch 13 taken 197905 times.
✓ Branch 15 taken 245349 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 245349 times.
✓ Branch 18 taken 197905 times.
✓ Branch 20 taken 396167 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 197905 times.
✓ Branch 23 taken 198262 times.
641516 BGL_FORALL_OUTEDGES(vert, e, dag, DAG) {
577
3/4
✓ Branch 1 taken 245349 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 75438 times.
✓ Branch 4 taken 169911 times.
2/2
✓ Decision 'true' taken 198262 times.
✓ Decision 'false' taken 47087 times.
245349 if (get_edgetype(e) == et) ++count;
578 }
579 198262 return count;
580 }
581
582 22 bool Circuit::is_quantum_node(const Vertex &vert) const {
583
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 return n_in_edges_of_type(vert, EdgeType::Classical) == 0 &&
584
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
44 n_out_edges_of_type(vert, EdgeType::Classical) == 0;
585 }
586
587 bool Circuit::is_classical_node(const Vertex &vert) const {
588 return n_in_edges_of_type(vert, EdgeType::Quantum) == 0 &&
589 n_out_edges_of_type(vert, EdgeType::Quantum) == 0;
590 }
591
592 1812745 unsigned Circuit::n_ports(const Vertex &vert) const {
593 1812745 return get_Op_signature_from_Vertex(vert).size();
594 }
595
596 // there are no checks to ensure the vertex exists in the graph
597 // returns a pointer to the op, try not to dereference and do anything with the
598 // op
599 16340700 const Op_ptr Circuit::get_Op_ptr_from_Vertex(const Vertex &vert) const {
600 16340700 return this->dag[vert].op;
601 }
602
603 1687012 const std::optional<std::string> &Circuit::get_opgroup_from_Vertex(
604 const Vertex &vert) const {
605 1687012 return this->dag[vert].opgroup;
606 }
607
608 4 const std::unordered_set<std::string> Circuit::get_opgroups() const {
609 4 std::unordered_set<std::string> opgroups;
610
7/8
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 65 times.
✓ Branch 6 taken 4 times.
✓ Branch 8 taken 65 times.
✓ Branch 9 taken 4 times.
✓ Branch 11 taken 4 times.
✓ Branch 12 taken 4 times.
73 BGL_FORALL_VERTICES(v, dag, DAG) {
611
2/4
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 65 times.
✗ Branch 5 not taken.
65 std::optional<std::string> v_opgroup = get_opgroup_from_Vertex(v);
612
2/2
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 41 times.
2/2
✓ Decision 'true' taken 24 times.
✓ Decision 'false' taken 41 times.
65 if (v_opgroup) {
613
2/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
24 opgroups.insert(v_opgroup.value());
614 }
615 65 }
616 4 return opgroups;
617 }
618
619 3216 void Circuit::set_vertex_Op_ptr(const Vertex &vert, const Op_ptr &op) {
620 3216 this->dag[vert].op = op;
621 3216 }
622
623 19335 OpDesc Circuit::get_OpDesc_from_Vertex(const Vertex &vert) const {
624
1/2
✓ Branch 3 taken 19335 times.
✗ Branch 4 not taken.
38670 return get_Op_ptr_from_Vertex(vert)->get_desc();
625 }
626
627 // there are no checks to ensure the vertex exists in the graph
628 8881577 OpType Circuit::get_OpType_from_Vertex(const Vertex &vert) const {
629 8881577 return get_Op_ptr_from_Vertex(vert)->get_type();
630 }
631
632 1812745 op_signature_t Circuit::get_Op_signature_from_Vertex(const Vertex &vert) const {
633
1/2
✓ Branch 3 taken 1812745 times.
✗ Branch 4 not taken.
3625490 return get_Op_ptr_from_Vertex(vert)->get_signature();
634 }
635
636 // there are no checks to ensure the vertex exists in the graph
637 // checks that the edge belongs to the vertex
638 1016463 Edge Circuit::get_next_edge(const Vertex &vert, const Edge &in_edge) const {
639
3/4
✓ Branch 1 taken 1016463 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1016462 times.
2/2
✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 1016462 times.
1016463 if (target(in_edge) != vert)
640
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 throw CircuitInvalidity(
641 2 "Cannot get next edge: Edge is not an in edge to Vertex");
642
1/2
✓ Branch 1 taken 1016462 times.
✗ Branch 2 not taken.
1016462 port_t order = get_target_port(in_edge);
643
1/2
✓ Branch 1 taken 1016462 times.
✗ Branch 2 not taken.
2032924 return get_nth_out_edge(vert, order);
644 }
645
646 // there are no checks to ensure the vertex exists in the graph
647 // checks that the edge belongs to the vertex
648 294785 Edge Circuit::get_last_edge(const Vertex &vert, const Edge &out_edge) const {
649
3/4
✓ Branch 1 taken 294785 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 294784 times.
2/2
✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 294784 times.
294785 if (source(out_edge) != vert)
650
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 throw CircuitInvalidity(
651 2 "Cannot get last edge: Edge is not an out edge from Vertex");
652
1/2
✓ Branch 1 taken 294784 times.
✗ Branch 2 not taken.
294784 port_t order = get_source_port(out_edge);
653
1/2
✓ Branch 1 taken 294784 times.
✗ Branch 2 not taken.
589568 return get_nth_in_edge(vert, order);
654 }
655
656 // // given a vertex and corresponding in edge, returns next vertex
657 // and edge
658 // there are no checks to ensure the vertex exists in the graph
659 843 std::pair<Vertex, Edge> Circuit::get_next_pair(
660 const Vertex &current_vertex, const Edge &inedge) const {
661
1/2
✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
843 Edge new_edge = get_next_edge(current_vertex, inedge);
662
1/2
✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
843 Vertex new_vert = target(new_edge);
663
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 842 times.
2/2
✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 842 times.
843 if (new_vert == current_vertex) {
664
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 throw CircuitInvalidity("A qubit path is looping");
665 }
666 1684 return {new_vert, new_edge};
667 }
668
669 // given a vertex and corresponding out edge, returns previous vertex
670 // and edge pair
671 // there are no checks to ensure the vertex exists in the graph
672 43576 std::pair<Vertex, Edge> Circuit::get_prev_pair(
673 const Vertex &current_vertex, const Edge &outedge) const {
674
1/2
✓ Branch 1 taken 43576 times.
✗ Branch 2 not taken.
43576 Edge last_edge = get_last_edge(current_vertex, outedge);
675
1/2
✓ Branch 1 taken 43576 times.
✗ Branch 2 not taken.
43576 Vertex last_vertex = source(last_edge);
676
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 43575 times.
2/2
✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 43575 times.
43576 if (last_vertex == current_vertex) {
677
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 throw CircuitInvalidity("A qubit path is looping");
678 }
679
680 87150 return {last_vertex, last_edge};
681 }
682
683 bool Circuit::detect_initial_Op(const Vertex &vertex) const {
684 OpType type = get_OpType_from_Vertex(vertex);
685 return is_initial_q_type(type) || type == OpType::ClInput;
686 }
687
688 5136039 bool Circuit::detect_final_Op(const Vertex &vertex) const {
689 5136039 OpType type = get_OpType_from_Vertex(vertex);
690
4/4
✓ Branch 1 taken 4195663 times.
✓ Branch 2 taken 940376 times.
✓ Branch 3 taken 271085 times.
✓ Branch 4 taken 3924578 times.
5136039 return is_final_q_type(type) || type == OpType::ClOutput;
691 }
692
693 1097625 bool Circuit::detect_boundary_Op(const Vertex &vertex) const {
694 1097625 OpType type = get_OpType_from_Vertex(vertex);
695
4/4
✓ Branch 1 taken 1096891 times.
✓ Branch 2 taken 734 times.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 1096847 times.
1097625 return is_boundary_q_type(type) || is_boundary_c_type(type);
696 }
697
698 19335 bool Circuit::detect_singleq_unitary_op(const Vertex &vert) const {
699
1/2
✓ Branch 1 taken 19335 times.
✗ Branch 2 not taken.
19335 const OpDesc desc = get_OpDesc_from_Vertex(vert);
700
6/8
✓ Branch 1 taken 19335 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18772 times.
✓ Branch 4 taken 563 times.
✓ Branch 6 taken 18772 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 15720 times.
✓ Branch 9 taken 3052 times.
38670 return desc.is_gate() && desc.is_singleq_unitary();
701 19335 }
702
703 72774 unsigned Circuit::qubit_index(
704 const Vertex &vert, PortType port_type, port_t port) const {
705 const EdgeVec edges = (port_type == PortType::Source)
706 ? get_out_edges_of_type(vert, EdgeType::Quantum)
707
4/6
✓ Branch 0 taken 21647 times.
✓ Branch 1 taken 51127 times.
✓ Branch 3 taken 21647 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 51127 times.
✗ Branch 7 not taken.
72774 : get_in_edges_of_type(vert, EdgeType::Quantum);
708 72774 unsigned n_edges = edges.size();
709
1/2
✓ Branch 0 taken 104988 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 104988 times.
✗ Decision 'false' not taken.
104988 for (unsigned i = 0; i < n_edges; i++) {
710 104988 const Edge &e = edges[i];
711
3/4
✓ Branch 0 taken 32980 times.
✓ Branch 1 taken 72008 times.
✓ Branch 3 taken 32980 times.
✗ Branch 4 not taken.
104988 port_t p = (port_type == PortType::Source) ? get_source_port(e)
712
1/2
✓ Branch 1 taken 72008 times.
✗ Branch 2 not taken.
72008 : get_target_port(e);
713
2/2
✓ Branch 0 taken 72774 times.
✓ Branch 1 taken 32214 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 177762 times.
177762 if (p == port) return i;
714 }
715
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
throw std::domain_error("Invalid port for vertex");
716 72774 }
717
718 44695 std::optional<Pauli> Circuit::commuting_basis(
719 const Vertex &vert, PortType port_type, port_t port) const {
720
1/2
✓ Branch 1 taken 44695 times.
✗ Branch 2 not taken.
44695 Op_ptr op = get_Op_ptr_from_Vertex(vert);
721
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 44691 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 44691 times.
44695 if (op->get_type() == OpType::Conditional) {
722
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 op = static_cast<const Conditional &>(*op).get_op();
723 }
724
2/4
✓ Branch 2 taken 44695 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 44695 times.
✗ Branch 6 not taken.
89390 return op->commuting_basis(qubit_index(vert, port_type, port));
725 44695 }
726
727 28079 bool Circuit::commutes_with_basis(
728 const Vertex &vert, const std::optional<Pauli> &colour, PortType port_type,
729 port_t port) const {
730
1/2
✓ Branch 1 taken 28079 times.
✗ Branch 2 not taken.
28079 Op_ptr op = get_Op_ptr_from_Vertex(vert);
731
2/2
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 28046 times.
2/2
✓ Decision 'true' taken 33 times.
✓ Decision 'false' taken 28046 times.
28079 if (op->get_type() == OpType::Conditional) {
732
1/2
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
33 op = static_cast<const Conditional &>(*op).get_op();
733 }
734
2/4
✓ Branch 2 taken 28079 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 28079 times.
✗ Branch 6 not taken.
56158 return op->commutes_with_basis(colour, qubit_index(vert, port_type, port));
735 28079 }
736
737 } // namespace tket
738