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 |