GCC Code Coverage Report


Directory: ./
File: Circuit/basic_circ_manip.cpp
Date: 2022-10-15 05:10:18
Warnings: 6 unchecked decisions!
Exec Total Coverage
Lines: 293 335 87.5%
Functions: 28 28 100.0%
Branches: 348 712 48.9%
Decisions: 80 118 67.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 PERFORM BASIC CIRCUIT MANIPULATION//
17 /////////////////////////////////////////////////////
18
19 #include <memory>
20 #include <optional>
21 #include <ostream>
22 #include <string>
23 #include <vector>
24
25 #include "Boxes.hpp"
26 #include "Circuit.hpp"
27 #include "Ops/MetaOp.hpp"
28
29 namespace tket {
30
31 // if there are any blank wires in the circuit,
32 // this method removes them and removes the vertices
33 // from boundaries
34 4 void Circuit::remove_blank_wires() {
35 4 VertexList bin;
36 4 unit_vector_t unused_units;
37
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 const Op_ptr noop = get_op_ptr(OpType::noop);
38
5/8
✓ Branch 4 taken 23 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 23 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 27 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 23 times.
✓ Branch 13 taken 4 times.
0/1
? Decision couldn't be analyzed.
27 for (const BoundaryElement& el : boundary.get<TagID>()) {
39 23 Vertex in = el.in_;
40 23 Vertex out = el.out_;
41
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 VertexVec succs = get_successors(in);
42
5/6
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 11 times.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 11 times.
2/2
✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 11 times.
23 if (succs.size() == 1 && succs.front() == out) {
43
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 dag[in].op = noop;
44
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 bin.push_back(in);
45
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 dag[out].op = noop;
46
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 bin.push_back(out);
47
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 unused_units.push_back(el.id_);
48 }
49 23 }
50
2/2
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 4 times.
2/2
✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 4 times.
16 for (const UnitID& u : unused_units) {
51
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 boundary.get<TagID>().erase(u);
52 }
53
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 remove_vertices(bin, GraphRewiring::No, VertexDeletion::Yes);
54 4 }
55
56 7216 void Circuit::remove_noops() {
57 7216 VertexSet bin;
58
7/8
✓ Branch 1 taken 7216 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 59564 times.
✓ Branch 6 taken 7216 times.
✓ Branch 8 taken 59564 times.
✓ Branch 9 taken 7216 times.
✓ Branch 11 taken 7216 times.
✓ Branch 12 taken 7216 times.
73996 BGL_FORALL_VERTICES(v, dag, DAG) {
59
1/2
✓ Branch 1 taken 59564 times.
✗ Branch 2 not taken.
59564 Op_ptr op = get_Op_ptr_from_Vertex(v);
60 59564 std::optional<double> phase;
61
10/16
✓ Branch 2 taken 59564 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 59564 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 31416 times.
✓ Branch 8 taken 28148 times.
✓ Branch 11 taken 31416 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 209 times.
✓ Branch 15 taken 31207 times.
✓ Branch 16 taken 59564 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 209 times.
✓ Branch 20 taken 59355 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
2/2
✓ Decision 'true' taken 209 times.
✓ Decision 'false' taken 59355 times.
59564 if (op->get_desc().is_gate() && (phase = op->is_identity())) {
62
1/2
✓ Branch 1 taken 209 times.
✗ Branch 2 not taken.
209 remove_vertex(
63 v, Circuit::GraphRewiring::Yes, Circuit::VertexDeletion::No);
64
2/4
✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 209 times.
✗ Branch 6 not taken.
209 add_phase(*phase);
65
1/2
✓ Branch 1 taken 209 times.
✗ Branch 2 not taken.
209 bin.insert(v);
66 }
67 59564 }
68
1/2
✓ Branch 1 taken 7216 times.
✗ Branch 2 not taken.
7216 remove_vertices(
69 bin, Circuit::GraphRewiring::No, Circuit::VertexDeletion::Yes);
70 7216 }
71
72 106 std::ostream& operator<<(std::ostream& out, const Circuit& circ) {
73
8/14
✓ Branch 1 taken 106 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 106 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1140 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1140 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1140 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 1140 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1140 times.
✓ Branch 21 taken 106 times.
0/1
? Decision couldn't be analyzed.
1246 for (const Command& com : circ) out << com << std::endl;
74
2/4
✓ Branch 3 taken 106 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 106 times.
✗ Branch 7 not taken.
106 out << "Phase (in half-turns): " << circ.get_phase() << std::endl;
75 106 return out;
76 }
77
78 template <>
79 624343 Vertex Circuit::add_op<unsigned>(
80 const Op_ptr& gate, const std::vector<unsigned>& args,
81 std::optional<std::string> opgroup) {
82
1/2
✓ Branch 2 taken 624343 times.
✗ Branch 3 not taken.
624343 op_signature_t sig = gate->get_signature();
83
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 624339 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 624339 times.
624343 if (sig.size() != args.size()) {
84
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 throw CircuitInvalidity(
85
3/6
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
8 std::to_string(args.size()) + " args provided, but " +
86
4/8
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
16 gate->get_name() + " requires " + std::to_string(sig.size()));
87 }
88 624339 OpType optype = gate->get_type();
89 624339 unit_vector_t arg_ids;
90
2/2
✓ Branch 1 taken 734813 times.
✓ Branch 2 taken 624339 times.
2/2
✓ Decision 'true' taken 734813 times.
✓ Decision 'false' taken 624339 times.
1359152 for (unsigned i = 0; i < args.size(); ++i) {
91
3/4
✓ Branch 1 taken 734813 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 733399 times.
✓ Branch 4 taken 1414 times.
2/2
✓ Decision 'true' taken 733399 times.
✓ Decision 'false' taken 1414 times.
734813 if (sig.at(i) == EdgeType::Quantum) {
92
2/4
✓ Branch 2 taken 733399 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 733399 times.
✗ Branch 6 not taken.
733399 arg_ids.push_back(Qubit(args[i]));
93 } else {
94
2/4
✓ Branch 2 taken 1414 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1414 times.
✗ Branch 6 not taken.
1414 arg_ids.push_back(Bit(args[i]));
95 }
96 }
97
6/6
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 624311 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 624338 times.
2/2
✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 624338 times.
624339 if (optype == OpType::CnRy && args.size() == 1) {
98
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 return add_op(get_op_ptr(OpType::Ry, gate->get_params()), arg_ids);
99
6/6
✓ Branch 0 taken 333 times.
✓ Branch 1 taken 624005 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 332 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 624337 times.
2/2
✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 624337 times.
624338 } else if (optype == OpType::CnX && args.size() == 1) {
100
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 return add_op(get_op_ptr(OpType::X), arg_ids);
101
4/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 624328 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 624337 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 624337 times.
624337 } else if (optype == OpType::CnZ && args.size() == 1) {
102 return add_op(get_op_ptr(OpType::Z), arg_ids);
103
4/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 624328 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 624337 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 624337 times.
624337 } else if (optype == OpType::CnY && args.size() == 1) {
104 return add_op(get_op_ptr(OpType::Y), arg_ids);
105 }
106
3/4
✓ Branch 1 taken 624337 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 624335 times.
✓ Branch 5 taken 2 times.
624339 return add_op(gate, arg_ids, opgroup);
107 624345 }
108
109 30 Vertex Circuit::add_barrier(
110 const std::vector<unsigned>& qubits, const std::vector<unsigned>& bits,
111 const std::string& _data) {
112
1/2
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
30 op_signature_t sig(qubits.size(), EdgeType::Quantum);
113
1/2
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
30 op_signature_t cl_sig(bits.size(), EdgeType::Classical);
114
1/2
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
30 sig.insert(sig.end(), cl_sig.begin(), cl_sig.end());
115
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 std::vector<unsigned> args = qubits;
116
1/2
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
30 args.insert(args.end(), bits.begin(), bits.end());
117
2/4
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
60 return add_op(std::make_shared<MetaOp>(OpType::Barrier, sig, _data), args);
118 30 }
119
120 9 Vertex Circuit::add_barrier(
121 const unit_vector_t& args, const std::string& _data) {
122 9 op_signature_t sig;
123
2/2
✓ Branch 5 taken 23 times.
✓ Branch 6 taken 9 times.
2/2
✓ Decision 'true' taken 23 times.
✓ Decision 'false' taken 9 times.
32 for (const UnitID& arg : args) {
124
2/2
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 3 times.
2/2
✓ Decision 'true' taken 20 times.
✓ Decision 'false' taken 3 times.
23 if (arg.type() == UnitType::Qubit) {
125
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 sig.push_back(EdgeType::Quantum);
126 } else {
127
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 sig.push_back(EdgeType::Classical);
128 }
129 }
130
2/4
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
18 return add_op(std::make_shared<MetaOp>(OpType::Barrier, sig, _data), args);
131 9 }
132
133 26 std::string Circuit::get_next_c_reg_name(const std::string& reg_name) {
134
3/4
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 8 times.
2/2
✓ Decision 'true' taken 18 times.
✓ Decision 'false' taken 8 times.
26 if (!get_reg_info(reg_name)) {
135 18 return reg_name;
136 }
137 8 unsigned post_fix = 1;
138 while (true) {
139 std::string incremented_reg_name =
140
4/8
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
16 reg_name + "(" + std::to_string(post_fix) + ")";
141
3/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
1/2
✓ Decision 'true' taken 8 times.
✗ Decision 'false' not taken.
8 if (!get_reg_info(incremented_reg_name)) {
142 8 return incremented_reg_name;
143 }
144 post_fix++;
145
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 }
146 }
147
148 13 static void append_debug_bits(
149 Circuit& circ, unit_vector_t& args,
150 const std::vector<bool>& expected_readouts,
151 const std::optional<std::string>& postfix) {
152 13 unsigned n_temp_bits = expected_readouts.size();
153 unsigned n_one_bits =
154 13 std::accumulate(expected_readouts.begin(), expected_readouts.end(), 0);
155 13 unsigned n_zero_bits = n_temp_bits - n_one_bits;
156
157 // Add a classical registers for this assertion
158 std::string zero_reg_name =
159 13 (postfix == std::nullopt)
160
3/8
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
6 ? c_debug_zero_prefix() + "_" + c_debug_default_name()
161
11/18
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 7 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 7 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 7 times.
✓ Branch 18 taken 6 times.
✓ Branch 19 taken 6 times.
✓ Branch 20 taken 7 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
26 : c_debug_zero_prefix() + "_" + postfix.value();
162 std::string one_reg_name =
163 13 (postfix == std::nullopt)
164
3/8
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
6 ? c_debug_one_prefix() + "_" + c_debug_default_name()
165
11/18
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 7 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 7 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 7 times.
✓ Branch 18 taken 6 times.
✓ Branch 19 taken 6 times.
✓ Branch 20 taken 7 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
26 : c_debug_one_prefix() + "_" + postfix.value();
166 std::string incremented_zero_reg_name =
167
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 circ.get_next_c_reg_name(zero_reg_name);
168
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 13 times.
✗ Decision 'false' not taken.
13 if (n_zero_bits > 0) {
169
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 circ.add_c_register(incremented_zero_reg_name, n_zero_bits);
170 }
171
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 std::string incremented_one_reg_name = circ.get_next_c_reg_name(one_reg_name);
172
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 9 times.
13 if (n_one_bits > 0) {
173
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 circ.add_c_register(incremented_one_reg_name, n_one_bits);
174 }
175
176 13 unsigned zero_reg_index = 0;
177 13 unsigned one_reg_index = 0;
178
179
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 13 times.
2/2
✓ Decision 'true' taken 30 times.
✓ Decision 'false' taken 13 times.
43 for (unsigned i = 0; i < n_temp_bits; i++) {
180
3/4
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 26 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 26 times.
30 if (expected_readouts[i]) {
181
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 args.push_back(Bit(incremented_one_reg_name, one_reg_index++));
182 } else {
183
2/4
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
26 args.push_back(Bit(incremented_zero_reg_name, zero_reg_index++));
184 }
185 }
186 13 }
187
188 8 Vertex Circuit::add_assertion(
189 const ProjectorAssertionBox& assertion_box,
190 const std::vector<Qubit>& qubits, const std::optional<Qubit>& ancilla,
191 const std::optional<std::string>& name) {
192
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 auto circ_ptr = assertion_box.to_circuit();
193
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 unsigned log2_dim = log2(assertion_box.get_matrix().rows());
194
3/8
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 8 times.
8 if (circ_ptr->n_qubits() > log2_dim && ancilla == std::nullopt) {
195 throw CircuitInvalidity("This assertion requires an ancilla");
196 }
197
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 8 times.
8 if (qubits.size() != log2_dim) {
198 throw CircuitInvalidity(
199 std::to_string(qubits.size()) +
200 " target qubits provided, but the projector requires " +
201 std::to_string(log2_dim));
202 }
203
204 8 unit_vector_t args;
205
1/2
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
8 args.insert(args.end(), qubits.begin(), qubits.end());
206
2/4
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 8 times.
8 if (circ_ptr->n_qubits() > log2_dim) {
207 args.push_back(*ancilla);
208 }
209
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 append_debug_bits(*this, args, assertion_box.get_expected_readouts(), name);
210
1/2
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
24 return add_op<UnitID>(
211
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
32 std::make_shared<ProjectorAssertionBox>(assertion_box), args);
212 8 }
213
214 5 Vertex Circuit::add_assertion(
215 const StabiliserAssertionBox& assertion_box,
216 const std::vector<Qubit>& qubits, const Qubit& ancilla,
217 const std::optional<std::string>& name) {
218
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 auto circ_ptr = assertion_box.to_circuit();
219
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 unsigned pauli_len = assertion_box.get_stabilisers()[0].string.size();
220
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 5 times.
5 if (qubits.size() != pauli_len) {
221 throw CircuitInvalidity(
222 std::to_string(qubits.size()) +
223 " target qubits provided, but the stabilisers requires " +
224 std::to_string(pauli_len));
225 }
226
227 5 unit_vector_t args;
228
1/2
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
5 args.insert(args.end(), qubits.begin(), qubits.end());
229
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 args.push_back(ancilla);
230
2/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
5 append_debug_bits(*this, args, assertion_box.get_expected_readouts(), name);
231
1/2
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
15 return add_op<UnitID>(
232
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
20 std::make_shared<StabiliserAssertionBox>(assertion_box), args);
233 5 }
234
235 // adds a vertex to dag of given op type without any connecting edges
236 // does not add boundary vertices to registers; this should be done manually
237 1506097 Vertex Circuit::add_vertex(
238 const Op_ptr op_ptr, std::optional<std::string> opgroup) {
239 1506097 Vertex new_V = boost::add_vertex(this->dag);
240
3/6
✓ Branch 2 taken 1506097 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1506097 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1506097 times.
✗ Branch 9 not taken.
1506097 this->dag[new_V] = {op_ptr, opgroup};
241 1506097 return new_V;
242 }
243
244 772888 Vertex Circuit::add_vertex(
245 const OpType& type, std::optional<std::string> opgroup) {
246
2/4
✓ Branch 3 taken 772888 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 772888 times.
✗ Branch 7 not taken.
772888 return add_vertex(get_op_ptr(type), opgroup);
247 }
248
249 // given vertices and desired in ports for i2 and out ports for i1, adds
250 // edge between them
251 // there are no checks to ensure the vertex exists in the graph
252 5564542 Edge Circuit::add_edge(
253 const VertPort& source, const VertPort& target, const EdgeType& type) {
254 // add new edge
255 std::pair<Edge, bool> edge_pairy =
256
1/2
✓ Branch 1 taken 5564542 times.
✗ Branch 2 not taken.
5564542 boost::add_edge(source.first, target.first, this->dag);
257
258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5564542 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 5564542 times.
5564542 if (edge_pairy.second == false) {
259 throw MissingVertex("Cannot create edge between vertices");
260 }
261 5564542 Edge new_E = edge_pairy.first;
262
1/2
✓ Branch 1 taken 5564542 times.
✗ Branch 2 not taken.
5564542 dag[new_E].ports.first = source.second;
263
1/2
✓ Branch 1 taken 5564542 times.
✗ Branch 2 not taken.
5564542 dag[new_E].ports.second = target.second;
264
1/2
✓ Branch 1 taken 5564542 times.
✗ Branch 2 not taken.
5564542 dag[new_E].type = type;
265
266 11129084 return new_E;
267 }
268
269 // given vertex, eradicates it from dag, returning edges used for rewiring
270 // methods
271 // there are no checks to ensure the vertex exists in the graph. This may cause
272 // a segfault if called on a vertex which doesn't exist any more. Take care with
273 // ordering of vertex removal! has flags for whether you want to a) rewire the
274 // hole left by the vertex and b) destroy vertex once it has been isolated As a
275 // sanity check, you cannot remove boundary vertices; converting them to noops
276 // beforehand is recommended
277 1313580 void Circuit::remove_vertex(
278 const Vertex& deadvert, GraphRewiring graph_rewiring,
279 VertexDeletion vertex_deletion) {
280
2/2
✓ Branch 0 taken 939109 times.
✓ Branch 1 taken 374471 times.
2/2
✓ Decision 'true' taken 939109 times.
✓ Decision 'false' taken 374471 times.
1313580 if (graph_rewiring == GraphRewiring::Yes) {
281
1/2
✓ Branch 1 taken 939109 times.
✗ Branch 2 not taken.
939109 EdgeVec ins = get_in_edges(deadvert);
282
1/2
✓ Branch 1 taken 939109 times.
✗ Branch 2 not taken.
939109 std::vector<EdgeVec> bundles = get_b_out_bundles(deadvert);
283 939109 port_t p = 0;
284
2/2
✓ Branch 4 taken 852584 times.
✓ Branch 5 taken 939109 times.
2/2
✓ Decision 'true' taken 852584 times.
✓ Decision 'false' taken 939109 times.
1791693 for (const Edge& e : ins) {
285
1/2
✓ Branch 1 taken 852584 times.
✗ Branch 2 not taken.
852584 EdgeType type = get_edgetype(e);
286
2/2
✓ Branch 0 taken 852563 times.
✓ Branch 1 taken 21 times.
2/2
✓ Decision 'true' taken 852563 times.
✓ Decision 'false' taken 21 times.
852584 if (type != EdgeType::Boolean) {
287
1/2
✓ Branch 1 taken 852563 times.
✗ Branch 2 not taken.
852563 Vertex pred_vert = source(e);
288
1/2
✓ Branch 1 taken 852563 times.
✗ Branch 2 not taken.
852563 port_t pred_port = get_source_port(e);
289
1/2
✓ Branch 1 taken 852563 times.
✗ Branch 2 not taken.
852563 Edge next_e = get_nth_out_edge(deadvert, p);
290
1/2
✓ Branch 1 taken 852563 times.
✗ Branch 2 not taken.
852563 Vertex succ_vert = target(next_e);
291
1/2
✓ Branch 1 taken 852563 times.
✗ Branch 2 not taken.
852563 port_t succ_port = get_target_port(next_e);
292
1/2
✓ Branch 3 taken 852563 times.
✗ Branch 4 not taken.
852563 add_edge({pred_vert, pred_port}, {succ_vert, succ_port}, type);
293
2/2
✓ Branch 0 taken 1094 times.
✓ Branch 1 taken 851469 times.
2/2
✓ Decision 'true' taken 2063 times.
✓ Decision 'false' taken 850500 times.
852563 if (type == EdgeType::Classical) {
294
2/2
✓ Branch 5 taken 969 times.
✓ Branch 6 taken 1094 times.
2/2
✓ Decision 'true' taken 969 times.
✓ Decision 'false' taken 1094 times.
2063 for (const Edge& cr : bundles[p]) {
295
1/2
✓ Branch 1 taken 969 times.
✗ Branch 2 not taken.
969 Vertex sv = target(cr);
296
1/2
✓ Branch 1 taken 969 times.
✗ Branch 2 not taken.
969 port_t sp = get_target_port(cr);
297
1/2
✓ Branch 3 taken 969 times.
✗ Branch 4 not taken.
969 add_edge({pred_vert, pred_port}, {sv, sp}, EdgeType::Boolean);
298 }
299 }
300 }
301 852584 ++p;
302 }
303 939109 }
304
305 1313580 boost::clear_vertex(deadvert, this->dag);
306
2/2
✓ Branch 0 taken 1094324 times.
✓ Branch 1 taken 219256 times.
2/2
✓ Decision 'true' taken 1094324 times.
✓ Decision 'false' taken 219256 times.
1313580 if (vertex_deletion == VertexDeletion::Yes) {
307
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1094324 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1094324 times.
1094324 if (detect_boundary_Op(deadvert))
308 throw CircuitInvalidity("Cannot remove a boundary vertex");
309 1094324 boost::remove_vertex(deadvert, this->dag);
310 }
311 1313580 }
312
313 // same as previous but for a set of vertices
314 263461 void Circuit::remove_vertices(
315 const VertexSet& surplus, GraphRewiring graph_rewiring,
316 VertexDeletion vertex_deletion) {
317
2/2
✓ Branch 5 taken 460667 times.
✓ Branch 6 taken 263461 times.
2/2
✓ Decision 'true' taken 460667 times.
✓ Decision 'false' taken 263461 times.
724128 for (const Vertex& to_remove : surplus) {
318
1/2
✓ Branch 1 taken 460667 times.
✗ Branch 2 not taken.
460667 remove_vertex(to_remove, graph_rewiring, vertex_deletion);
319 }
320 263461 }
321
322 282635 void Circuit::remove_vertices(
323 const VertexList& surplus, GraphRewiring graph_rewiring,
324 VertexDeletion vertex_deletion) {
325
2/2
✓ Branch 5 taken 674985 times.
✓ Branch 6 taken 282635 times.
2/2
✓ Decision 'true' taken 674985 times.
✓ Decision 'false' taken 282635 times.
957620 for (const Vertex& to_remove : surplus) {
326
1/2
✓ Branch 1 taken 674985 times.
✗ Branch 2 not taken.
674985 remove_vertex(to_remove, graph_rewiring, vertex_deletion);
327 }
328 282635 }
329
330 1262912 void Circuit::remove_edge(const Edge& edge) {
331 1262912 boost::remove_edge(edge, this->dag);
332 1262912 }
333
334 22 unit_map_t Circuit::flatten_registers() {
335 22 unsigned q_index = 0;
336 22 unsigned c_index = 0;
337
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 boundary_t new_map;
338 22 unit_map_t qmap;
339
5/8
✓ Branch 4 taken 133 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 133 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 155 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 133 times.
✓ Branch 13 taken 22 times.
0/1
? Decision couldn't be analyzed.
155 for (const BoundaryElement& el : boundary.get<TagID>()) {
340 133 BoundaryElement new_el = el;
341
2/2
✓ Branch 1 taken 131 times.
✓ Branch 2 taken 2 times.
2/2
✓ Decision 'true' taken 131 times.
✓ Decision 'false' taken 2 times.
133 if (el.type() == UnitType::Qubit) {
342
2/4
✓ Branch 1 taken 131 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 131 times.
✗ Branch 5 not taken.
131 new_el.id_ = Qubit(q_default_reg(), q_index);
343 131 q_index++;
344 } else {
345
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 new_el.id_ = Bit(c_default_reg(), c_index);
346 2 c_index++;
347 }
348
1/2
✓ Branch 2 taken 133 times.
✗ Branch 3 not taken.
133 qmap.insert({el.id_, new_el.id_});
349
1/2
✓ Branch 1 taken 133 times.
✗ Branch 2 not taken.
133 new_map.insert(new_el);
350 133 }
351
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 boundary = new_map;
352 44 return qmap;
353 22 }
354
355 // this automatically updates the circuit boundaries
356 108 void Circuit::add_blank_wires(unsigned n) {
357
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 108 times.
108 if (!default_regs_ok())
358 throw CircuitInvalidity(
359 "Incompatible registers exist with the default names");
360 108 unsigned index = 0;
361
2/2
✓ Branch 0 taken 323 times.
✓ Branch 1 taken 108 times.
2/2
✓ Decision 'true' taken 323 times.
✓ Decision 'false' taken 108 times.
431 for (unsigned i = 0; i < n; i++) {
362
1/2
✓ Branch 2 taken 323 times.
✗ Branch 3 not taken.
323 Vertex in = add_vertex(OpType::Input);
363
1/2
✓ Branch 2 taken 323 times.
✗ Branch 3 not taken.
323 Vertex out = add_vertex(OpType::Output);
364
1/2
✓ Branch 3 taken 323 times.
✗ Branch 4 not taken.
323 add_edge({in, 0}, {out, 0}, EdgeType::Quantum);
365 323 bool searching = true;
366
2/2
✓ Branch 0 taken 334 times.
✓ Branch 1 taken 323 times.
2/2
✓ Decision 'true' taken 334 times.
✓ Decision 'false' taken 323 times.
657 while (searching) {
367
1/2
✓ Branch 1 taken 334 times.
✗ Branch 2 not taken.
334 Qubit q_id(index);
368
1/2
✓ Branch 2 taken 334 times.
✗ Branch 3 not taken.
334 boundary_t::iterator found = boundary.get<TagID>().find(q_id);
369
3/4
✓ Branch 3 taken 334 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 323 times.
✓ Branch 6 taken 11 times.
2/2
✓ Decision 'true' taken 323 times.
✓ Decision 'false' taken 11 times.
334 if (found == boundary.get<TagID>().end()) {
370 323 searching = false;
371
1/2
✓ Branch 2 taken 323 times.
✗ Branch 3 not taken.
323 boundary.insert({q_id, in, out});
372 }
373 334 index++;
374 334 }
375 }
376 108 }
377
378 998 void Circuit::add_qubit(const Qubit& id, bool reject_dups) {
379 boundary_t::index<TagID>::type::iterator found =
380
1/2
✓ Branch 2 taken 998 times.
✗ Branch 3 not taken.
998 boundary.get<TagID>().find(id);
381
2/4
✓ Branch 3 taken 998 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 998 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 998 times.
998 if (found != boundary.get<TagID>().end()) {
382
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (reject_dups) {
383 throw CircuitInvalidity(
384 "A unit with ID \"" + id.repr() + "\" already exists");
385
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
} else if (found->type() == UnitType::Qubit) {
386 return;
387 } else {
388 throw CircuitInvalidity(
389 "A bit with ID \"" + id.repr() + "\" already exists");
390 }
391 }
392
2/4
✓ Branch 1 taken 998 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 998 times.
✗ Branch 5 not taken.
998 opt_reg_info_t reg_info = get_reg_info(id.reg_name());
393 998 register_info_t correct_info = {UnitType::Qubit, id.reg_dim()};
394
5/8
✓ Branch 1 taken 539 times.
✓ Branch 2 taken 459 times.
✓ Branch 4 taken 539 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 539 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 998 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 998 times.
998 if (reg_info && !(reg_info.value() == correct_info))
395 throw CircuitInvalidity(
396 "Cannot add qubit with ID \"" + id.repr() +
397 "\" as register is not compatible");
398
1/2
✓ Branch 2 taken 998 times.
✗ Branch 3 not taken.
998 Vertex in = add_vertex(OpType::Input);
399
1/2
✓ Branch 2 taken 998 times.
✗ Branch 3 not taken.
998 Vertex out = add_vertex(OpType::Output);
400
1/2
✓ Branch 3 taken 998 times.
✗ Branch 4 not taken.
998 add_edge({in, 0}, {out, 0}, EdgeType::Quantum);
401
1/2
✓ Branch 2 taken 998 times.
✗ Branch 3 not taken.
998 boundary.insert({id, in, out});
402 }
403
404 582 void Circuit::add_bit(const Bit& id, bool reject_dups) {
405 boundary_t::index<TagID>::type::iterator found =
406
1/2
✓ Branch 2 taken 582 times.
✗ Branch 3 not taken.
582 boundary.get<TagID>().find(id);
407
2/4
✓ Branch 3 taken 582 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 582 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 582 times.
582 if (found != boundary.get<TagID>().end()) {
408
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (reject_dups) {
409 throw CircuitInvalidity(
410 "A unit with ID \"" + id.repr() + "\" already exists");
411
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
} else if (found->type() == UnitType::Bit) {
412 return;
413 } else {
414 throw CircuitInvalidity(
415 "A qubit with ID \"" + id.repr() + "\" already exists");
416 }
417 }
418
2/4
✓ Branch 1 taken 582 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 582 times.
✗ Branch 5 not taken.
582 opt_reg_info_t reg_info = get_reg_info(id.reg_name());
419 582 register_info_t correct_info = {UnitType::Bit, id.reg_dim()};
420
5/8
✓ Branch 1 taken 293 times.
✓ Branch 2 taken 289 times.
✓ Branch 4 taken 293 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 293 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 582 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 582 times.
582 if (reg_info && !(reg_info.value() == correct_info))
421 throw CircuitInvalidity(
422 "Cannot add bit with ID \"" + id.repr() +
423 "\" as register is not compatible");
424
1/2
✓ Branch 2 taken 582 times.
✗ Branch 3 not taken.
582 Vertex in = add_vertex(OpType::ClInput);
425
1/2
✓ Branch 2 taken 582 times.
✗ Branch 3 not taken.
582 Vertex out = add_vertex(OpType::ClOutput);
426
1/2
✓ Branch 3 taken 582 times.
✗ Branch 4 not taken.
582 add_edge({in, 0}, {out, 0}, EdgeType::Classical);
427
1/2
✓ Branch 2 taken 582 times.
✗ Branch 3 not taken.
582 boundary.insert({id, in, out});
428 }
429
430 257424 register_t Circuit::add_q_register(std::string reg_name, unsigned size) {
431
2/4
✓ Branch 2 taken 257424 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 257424 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 257424 times.
257424 if (get_reg_info(reg_name))
432 throw CircuitInvalidity(
433 "A register with name \"" + reg_name + "\" already exists");
434 257424 register_t ids;
435
2/2
✓ Branch 0 taken 330820 times.
✓ Branch 1 taken 257424 times.
2/2
✓ Decision 'true' taken 330820 times.
✓ Decision 'false' taken 257424 times.
588244 for (unsigned i = 0; i < size; i++) {
436
1/2
✓ Branch 2 taken 330820 times.
✗ Branch 3 not taken.
330820 Vertex in = add_vertex(OpType::Input);
437
1/2
✓ Branch 2 taken 330820 times.
✗ Branch 3 not taken.
330820 Vertex out = add_vertex(OpType::Output);
438
1/2
✓ Branch 3 taken 330820 times.
✗ Branch 4 not taken.
330820 add_edge({in, 0}, {out, 0}, EdgeType::Quantum);
439
1/2
✓ Branch 1 taken 330820 times.
✗ Branch 2 not taken.
330820 Qubit id(reg_name, i);
440
1/2
✓ Branch 2 taken 330820 times.
✗ Branch 3 not taken.
330820 boundary.insert({id, in, out});
441
1/2
✓ Branch 2 taken 330820 times.
✗ Branch 3 not taken.
330820 ids.insert({i, id});
442 330820 }
443 257424 return ids;
444 }
445
446 271 register_t Circuit::add_c_register(std::string reg_name, unsigned size) {
447
3/4
✓ Branch 2 taken 271 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 270 times.
2/2
✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 270 times.
271 if (get_reg_info(reg_name))
448
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 throw CircuitInvalidity(
449
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
2 "A register with name \"" + reg_name + "\" already exists");
450 270 register_t ids;
451
2/2
✓ Branch 0 taken 524 times.
✓ Branch 1 taken 270 times.
2/2
✓ Decision 'true' taken 524 times.
✓ Decision 'false' taken 270 times.
794 for (unsigned i = 0; i < size; i++) {
452
1/2
✓ Branch 2 taken 524 times.
✗ Branch 3 not taken.
524 Vertex in = add_vertex(OpType::ClInput);
453
1/2
✓ Branch 2 taken 524 times.
✗ Branch 3 not taken.
524 Vertex out = add_vertex(OpType::ClOutput);
454
1/2
✓ Branch 3 taken 524 times.
✗ Branch 4 not taken.
524 add_edge({in, 0}, {out, 0}, EdgeType::Classical);
455
1/2
✓ Branch 1 taken 524 times.
✗ Branch 2 not taken.
524 Bit id(reg_name, i);
456
1/2
✓ Branch 2 taken 524 times.
✗ Branch 3 not taken.
524 boundary.insert({id, in, out});
457
1/2
✓ Branch 2 taken 524 times.
✗ Branch 3 not taken.
524 ids.insert({i, id});
458 524 }
459 270 return ids;
460 }
461
462 47 void Circuit::qubit_create(const Qubit& id) {
463 47 Vertex v = get_in(id);
464
2/4
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 47 times.
✗ Branch 5 not taken.
47 dag[v].op = std::make_shared<const MetaOp>(OpType::Create);
465 47 }
466
467 8 void Circuit::qubit_create_all() {
468
3/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 24 times.
✓ Branch 9 taken 8 times.
0/1
? Decision couldn't be analyzed.
32 for (const auto& qb : all_qubits()) {
469
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 qubit_create(qb);
470 8 }
471 8 }
472
473 22 void Circuit::qubit_discard(const Qubit& id) {
474 22 Vertex v = get_out(id);
475
2/4
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 22 times.
✗ Branch 5 not taken.
22 dag[v].op = std::make_shared<const MetaOp>(OpType::Discard);
476 22 }
477
478 4 void Circuit::qubit_discard_all() {
479
3/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 4 times.
0/1
? Decision couldn't be analyzed.
12 for (const auto& qb : all_qubits()) {
480
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 qubit_discard(qb);
481 4 }
482 4 }
483
484 // for wiring in a single vertex with multiple qubits
485 // there are no checks to ensure the vertex exists in the graph
486 637825 void Circuit::rewire(
487 const Vertex& new_vert, const EdgeVec& preds, const op_signature_t& types) {
488 // multi qubit gate
489 637825 EdgeList bin;
490
2/2
✓ Branch 1 taken 756455 times.
✓ Branch 2 taken 637825 times.
2/2
✓ Decision 'true' taken 756455 times.
✓ Decision 'false' taken 637825 times.
1394280 for (unsigned i = 0; i < preds.size(); ++i) {
491 756455 EdgeType insert_type = types[i];
492
1/2
✓ Branch 2 taken 756455 times.
✗ Branch 3 not taken.
756455 EdgeType replace_type = get_edgetype(preds[i]);
493
1/2
✓ Branch 2 taken 756455 times.
✗ Branch 3 not taken.
756455 port_t port1 = get_source_port(preds[i]);
494
1/2
✓ Branch 2 taken 756455 times.
✗ Branch 3 not taken.
756455 port_t port2 = get_target_port(preds[i]);
495
1/2
✓ Branch 2 taken 756455 times.
✗ Branch 3 not taken.
756455 Vertex old_v1 = source(preds[i]);
496
1/2
✓ Branch 2 taken 756455 times.
✗ Branch 3 not taken.
756455 Vertex old_v2 = target(preds[i]);
497
2/2
✓ Branch 0 taken 2242 times.
✓ Branch 1 taken 754213 times.
2/2
✓ Decision 'true' taken 2242 times.
✓ Decision 'false' taken 754213 times.
756455 if (insert_type == EdgeType::Boolean) {
498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2242 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 2242 times.
2242 if (replace_type != EdgeType::Classical) {
499 throw CircuitInvalidity(
500 "Cannot rewire; Boolean needs a classical value "
501 "to read from");
502 }
503
1/2
✓ Branch 3 taken 2242 times.
✗ Branch 4 not taken.
2242 add_edge({old_v1, port1}, {new_vert, i}, insert_type);
504 } else {
505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 754213 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 754213 times.
754213 if (insert_type != replace_type) {
506 throw CircuitInvalidity("Cannot rewire; changing type of edge");
507 }
508
1/2
✓ Branch 3 taken 754213 times.
✗ Branch 4 not taken.
754213 add_edge({old_v1, port1}, {new_vert, i}, insert_type);
509
1/2
✓ Branch 3 taken 754213 times.
✗ Branch 4 not taken.
754213 add_edge({new_vert, i}, {old_v2, port2}, insert_type);
510
1/2
✓ Branch 2 taken 754213 times.
✗ Branch 3 not taken.
754213 bin.push_back(preds[i]);
511 }
512 }
513
3/4
✓ Branch 4 taken 754213 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 754213 times.
✓ Branch 9 taken 637825 times.
0/1
? Decision couldn't be analyzed.
1392038 for (const Edge& e : bin) remove_edge(e);
514 637825 }
515
516 } // namespace tket
517