Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | // Copyright 2019-2022 Cambridge Quantum Computing | |||
2 | // | |||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | |||
4 | // you may not use this file except in compliance with the License. | |||
5 | // You may obtain a copy of the License at | |||
6 | // | |||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | |||
8 | // | |||
9 | // Unless required by applicable law or agreed to in writing, software | |||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | |||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
12 | // See the License for the specific language governing permissions and | |||
13 | // limitations under the License. | |||
14 | ||||
15 | #include "Boxes.hpp" | |||
16 | ||||
17 | #include <memory> | |||
18 | #include <numeric> | |||
19 | #include <tkassert/Assert.hpp> | |||
20 | ||||
21 | #include "CircUtils.hpp" | |||
22 | #include "Circuit/AssertionSynthesis.hpp" | |||
23 | #include "Command.hpp" | |||
24 | #include "Gate/Rotation.hpp" | |||
25 | #include "OpType/OpTypeInfo.hpp" | |||
26 | #include "Ops/OpJsonFactory.hpp" | |||
27 | #include "Ops/OpPtr.hpp" | |||
28 | #include "ThreeQubitConversion.hpp" | |||
29 | #include "Utils/EigenConfig.hpp" | |||
30 | #include "Utils/Expression.hpp" | |||
31 | #include "Utils/Json.hpp" | |||
32 | #include "Utils/PauliStrings.hpp" | |||
33 | ||||
34 | namespace tket { | |||
35 | ||||
36 | 1 | unsigned Box::n_qubits() const { | ||
37 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | op_signature_t sig = get_signature(); | |
38 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | return std::count(sig.begin(), sig.end(), EdgeType::Quantum); | |
39 | 1 | } | ||
40 | ||||
41 | ✗ | unsigned Box::n_boolean() const { | ||
42 | ✗ | op_signature_t sig = get_signature(); | ||
43 | ✗ | return std::count(sig.begin(), sig.end(), EdgeType::Boolean); | ||
44 | } | |||
45 | ||||
46 | ✗ | unsigned Box::n_classical() const { | ||
47 | ✗ | op_signature_t sig = get_signature(); | ||
48 | ✗ | return std::count(sig.begin(), sig.end(), EdgeType::Classical); | ||
49 | } | |||
50 | ||||
51 | 900 | op_signature_t Box::get_signature() const { | ||
52 |
1/2✓ Branch 1 taken 900 times.
✗ Branch 2 not taken.
|
900 | std::optional<op_signature_t> sig = desc_.signature(); | |
53 |
2/2✓ Branch 1 taken 200 times.
✓ Branch 2 taken 700 times.
|
2/2✓ Decision 'true' taken 200 times.
✓ Decision 'false' taken 700 times.
|
900 | if (sig) |
54 |
1/2✓ Branch 2 taken 200 times.
✗ Branch 3 not taken.
|
200 | return *sig; | |
55 | else | |||
56 |
1/2✓ Branch 1 taken 700 times.
✗ Branch 2 not taken.
|
700 | return signature_; | |
57 | 900 | } | ||
58 | ||||
59 | 13 | nlohmann::json Box::serialize() const { | ||
60 | 13 | nlohmann::json j; | ||
61 |
2/4✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
|
13 | j["type"] = get_type(); | |
62 |
3/6✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13 times.
✗ Branch 8 not taken.
|
13 | j["box"] = OpJsonFactory::to_json(shared_from_this()); | |
63 | 13 | return j; | ||
64 | } | |||
65 | ||||
66 | 13 | Op_ptr Box::deserialize(const nlohmann::json &j) { | ||
67 | 13 | return OpJsonFactory::from_json(j.at("box")); | ||
68 | } | |||
69 | ||||
70 |
1/2✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
|
45 | CircBox::CircBox(const Circuit &circ) : Box(OpType::CircBox) { | |
71 |
4/6✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 44 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
2/2✓ Decision 'true' taken 44 times.
✓ Decision 'false' taken 1 times.
|
45 | if (!circ.is_simple()) throw SimpleOnly(); |
72 |
2/4✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
|
44 | signature_ = op_signature_t(circ.n_qubits(), EdgeType::Quantum); | |
73 |
2/4✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
|
44 | op_signature_t bits(circ.n_bits(), EdgeType::Classical); | |
74 |
1/2✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
|
44 | signature_.insert(signature_.end(), bits.begin(), bits.end()); | |
75 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
44 | circ_ = std::make_shared<Circuit>(circ); | |
76 | 45 | } | ||
77 | ||||
78 | 48 | CircBox::CircBox(const CircBox &other) : Box(other) {} | ||
79 | ||||
80 | ✗ | CircBox::CircBox() : Box(OpType::CircBox) { | ||
81 | ✗ | circ_ = std::make_shared<Circuit>(); | ||
82 | } | |||
83 | ||||
84 | 1 | bool CircBox::is_clifford() const { | ||
85 |
7/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 45 times.
✓ Branch 7 taken 1 times.
✓ Branch 9 taken 45 times.
✓ Branch 10 taken 1 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
|
47 | BGL_FORALL_VERTICES(v, circ_->dag, DAG) { | |
86 |
3/6✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 45 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 45 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 44 times.
|
45 | if (!circ_->get_Op_ptr_from_Vertex(v)->is_clifford()) return false; |
87 | } | |||
88 | 1 | return true; | ||
89 | } | |||
90 | ||||
91 | ✗ | Op_ptr CircBox::symbol_substitution( | ||
92 | const SymEngine::map_basic_basic &sub_map) const { | |||
93 | ✗ | Circuit new_circ(*to_circuit()); | ||
94 | ✗ | new_circ.symbol_substitution(sub_map); | ||
95 | ✗ | return std::make_shared<CircBox>(new_circ); | ||
96 | } | |||
97 | ||||
98 |
1/2✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
|
28 | SymSet CircBox::free_symbols() const { return to_circuit()->free_symbols(); } | |
99 | ||||
100 | 1 | Op_ptr CircBox::dagger() const { | ||
101 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1 | return std::make_shared<CircBox>(circ_->dagger()); | |
102 | } | |||
103 | ||||
104 | ✗ | Op_ptr CircBox::transpose() const { | ||
105 | ✗ | return std::make_shared<CircBox>(circ_->transpose()); | ||
106 | } | |||
107 | ||||
108 | 13 | Unitary1qBox::Unitary1qBox(const Eigen::Matrix2cd &m) | ||
109 |
2/4✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
|
13 | : Box(OpType::Unitary1qBox), m_(m) { | |
110 |
3/6✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 13 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 13 times.
|
13 | if (!is_unitary(m)) { |
111 |
0/1? Decision couldn't be analyzed.
|
✗ | throw CircuitInvalidity("Matrix for Unitary1qBox must be unitary"); | |
112 | } | |||
113 | 13 | } | ||
114 | ||||
115 | 7 | Unitary1qBox::Unitary1qBox(const Unitary1qBox &other) | ||
116 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | : Box(other), m_(other.m_) {} | |
117 | ||||
118 | ✗ | Unitary1qBox::Unitary1qBox() : Unitary1qBox(Eigen::Matrix2cd::Identity()) {} | ||
119 | ||||
120 | 1 | Op_ptr Unitary1qBox::dagger() const { | ||
121 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | return std::make_shared<Unitary1qBox>(m_.conjugate().transpose()); | |
122 | } | |||
123 | ||||
124 | 1 | Op_ptr Unitary1qBox::transpose() const { | ||
125 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | return std::make_shared<Unitary1qBox>(m_.transpose()); | |
126 | } | |||
127 | ||||
128 | 1 | bool Unitary1qBox::is_clifford() const { | ||
129 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | std::vector<Command> cmds = to_circuit()->get_commands(); | |
130 | TKET_ASSERT(cmds.size() == 1); | |||
131 |
1/2✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | return cmds[0].get_op_ptr()->is_clifford(); | |
132 | 1 | } | ||
133 | ||||
134 | 4 | void Unitary1qBox::generate_circuit() const { | ||
135 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | std::vector<double> tk1_params = tk1_angles_from_unitary(m_); | |
136 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | Circuit temp_circ(1); | |
137 |
8/16✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 4 times.
✗ Branch 20 not taken.
✓ Branch 23 taken 12 times.
✓ Branch 24 taken 4 times.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
|
28 | temp_circ.add_op<unsigned>( | |
138 | 12 | OpType::TK1, {tk1_params[0], tk1_params[1], tk1_params[2]}, {0}); | ||
139 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | circ_ = std::make_shared<Circuit>(temp_circ); | |
140 |
2/4✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
4 | circ_->add_phase(tk1_params[3]); | |
141 | 4 | } | ||
142 | ||||
143 | 34 | Unitary2qBox::Unitary2qBox(const Eigen::Matrix4cd &m, BasisOrder basis) | ||
144 | ✗ | : Box(OpType::Unitary2qBox), | ||
145 |
3/8✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 34 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 34 times.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
34 | m_(basis == BasisOrder::ilo ? m : reverse_indexing(m)) { | |
146 |
3/6✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 34 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 34 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 34 times.
|
34 | if (!is_unitary(m)) { |
147 |
0/1? Decision couldn't be analyzed.
|
✗ | throw CircuitInvalidity("Matrix for Unitary2qBox must be unitary"); | |
148 | } | |||
149 | 34 | } | ||
150 | ||||
151 | 27 | Unitary2qBox::Unitary2qBox(const Unitary2qBox &other) | ||
152 |
1/2✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
|
27 | : Box(other), m_(other.m_) {} | |
153 | ||||
154 | ✗ | Unitary2qBox::Unitary2qBox() : Unitary2qBox(Eigen::Matrix4cd::Identity()) {} | ||
155 | ||||
156 | 2 | Op_ptr Unitary2qBox::dagger() const { | ||
157 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | return std::make_shared<Unitary2qBox>(m_.conjugate().transpose()); | |
158 | } | |||
159 | ||||
160 | 2 | Op_ptr Unitary2qBox::transpose() const { | ||
161 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | return std::make_shared<Unitary2qBox>(m_.transpose()); | |
162 | } | |||
163 | ||||
164 | 9 | void Unitary2qBox::generate_circuit() const { | ||
165 |
1/2✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | circ_ = std::make_shared<Circuit>(two_qubit_canonical(m_)); | |
166 | 9 | } | ||
167 | ||||
168 | 20 | Unitary3qBox::Unitary3qBox(const Matrix8cd &m, BasisOrder basis) | ||
169 | ✗ | : Box(OpType::Unitary3qBox), | ||
170 |
3/8✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 20 times.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
20 | m_(basis == BasisOrder::ilo ? m : reverse_indexing(m)) {} | |
171 | ||||
172 | 16 | Unitary3qBox::Unitary3qBox(const Unitary3qBox &other) | ||
173 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | : Box(other), m_(other.m_) {} | |
174 | ||||
175 | ✗ | Unitary3qBox::Unitary3qBox() : Unitary3qBox(Matrix8cd::Identity()) {} | ||
176 | ||||
177 | ✗ | Op_ptr Unitary3qBox::dagger() const { | ||
178 | ✗ | return std::make_shared<Unitary3qBox>(m_.adjoint()); | ||
179 | } | |||
180 | ||||
181 | ✗ | Op_ptr Unitary3qBox::transpose() const { | ||
182 | ✗ | return std::make_shared<Unitary3qBox>(m_.transpose()); | ||
183 | } | |||
184 | ||||
185 | 5 | void Unitary3qBox::generate_circuit() const { | ||
186 |
2/4✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
|
5 | circ_ = std::make_shared<Circuit>(three_qubit_tk_synthesis(m_)); | |
187 | 5 | } | ||
188 | ||||
189 | 28 | ExpBox::ExpBox(const Eigen::Matrix4cd &A, double t, BasisOrder basis) | ||
190 | ✗ | : Box(OpType::ExpBox), | ||
191 |
1/4✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
28 | A_(basis == BasisOrder::ilo ? A : reverse_indexing(A)), | |
192 |
2/4✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 28 times.
✗ Branch 6 not taken.
|
28 | t_(t) { | |
193 |
3/6✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 28 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 28 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 28 times.
|
28 | if (!A.isApprox(A.adjoint())) { |
194 |
0/1? Decision couldn't be analyzed.
|
✗ | throw CircuitInvalidity("Matrix for ExpBox must be Hermitian"); | |
195 | } | |||
196 | 28 | } | ||
197 | ||||
198 |
1/2✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
|
21 | ExpBox::ExpBox(const ExpBox &other) : Box(other), A_(other.A_), t_(other.t_) {} | |
199 | ||||
200 | ✗ | ExpBox::ExpBox() : ExpBox(Eigen::Matrix4cd::Zero(), 1.) {} | ||
201 | ||||
202 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Op_ptr ExpBox::dagger() const { return std::make_shared<ExpBox>(A_, -t_); } | |
203 | ||||
204 | 1 | Op_ptr ExpBox::transpose() const { | ||
205 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | return std::make_shared<ExpBox>(A_.transpose(), t_); | |
206 | } | |||
207 | ||||
208 | ✗ | void ExpBox::generate_circuit() const { | ||
209 | ✗ | circ_ = std::make_shared<Circuit>(two_qubit_canonical((i_ * t_ * A_).exp())); | ||
210 | } | |||
211 | ||||
212 | 1882 | PauliExpBox::PauliExpBox(const std::vector<Pauli> &paulis, const Expr &t) | ||
213 | ✗ | : Box(OpType::PauliExpBox, | ||
214 |
1/2✓ Branch 2 taken 1882 times.
✗ Branch 3 not taken.
|
3764 | op_signature_t(paulis.size(), EdgeType::Quantum)), | |
215 | 1882 | paulis_(paulis), | ||
216 |
3/6✓ Branch 2 taken 1882 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1882 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1882 times.
✗ Branch 9 not taken.
|
5646 | t_(t) {} | |
217 | ||||
218 | 135 | PauliExpBox::PauliExpBox(const PauliExpBox &other) | ||
219 |
2/4✓ Branch 2 taken 135 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 135 times.
✗ Branch 6 not taken.
|
135 | : Box(other), paulis_(other.paulis_), t_(other.t_) {} | |
220 | ||||
221 | ✗ | PauliExpBox::PauliExpBox() : PauliExpBox({}, 0.) {} | ||
222 | ||||
223 | 1 | bool PauliExpBox::is_clifford() const { | ||
224 |
6/18✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
|
1 | return equiv_0(4 * t_) || paulis_.empty(); | |
225 | } | |||
226 | ||||
227 | 6 | SymSet PauliExpBox::free_symbols() const { return expr_free_symbols(t_); } | ||
228 | ||||
229 | 1 | Op_ptr PauliExpBox::dagger() const { | ||
230 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | return std::make_shared<PauliExpBox>(paulis_, -t_); | |
231 | } | |||
232 | ||||
233 | 2 | Op_ptr PauliExpBox::transpose() const { | ||
234 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | std::vector<Pauli> paulis = get_paulis(); | |
235 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
2 | int y_pauli_counter = std::count(paulis.begin(), paulis.end(), Pauli::Y); | |
236 | ||||
237 | // Negate the parameter if odd | |||
238 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 1 times.
|
2 | if (y_pauli_counter % 2 == 0) { |
239 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | return std::make_shared<PauliExpBox>(paulis_, t_); | |
240 | } else { | |||
241 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | return std::make_shared<PauliExpBox>(paulis_, -t_); | |
242 | }; | |||
243 | 2 | } | ||
244 | ||||
245 | 25 | Op_ptr PauliExpBox::symbol_substitution( | ||
246 | const SymEngine::map_basic_basic &sub_map) const { | |||
247 |
1/2✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
|
25 | return std::make_shared<PauliExpBox>(this->paulis_, this->t_.subs(sub_map)); | |
248 | } | |||
249 | ||||
250 | ✗ | void PauliExpBox::generate_circuit() const { | ||
251 | ✗ | Circuit circ = pauli_gadget(paulis_, t_); | ||
252 | ✗ | circ_ = std::make_shared<Circuit>(circ); | ||
253 | } | |||
254 | ||||
255 | 12 | composite_def_ptr_t CompositeGateDef::define_gate( | ||
256 | const std::string &name, const Circuit &def, const std::vector<Sym> &args) { | |||
257 | 12 | return std::make_shared<CompositeGateDef>(name, def, args); | ||
258 | } | |||
259 | ||||
260 | 12 | CompositeGateDef::CompositeGateDef( | ||
261 | 12 | const std::string &name, const Circuit &def, const std::vector<Sym> &args) | ||
262 |
3/6✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
|
12 | : name_(name), def_(std::make_shared<Circuit>(def)), args_(args) {} | |
263 | ||||
264 | 5 | Circuit CompositeGateDef::instance(const std::vector<Expr> ¶ms) const { | ||
265 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | Circuit circ = *def_; | |
266 | 5 | symbol_map_t symbol_map; | ||
267 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
|
2/2✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 5 times.
|
10 | for (unsigned i = 0; i < params.size(); i++) { |
268 |
4/8✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
|
5 | symbol_map.insert({args_.at(i), params.at(i)}); | |
269 | } | |||
270 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | circ.symbol_substitution(symbol_map); | |
271 | 10 | return circ; | ||
272 | 5 | } | ||
273 | ||||
274 | 16 | op_signature_t CompositeGateDef::signature() const { | ||
275 |
2/4✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
|
16 | op_signature_t qubs(def_->n_qubits(), EdgeType::Quantum); | |
276 |
2/4✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
|
16 | op_signature_t bs(def_->n_bits(), EdgeType::Classical); | |
277 |
1/2✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
|
16 | qubs.insert(qubs.end(), bs.begin(), bs.end()); | |
278 | 32 | return qubs; | ||
279 | 16 | } | ||
280 | ||||
281 | 4 | bool CompositeGateDef::operator==(const CompositeGateDef &other) const { | ||
282 |
4/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 3 times.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 1 times.
|
4 | if (this->get_name() != other.get_name()) return false; |
283 |
1/2✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | std::vector<Expr> this_args = {this->args_.begin(), this->args_.end()}; | |
284 |
1/2✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | std::vector<Expr> other_args = {other.args_.begin(), other.args_.end()}; | |
285 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
|
1/2✓ Decision 'true' taken 3 times.
✗ Decision 'false' not taken.
|
3 | if (this_args != other_args) return false; |
286 |
1/2✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
3 | return this->get_def()->circuit_equality(*other.get_def(), {}, false); | |
287 | 3 | } | ||
288 | ||||
289 | 17 | CustomGate::CustomGate( | ||
290 | 17 | const composite_def_ptr_t &gate, const std::vector<Expr> ¶ms) | ||
291 |
2/4✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 17 times.
✗ Branch 8 not taken.
|
17 | : Box(OpType::CustomGate), gate_(gate), params_(params) { | |
292 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 16 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 16 times.
|
17 | if (!gate) { |
293 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | throw std::runtime_error( | |
294 | 2 | "Null CompositeGateDef pointer passed to CustomGate"); | ||
295 | } | |||
296 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | signature_ = gate->signature(); | |
297 | ||||
298 |
1/4✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
0/1? Decision couldn't be analyzed.
|
16 | if (params_.size() != gate_->n_args()) throw InvalidParameterCount(); |
299 | 19 | } | ||
300 | ||||
301 | 7 | CustomGate::CustomGate(const CustomGate &other) | ||
302 |
1/2✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
|
7 | : Box(other), gate_(other.gate_), params_(other.params_) {} | |
303 | ||||
304 | 8 | bool CustomGate::is_equal(const Op &op_other) const { | ||
305 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | const CustomGate &other = dynamic_cast<const CustomGate &>(op_other); | |
306 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 5 times.
|
8 | if (this->id_ == other.id_) { |
307 | 3 | return true; | ||
308 | } | |||
309 | TKET_ASSERT(gate_ && other.gate_); | |||
310 |
4/4✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
|
5 | return params_ == other.params_ && *gate_ == *other.gate_; | |
311 | } | |||
312 | ||||
313 | ✗ | Op_ptr CustomGate::symbol_substitution( | ||
314 | const SymEngine::map_basic_basic &sub_map) const { | |||
315 | ✗ | std::vector<Expr> new_params; | ||
316 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | for (const Expr &p : this->params_) { | |
317 | ✗ | new_params.push_back(p.subs(sub_map)); | ||
318 | } | |||
319 | ✗ | return std::make_shared<CustomGate>(this->gate_, new_params); | ||
320 | } | |||
321 | ||||
322 | 5 | void CustomGate::generate_circuit() const { | ||
323 |
1/2✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
|
5 | circ_ = std::make_shared<Circuit>(gate_->instance(params_)); | |
324 | 5 | } | ||
325 | ||||
326 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | SymSet CustomGate::free_symbols() const { return to_circuit()->free_symbols(); } | |
327 | ||||
328 | 3 | std::string CustomGate::get_name(bool) const { | ||
329 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | std::stringstream s; | |
330 |
2/4✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
|
3 | s << gate_->get_name(); | |
331 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 1 times.
|
3 | if (!params_.empty()) { |
332 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | s << "("; | |
333 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::string sep = ""; | |
334 |
2/2✓ Branch 5 taken 4 times.
✓ Branch 6 taken 2 times.
|
2/2✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 2 times.
|
6 | for (const Expr &e : params_) { |
335 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | s << sep << e; | |
336 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | sep = ","; | |
337 | } | |||
338 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | s << ")"; | |
339 | 2 | } | ||
340 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
6 | return s.str(); | |
341 | 3 | } | ||
342 | ||||
343 | 1 | bool CustomGate::is_clifford() const { | ||
344 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::shared_ptr<Circuit> circ = to_circuit(); | |
345 |
7/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 1 times.
✓ Branch 9 taken 7 times.
✓ Branch 10 taken 1 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
|
9 | BGL_FORALL_VERTICES(v, circ->dag, DAG) { | |
346 |
3/6✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 7 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 6 times.
|
7 | if (!circ->get_Op_ptr_from_Vertex(v)->is_clifford()) return false; |
347 | } | |||
348 | 1 | return true; | ||
349 | 1 | } | ||
350 | ||||
351 | 33 | QControlBox::QControlBox(const Op_ptr &op, unsigned n_controls) | ||
352 |
1/2✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
|
33 | : Box(OpType::QControlBox), op_(op), n_controls_(n_controls) { | |
353 |
1/2✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
|
33 | op_signature_t inner_sig = op_->get_signature(); | |
354 | 33 | n_inner_qubits_ = inner_sig.size(); | ||
355 |
1/2✓ Branch 3 taken 33 times.
✗ Branch 4 not taken.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 33 times.
|
33 | if (std::count(inner_sig.begin(), inner_sig.end(), EdgeType::Quantum) != |
356 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
|
33 | n_inner_qubits_) { | |
357 | ✗ | throw BadOpType( | ||
358 | ✗ | "Quantum control of classical wires not supported", op_->get_type()); | ||
359 | } | |||
360 |
1/2✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
|
33 | signature_ = op_signature_t(n_controls + n_inner_qubits_, EdgeType::Quantum); | |
361 | 33 | } | ||
362 | ||||
363 | 4 | QControlBox::QControlBox(const QControlBox &other) | ||
364 | : Box(other), | |||
365 | 4 | op_(other.op_), | ||
366 | 4 | n_controls_(other.n_controls_), | ||
367 | 4 | n_inner_qubits_(other.n_inner_qubits_) {} | ||
368 | ||||
369 | ✗ | Op_ptr QControlBox::symbol_substitution( | ||
370 | const SymEngine::map_basic_basic &sub_map) const { | |||
371 | ✗ | return std::make_shared<QControlBox>( | ||
372 | ✗ | op_->symbol_substitution(sub_map), n_controls_); | ||
373 | } | |||
374 | ||||
375 | ✗ | SymSet QControlBox::free_symbols() const { return op_->free_symbols(); } | ||
376 | ||||
377 | ✗ | std::string QControlBox::get_command_str(const unit_vector_t &args) const { | ||
378 | ✗ | std::stringstream out; | ||
379 | ✗ | out << "qif ("; | ||
380 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | if (n_controls_ > 0) { | |
381 | ✗ | out << args.at(0).repr(); | ||
382 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | for (unsigned i = 1; i < n_controls_; ++i) { | |
383 | ✗ | out << ", " << args.at(i).repr(); | ||
384 | } | |||
385 | } | |||
386 | ✗ | unit_vector_t inner_args(args.begin() + n_controls_, args.end()); | ||
387 | ✗ | out << ") " << op_->get_command_str(inner_args); | ||
388 | ✗ | return out.str(); | ||
389 | } | |||
390 | ||||
391 | 28 | void QControlBox::generate_circuit() const { | ||
392 |
1/2✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | Circuit c(n_inner_qubits_); | |
393 |
1/2✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | std::vector<unsigned> qbs(n_inner_qubits_); | |
394 | 28 | std::iota(qbs.begin(), qbs.end(), 0); | ||
395 |
1/2✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | c.add_op(op_, qbs); | |
396 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | c.decompose_boxes_recursively(); | |
397 |
2/4✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
|
28 | c = with_controls(c, n_controls_); | |
398 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | circ_ = std::make_shared<Circuit>(c); | |
399 | 28 | } | ||
400 | ||||
401 | ✗ | Op_ptr QControlBox::dagger() const { | ||
402 | ✗ | const Op_ptr inner_dagger = op_->dagger(); | ||
403 | ✗ | return std::make_shared<QControlBox>(inner_dagger, n_controls_); | ||
404 | } | |||
405 | ||||
406 | ✗ | Op_ptr QControlBox::transpose() const { | ||
407 | ✗ | const Op_ptr inner_transpose = op_->transpose(); | ||
408 | ✗ | return std::make_shared<QControlBox>(inner_transpose, n_controls_); | ||
409 | } | |||
410 | ||||
411 | 2 | ProjectorAssertionBox::ProjectorAssertionBox( | ||
412 | 2 | const Eigen::MatrixXcd &m, BasisOrder basis) | ||
413 | ✗ | : Box(OpType::ProjectorAssertionBox), | ||
414 |
1/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
2 | m_(basis == BasisOrder::ilo ? m : reverse_indexing(m)), | |
415 |
3/6✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
|
4 | expected_readouts_({}) { | |
416 |
7/12✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 2 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 2 times.
|
2 | if ((m.rows() != 2 && m.rows() != 4 && m.rows() != 8) || !is_projector(m)) { |
417 | ✗ | throw CircuitInvalidity( | ||
418 | "Matrix for ProjectorAssertionBox must be a 2x2, 4x4, or 8x8 " | |||
419 | ✗ | "projector"); | ||
420 | } | |||
421 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | generate_circuit(); | |
422 | 2 | } | ||
423 | ||||
424 | 8 | ProjectorAssertionBox::ProjectorAssertionBox(const ProjectorAssertionBox &other) | ||
425 |
2/4✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
|
8 | : Box(other), m_(other.m_), expected_readouts_(other.expected_readouts_) {} | |
426 | ||||
427 | ✗ | Op_ptr ProjectorAssertionBox::dagger() const { | ||
428 | ✗ | return std::make_shared<ProjectorAssertionBox>(m_.adjoint()); | ||
429 | } | |||
430 | ||||
431 | ✗ | Op_ptr ProjectorAssertionBox::transpose() const { | ||
432 | ✗ | return std::make_shared<ProjectorAssertionBox>(m_.transpose()); | ||
433 | } | |||
434 | ||||
435 | 32 | op_signature_t ProjectorAssertionBox::get_signature() const { | ||
436 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | auto circ_ptr = to_circuit(); | |
437 |
2/4✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 32 times.
✗ Branch 7 not taken.
|
32 | op_signature_t qubs(circ_ptr->n_qubits(), EdgeType::Quantum); | |
438 |
2/4✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 32 times.
✗ Branch 7 not taken.
|
32 | op_signature_t bs(circ_ptr->n_bits(), EdgeType::Classical); | |
439 |
1/2✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
|
32 | qubs.insert(qubs.end(), bs.begin(), bs.end()); | |
440 | 64 | return qubs; | ||
441 | 32 | } | ||
442 | ||||
443 | 2 | void ProjectorAssertionBox::generate_circuit() const { | ||
444 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | Circuit c; | |
445 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | std::tie(c, expected_readouts_) = projector_assertion_synthesis(m_); | |
446 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | c.decompose_boxes_recursively(); | |
447 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | circ_ = std::make_shared<Circuit>(c); | |
448 | 2 | } | ||
449 | ||||
450 | 5 | StabiliserAssertionBox::StabiliserAssertionBox( | ||
451 | 5 | const PauliStabiliserList &paulis) | ||
452 | ✗ | : Box(OpType::StabiliserAssertionBox), | ||
453 | 7 | paulis_(paulis), | ||
454 |
3/6✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
|
5 | expected_readouts_({}) { | |
455 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
|
5 | generate_circuit(); | |
456 | 9 | } | ||
457 | ||||
458 | 6 | StabiliserAssertionBox::StabiliserAssertionBox( | ||
459 | 6 | const StabiliserAssertionBox &other) | ||
460 | : Box(other), | |||
461 | 6 | paulis_(other.paulis_), | ||
462 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
6 | expected_readouts_(other.expected_readouts_) {} | |
463 | ||||
464 | ✗ | Op_ptr StabiliserAssertionBox::dagger() const { | ||
465 | ✗ | return std::make_shared<StabiliserAssertionBox>(paulis_); | ||
466 | } | |||
467 | ||||
468 | ✗ | Op_ptr StabiliserAssertionBox::transpose() const { | ||
469 | ✗ | PauliStabiliserList new_pauli_list; | ||
470 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | for (auto &pauli : paulis_) { | |
471 | int y_pauli_counter = | |||
472 | ✗ | std::count(pauli.string.begin(), pauli.string.end(), Pauli::Y); | ||
473 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | if (y_pauli_counter % 2 == 0) { | |
474 | ✗ | new_pauli_list.push_back(PauliStabiliser(pauli.string, pauli.coeff)); | ||
475 | } else { | |||
476 | ✗ | new_pauli_list.push_back(PauliStabiliser(pauli.string, !pauli.coeff)); | ||
477 | }; | |||
478 | } | |||
479 | ✗ | return std::make_shared<StabiliserAssertionBox>(new_pauli_list); | ||
480 | } | |||
481 | ||||
482 | 5 | void StabiliserAssertionBox::generate_circuit() const { | ||
483 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | Circuit c; | |
484 |
3/4✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
|
5 | std::tie(c, expected_readouts_) = stabiliser_assertion_synthesis(paulis_); | |
485 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | c.decompose_boxes_recursively(); | |
486 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | circ_ = std::make_shared<Circuit>(c); | |
487 | 5 | } | ||
488 | ||||
489 | 20 | op_signature_t StabiliserAssertionBox::get_signature() const { | ||
490 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | auto circ_ptr = to_circuit(); | |
491 |
2/4✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
|
20 | op_signature_t qubs(circ_ptr->n_qubits(), EdgeType::Quantum); | |
492 |
2/4✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
|
20 | op_signature_t bs(circ_ptr->n_bits(), EdgeType::Classical); | |
493 |
1/2✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
|
20 | qubs.insert(qubs.end(), bs.begin(), bs.end()); | |
494 | 40 | return qubs; | ||
495 | 20 | } | ||
496 | ||||
497 | 8 | ToffoliBox::ToffoliBox( | ||
498 | unsigned _n_qubits, | |||
499 | 8 | std::map<std::vector<bool>, std::vector<bool>> _permutation) | ||
500 |
1/2✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | : Box(OpType::ToffoliBox), n_qubits_(_n_qubits) { | |
501 | // Convert passed permutation to cycles | |||
502 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
|
2/2✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 8 times.
|
16 | while (!_permutation.empty()) { |
503 | 8 | auto it = _permutation.begin(); | ||
504 |
2/4✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
|
24 | cycle_permutation_t cycle = {it->first}; | |
505 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 8 times.
|
8 | if (it->first.size() != this->n_qubits_) { |
506 | ✗ | throw std::invalid_argument( | ||
507 | ✗ | "Size of bitstring does not match number of qubits."); | ||
508 | } | |||
509 |
1/2✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | it = _permutation.find(it->second); | |
510 |
3/4✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 8 times.
|
0/1? Decision couldn't be analyzed.
|
26 | while (it->first != cycle[0]) { |
511 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 18 times.
|
18 | if (it->first.size() != this->n_qubits_) { |
512 | ✗ | throw std::invalid_argument( | ||
513 | ✗ | "Size of bitstring does not match number of qubits."); | ||
514 | } | |||
515 |
1/2✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
18 | cycle.push_back(it->first); | |
516 |
1/2✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
18 | it = _permutation.find(it->second); | |
517 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 18 times.
|
18 | if (it == _permutation.end()) { |
518 | ✗ | throw std::invalid_argument("Permutation is not complete."); | ||
519 | } | |||
520 | } | |||
521 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
1/2✓ Decision 'true' taken 8 times.
✗ Decision 'false' not taken.
|
8 | if (cycle.size() > 1) { |
522 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | this->cycles_.insert(cycle); | |
523 | } | |||
524 |
2/2✓ Branch 5 taken 26 times.
✓ Branch 6 taken 8 times.
|
2/2✓ Decision 'true' taken 26 times.
✓ Decision 'false' taken 8 times.
|
34 | for (const std::vector<bool> &bitstring : cycle) { |
525 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | _permutation.erase(bitstring); | |
526 | } | |||
527 | 8 | } | ||
528 | 8 | } | ||
529 | ||||
530 | 2 | ToffoliBox::ToffoliBox(const ToffoliBox &other) | ||
531 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | : Box(other), n_qubits_(other.n_qubits_), cycles_(other.cycles_) {} | |
532 | ||||
533 | 1 | ToffoliBox::ToffoliBox( | ||
534 | 1 | unsigned _n_qubits, const std::set<cycle_permutation_t> &_cycles) | ||
535 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
1 | : Box(OpType::ToffoliBox), n_qubits_(_n_qubits), cycles_(_cycles) {} | |
536 | ||||
537 | 139 | unsigned get_hamming_distance( | ||
538 | const std::vector<bool> &a, const std::vector<bool> &b) { | |||
539 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 139 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 139 times.
|
139 | if (a.size() != b.size()) { |
540 | ✗ | throw std::invalid_argument("Bitstrings must have identical size."); | ||
541 | } | |||
542 | 139 | unsigned counter = 0; | ||
543 |
2/2✓ Branch 1 taken 456 times.
✓ Branch 2 taken 139 times.
|
2/2✓ Decision 'true' taken 456 times.
✓ Decision 'false' taken 139 times.
|
595 | for (unsigned i = 0; i < a.size(); i++) { |
544 |
2/2✓ Branch 2 taken 250 times.
✓ Branch 3 taken 206 times.
|
2/2✓ Decision 'true' taken 250 times.
✓ Decision 'false' taken 206 times.
|
456 | if (a[i] != b[i]) { |
545 | 250 | ++counter; | ||
546 | } | |||
547 | } | |||
548 | 139 | return counter; | ||
549 | } | |||
550 | ||||
551 | 7 | ToffoliBox::cycle_transposition_t ToffoliBox::cycle_to_transposition( | ||
552 | cycle_permutation_t cycle) const { | |||
553 | /** | |||
554 | * A cycle can start at any element | |||
555 | * A transposition for a cycle can always be constructed by pairing the | |||
556 | * starting element with the others in cycle order | |||
557 | * This also gives opportunities to produce gray codes with matching elements | |||
558 | * that can be cancelled | |||
559 | * | |||
560 | * For each element in a cycle, produce a sequence of transpositions and | |||
561 | * compare total Hamming distance Return the transposition with smallest | |||
562 | * Hamming distance | |||
563 | * | |||
564 | */ | |||
565 | 7 | cycle_transposition_t best_transposition; | ||
566 | 7 | unsigned best_hamming_distance = 0; | ||
567 | ||||
568 |
2/2✓ Branch 1 taken 24 times.
✓ Branch 2 taken 7 times.
|
2/2✓ Decision 'true' taken 24 times.
✓ Decision 'false' taken 7 times.
|
31 | for (unsigned i = 0; i < cycle.size(); i++) { |
569 | 24 | unsigned accumulated_hamming_distance = 0; | ||
570 | 24 | cycle_transposition_t transposition; | ||
571 |
2/2✓ Branch 1 taken 88 times.
✓ Branch 2 taken 24 times.
|
2/2✓ Decision 'true' taken 88 times.
✓ Decision 'false' taken 24 times.
|
112 | for (unsigned j = 1; j < cycle.size(); j++) { |
572 |
4/8✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 88 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 88 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 88 times.
✗ Branch 14 not taken.
|
88 | transposition.push_back({cycle[0], cycle[j], cycle[0]}); | |
573 |
1/2✓ Branch 3 taken 88 times.
✗ Branch 4 not taken.
|
88 | accumulated_hamming_distance += get_hamming_distance(cycle[0], cycle[j]); | |
574 | } | |||
575 |
6/6✓ Branch 1 taken 17 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 16 times.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 21 times.
|
24 | if (best_transposition.empty() || |
576 | accumulated_hamming_distance < best_hamming_distance) { | |||
577 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | best_transposition = transposition; | |
578 | 8 | best_hamming_distance = accumulated_hamming_distance; | ||
579 | } | |||
580 |
1/2✓ Branch 5 taken 24 times.
✗ Branch 6 not taken.
|
24 | std::rotate(cycle.begin(), cycle.begin() + 1, cycle.end()); | |
581 | 24 | } | ||
582 | 7 | return best_transposition; | ||
583 | } | |||
584 | ||||
585 | 7 | std::vector<ToffoliBox::cycle_transposition_t> ToffoliBox::get_transpositions() | ||
586 | const { | |||
587 | 7 | std::vector<ToffoliBox::cycle_transposition_t> transpositions; | ||
588 |
2/2✓ Branch 4 taken 7 times.
✓ Branch 5 taken 7 times.
|
14 | for (const cycle_permutation_t &cycle : this->cycles_) { | |
589 | // each cycle is costed via the Hamming distance to reduce the number of | |||
590 | // operations | |||
591 |
3/6✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
|
7 | transpositions.push_back(this->cycle_to_transposition(cycle)); | |
592 | } | |||
593 | 7 | return transpositions; | ||
594 | } | |||
595 | ||||
596 | 31 | Circuit ToffoliBox::get_bitstring_circuit( | ||
597 | const std::vector<bool> &bitstring, const unsigned &target) const { | |||
598 | // flip qubits that need to be state 0 | |||
599 |
1/2✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
|
31 | Circuit x_circuit(this->n_qubits_); | |
600 | 31 | std::vector<unsigned> cnx_args; | ||
601 |
2/2✓ Branch 0 taken 92 times.
✓ Branch 1 taken 31 times.
|
123 | for (unsigned i = 0; i < this->n_qubits_; i++) { | |
602 |
2/2✓ Branch 0 taken 61 times.
✓ Branch 1 taken 31 times.
|
92 | if (i != target) { | |
603 |
3/4✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 34 times.
|
61 | if (!bitstring[i]) { | |
604 |
2/4✓ Branch 3 taken 27 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 27 times.
✗ Branch 7 not taken.
|
27 | x_circuit.add_op<unsigned>(OpType::X, {i}); | |
605 | } | |||
606 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
61 | cnx_args.push_back(i); | |
607 | } | |||
608 | } | |||
609 |
1/2✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
|
31 | cnx_args.push_back(target); | |
610 | TKET_ASSERT(cnx_args.size() == this->n_qubits_); | |||
611 | ||||
612 |
1/2✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
|
31 | Circuit return_circuit(this->n_qubits_); | |
613 |
1/2✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
|
31 | return_circuit.append(x_circuit); | |
614 |
1/2✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
|
31 | return_circuit.add_op<unsigned>(OpType::CnX, cnx_args); | |
615 |
1/2✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
|
31 | return_circuit.append(x_circuit); | |
616 | 62 | return return_circuit; | ||
617 | 31 | } | ||
618 | ||||
619 | 17 | ToffoliBox::gray_code_t ToffoliBox::transposition_to_gray_code( | ||
620 | const ToffoliBox::transposition_t &transposition) const { | |||
621 | unsigned first_middle_hamming_distance = | |||
622 |
1/2✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
|
17 | get_hamming_distance(transposition.first, transposition.middle); | |
623 | unsigned middle_last_hamming_distance = | |||
624 |
1/2✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
|
17 | get_hamming_distance(transposition.middle, transposition.last); | |
625 | 17 | ToffoliBox::gray_code_t all_gray_code_entries; | ||
626 | // => that some optimisation is done to middle_last, so must go via | |||
627 | // transposition.last bitstring to allow proper cancellation | |||
628 | // At some point transposition.first == transposition.last | |||
629 | // If transposition.last != transposition.first & the hamming distance | |||
630 | // between transposition.last and transposition.middle is smaller than | |||
631 | // transposition.first and transposition.middle, | |||
632 | // then we need to make sure that the gray code between transposition.first | |||
633 | // and transposition.middle goes via transposition.last, such that the | |||
634 | // eventual gray code between transposition.middle and transposition.last | |||
635 | // uncomputes this we can assume that the remaining | |||
636 | // transposition.last->transposition.first gray code would be cancelled out if | |||
637 | // added | |||
638 |
1/2✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
|
17 | std::vector<bool> initial = transposition.first; | |
639 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 12 times.
|
17 | if (middle_last_hamming_distance < first_middle_hamming_distance) { | |
640 | // get bitstrings for first -> last | |||
641 |
2/2✓ Branch 1 taken 17 times.
✓ Branch 2 taken 5 times.
|
22 | for (unsigned i = 0; i < transposition.first.size(); i++) { | |
642 |
4/6✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 11 times.
|
17 | if (transposition.first[i] != transposition.last[i]) { | |
643 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
6 | initial[i] = !initial[i]; | |
644 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | all_gray_code_entries.push_back({initial, i}); | |
645 | } | |||
646 | } | |||
647 | } | |||
648 | // with the right middle bitstring now guaranteed, go from this bitstring to | |||
649 | // middle | |||
650 |
1/2✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
|
17 | std::vector<bool> bitstring = initial; | |
651 |
2/2✓ Branch 1 taken 50 times.
✓ Branch 2 taken 17 times.
|
67 | for (unsigned i = 0; i < transposition.first.size(); i++) { | |
652 |
4/6✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 50 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 18 times.
✓ Branch 8 taken 32 times.
|
50 | if (initial[i] != transposition.middle[i]) { | |
653 |
2/4✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
|
18 | bitstring[i] = !bitstring[i]; | |
654 |
2/4✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
|
18 | all_gray_code_entries.push_back({bitstring, i}); | |
655 | } | |||
656 | } | |||
657 | // now do the last->middle in reverse to guarantee right | |||
658 | // gray code path is taken | |||
659 |
1/2✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
|
17 | initial = transposition.last; | |
660 | 17 | ToffoliBox::gray_code_t reverse_gray_code_entries; | ||
661 | // as before, implies some optimisation has been completed on | |||
662 | // first one | |||
663 | // thus make sure that gray code goes via transposition.first | |||
664 | // to make applied permutation right | |||
665 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 12 times.
|
17 | if (first_middle_hamming_distance < middle_last_hamming_distance) { | |
666 | // get bitstrings for first -> last | |||
667 |
2/2✓ Branch 1 taken 17 times.
✓ Branch 2 taken 5 times.
|
22 | for (unsigned i = 0; i < transposition.first.size(); i++) { | |
668 |
4/6✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 11 times.
|
17 | if (initial[i] != transposition.first[i]) { | |
669 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
6 | initial[i] = !initial[i]; | |
670 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | reverse_gray_code_entries.push_back({initial, i}); | |
671 | } | |||
672 | } | |||
673 | } | |||
674 | // and then go from bitstring to middle | |||
675 |
1/2✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
|
17 | bitstring = initial; | |
676 |
2/2✓ Branch 1 taken 50 times.
✓ Branch 2 taken 17 times.
|
67 | for (unsigned i = 0; i < transposition.middle.size(); i++) { | |
677 |
4/6✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18 times.
✓ Branch 8 taken 32 times.
|
50 | if (transposition.middle[i] != initial[i]) { | |
678 |
2/4✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
|
18 | bitstring[i] = !bitstring[i]; | |
679 |
2/4✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
|
18 | reverse_gray_code_entries.push_back({bitstring, i}); | |
680 | } | |||
681 | } | |||
682 | // don't want to add transformation for reaching final -> so pop_back | |||
683 |
1/2✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
|
17 | if (!reverse_gray_code_entries.empty()) { | |
684 | 17 | reverse_gray_code_entries.pop_back(); | ||
685 | } | |||
686 |
1/2✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
|
17 | all_gray_code_entries.insert( | |
687 | 17 | all_gray_code_entries.end(), reverse_gray_code_entries.rbegin(), | ||
688 | 17 | reverse_gray_code_entries.rend()); | ||
689 | 34 | return all_gray_code_entries; | ||
690 | 17 | } | ||
691 | ||||
692 | 7 | ToffoliBox::cycle_transposition_t ToffoliBox::merge_cycles( | ||
693 | std::vector<ToffoliBox::cycle_transposition_t> &cycle_transpositions) | |||
694 | const { | |||
695 | 7 | ToffoliBox::cycle_transposition_t return_transposition; | ||
696 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 7 times.
|
14 | for (unsigned k = 0; k < cycle_transpositions.size(); k++) { | |
697 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | ToffoliBox::cycle_transposition_t cycle = cycle_transpositions[k]; | |
698 | 7 | unsigned i = 0, j = 1; | ||
699 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 7 times.
|
17 | while (j < cycle.size()) { | |
700 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | ToffoliBox::transposition_t transposition_i = cycle[i]; | |
701 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | ToffoliBox::transposition_t transposition_j = cycle[j]; | |
702 | ||||
703 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | std::vector<bool> transposition_j_first = transposition_j.first; | |
704 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | std::vector<bool> transposition_i_last = transposition_i.last; | |
705 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | std::vector<bool> transposition_i_first = transposition_i.first; | |
706 | ||||
707 | TKET_ASSERT(transposition_i_last == transposition_j.first); | |||
708 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | std::vector<bool> i_middle = transposition_i.middle; | |
709 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | std::vector<bool> j_middle = transposition_j.middle; | |
710 | ||||
711 | TKET_ASSERT(i_middle.size() == transposition_i.last.size()); | |||
712 | TKET_ASSERT(j_middle.size() == transposition_i.last.size()); | |||
713 | // if a transposition has already been reduced, still need to make sure we | |||
714 | // uncompute it | |||
715 |
3/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 6 times.
|
10 | if (transposition_i_first != transposition_i_last) { | |
716 | unsigned middle_last_distance = | |||
717 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | get_hamming_distance(i_middle, transposition_i_last); | |
718 | unsigned middle_first_distance = | |||
719 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | get_hamming_distance(i_middle, transposition_i_first); | |
720 | // this => the reduced transposition is on a good gray code between the | |||
721 | // new "first" and target | |||
722 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (middle_first_distance < middle_last_distance && | |
723 | middle_first_distance > 1) { | |||
724 | ✗ | transposition_i_last = transposition_i_first; | ||
725 | ✗ | std::vector<bool> starting_point = transposition_i_last; | ||
726 | ✗ | for (unsigned k = 0; k < i_middle.size(); k++) { | ||
727 | ✗ | if (i_middle[k] == j_middle[k] && | ||
728 | ✗ | get_hamming_distance(starting_point, i_middle) > 1) { | ||
729 | ✗ | starting_point[k] = i_middle[k]; | ||
730 | } | |||
731 | } | |||
732 | ||||
733 | ✗ | cycle_transpositions[k][i].last = starting_point; | ||
734 | ✗ | cycle_transpositions[k][j].first = starting_point; | ||
735 | } | |||
736 | } else { // else in this case just find any good transposition | |||
737 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | std::vector<bool> starting_point = transposition_i_last; | |
738 |
2/2✓ Branch 1 taken 21 times.
✓ Branch 2 taken 6 times.
|
27 | for (unsigned k = 0; k < i_middle.size(); k++) { | |
739 |
6/8✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✓ Branch 8 taken 12 times.
✓ Branch 9 taken 8 times.
✓ Branch 10 taken 13 times.
|
30 | if (i_middle[k] == j_middle[k] && | |
740 |
3/4✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 1 times.
|
9 | get_hamming_distance(starting_point, i_middle) > 1) { | |
741 |
2/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
8 | starting_point[k] = i_middle[k]; | |
742 | } | |||
743 | } | |||
744 | ||||
745 |
1/2✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | cycle[i].last = starting_point; | |
746 |
1/2✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | cycle[j].first = starting_point; | |
747 | 6 | } | ||
748 | ||||
749 | 10 | ++i; | ||
750 | 10 | ++j; | ||
751 | 10 | } | ||
752 | ||||
753 |
1/2✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
14 | return_transposition.insert( | |
754 | 7 | return_transposition.end(), cycle.begin(), cycle.end()); | ||
755 | 7 | } | ||
756 | ||||
757 | 7 | return return_transposition; | ||
758 | } | |||
759 | ||||
760 | 5 | op_signature_t ToffoliBox::get_signature() const { | ||
761 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | op_signature_t qubs(this->n_qubits_, EdgeType::Quantum); | |
762 | 5 | return qubs; | ||
763 | } | |||
764 | ||||
765 | 7 | void ToffoliBox::generate_circuit() const { | ||
766 | // This decomposition is as described on page 191, section 4.5.2 "Single | |||
767 | // qubit and CNOT gates are universal" of Nielsen & Chuang | |||
768 | std::vector<ToffoliBox::cycle_transposition_t> cycle_transpositions = | |||
769 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | this->get_transpositions(); | |
770 | ||||
771 | // optionally, order the transpositions and cycles to allow gate | |||
772 | // cancellation | |||
773 | 7 | cycle_transposition_t ordered_transpositions; | ||
774 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | ordered_transpositions = merge_cycles(cycle_transpositions); | |
775 | ||||
776 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6 times.
|
7 | if (ordered_transpositions.empty()) { | |
777 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | this->circ_ = std::make_shared<Circuit>(this->n_qubits_); | |
778 | 1 | return; | ||
779 | } | |||
780 | ||||
781 | // Now we have ordered transpositions, produced front->middle and | |||
782 | // middle->back gray codes for each transposition and add to circuit | |||
783 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | this->circ_ = std::make_shared<Circuit>(this->n_qubits_); | |
784 |
2/2✓ Branch 5 taken 17 times.
✓ Branch 6 taken 6 times.
|
23 | for (const transposition_t &transposition : ordered_transpositions) { | |
785 | TKET_ASSERT(transposition.first.size() == this->n_qubits_); | |||
786 | TKET_ASSERT(transposition.middle.size() == this->n_qubits_); | |||
787 | TKET_ASSERT(transposition.last.size() == this->n_qubits_); | |||
788 | ToffoliBox::gray_code_t all_gray_code_entries = | |||
789 |
1/2✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
|
17 | transposition_to_gray_code(transposition); | |
790 | 17 | for (const std::pair<std::vector<bool>, unsigned> &entry : | ||
791 |
2/2✓ Branch 4 taken 31 times.
✓ Branch 5 taken 17 times.
|
65 | all_gray_code_entries) { | |
792 |
1/2✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
|
62 | this->circ_->append( | |
793 |
1/2✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
|
62 | this->get_bitstring_circuit(entry.first, entry.second)); | |
794 | } | |||
795 | 17 | } | ||
796 |
4/4✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 1 times.
|
8 | } | |
797 | ||||
798 | 13 | nlohmann::json core_box_json(const Box &box) { | ||
799 | 13 | nlohmann::json j; | ||
800 |
2/4✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
|
13 | j["type"] = box.get_type(); | |
801 |
3/6✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 13 times.
✗ Branch 9 not taken.
|
13 | j["id"] = boost::lexical_cast<std::string>(box.get_id()); | |
802 | 13 | return j; | ||
803 | } | |||
804 | ||||
805 | 1 | nlohmann::json CircBox::to_json(const Op_ptr &op) { | ||
806 | 1 | const auto &box = static_cast<const CircBox &>(*op); | ||
807 | 1 | nlohmann::json j = core_box_json(box); | ||
808 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
1 | j["circuit"] = *(box.to_circuit()); | |
809 | 1 | return j; | ||
810 | } | |||
811 | ||||
812 | 1 | Op_ptr CircBox::from_json(const nlohmann::json &j) { | ||
813 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | CircBox box = CircBox(j.at("circuit").get<Circuit>()); | |
814 | return set_box_id( | |||
815 | box, | |||
816 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
3 | boost::lexical_cast<boost::uuids::uuid>(j.at("id").get<std::string>())); | |
817 | 1 | } | ||
818 | ||||
819 | 1 | nlohmann::json Unitary1qBox::to_json(const Op_ptr &op) { | ||
820 | 1 | const auto &box = static_cast<const Unitary1qBox &>(*op); | ||
821 | 1 | nlohmann::json j = core_box_json(box); | ||
822 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | j["matrix"] = box.get_matrix(); | |
823 | 1 | return j; | ||
824 | } | |||
825 | ||||
826 | 1 | Op_ptr Unitary1qBox::from_json(const nlohmann::json &j) { | ||
827 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | Unitary1qBox box = Unitary1qBox(j.at("matrix").get<Eigen::Matrix2cd>()); | |
828 | return set_box_id( | |||
829 | box, | |||
830 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
3 | boost::lexical_cast<boost::uuids::uuid>(j.at("id").get<std::string>())); | |
831 | 1 | } | ||
832 | ||||
833 | 1 | nlohmann::json Unitary2qBox::to_json(const Op_ptr &op) { | ||
834 | 1 | const auto &box = static_cast<const Unitary2qBox &>(*op); | ||
835 | 1 | nlohmann::json j = core_box_json(box); | ||
836 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | j["matrix"] = box.get_matrix(); | |
837 | 1 | return j; | ||
838 | } | |||
839 | ||||
840 | 1 | Op_ptr Unitary2qBox::from_json(const nlohmann::json &j) { | ||
841 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | Unitary2qBox box = Unitary2qBox(j.at("matrix").get<Eigen::Matrix4cd>()); | |
842 | return set_box_id( | |||
843 | box, | |||
844 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
3 | boost::lexical_cast<boost::uuids::uuid>(j.at("id").get<std::string>())); | |
845 | 1 | } | ||
846 | 1 | nlohmann::json Unitary3qBox::to_json(const Op_ptr &op) { | ||
847 | 1 | const auto &box = static_cast<const Unitary3qBox &>(*op); | ||
848 | 1 | nlohmann::json j = core_box_json(box); | ||
849 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | j["matrix"] = box.get_matrix(); | |
850 | 1 | return j; | ||
851 | } | |||
852 | ||||
853 | 1 | Op_ptr Unitary3qBox::from_json(const nlohmann::json &j) { | ||
854 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | Unitary3qBox box = Unitary3qBox(j.at("matrix").get<Matrix8cd>()); | |
855 | return set_box_id( | |||
856 | box, | |||
857 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
3 | boost::lexical_cast<boost::uuids::uuid>(j.at("id").get<std::string>())); | |
858 | 1 | } | ||
859 | ||||
860 | 1 | nlohmann::json ExpBox::to_json(const Op_ptr &op) { | ||
861 | 1 | const auto &box = static_cast<const ExpBox &>(*op); | ||
862 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | nlohmann::json j = core_box_json(box); | |
863 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const auto &matrix_phase = box.get_matrix_and_phase(); | |
864 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | j["matrix"] = matrix_phase.first; | |
865 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | j["phase"] = matrix_phase.second; | |
866 | 2 | return j; | ||
867 | } | |||
868 | ||||
869 | 1 | Op_ptr ExpBox::from_json(const nlohmann::json &j) { | ||
870 | ExpBox box = ExpBox( | |||
871 |
5/10✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
|
1 | j.at("matrix").get<Eigen::Matrix4cd>(), j.at("phase").get<double>()); | |
872 | return set_box_id( | |||
873 | box, | |||
874 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
3 | boost::lexical_cast<boost::uuids::uuid>(j.at("id").get<std::string>())); | |
875 | 1 | } | ||
876 | ||||
877 | 1 | nlohmann::json PauliExpBox::to_json(const Op_ptr &op) { | ||
878 | 1 | const auto &box = static_cast<const PauliExpBox &>(*op); | ||
879 | 1 | nlohmann::json j = core_box_json(box); | ||
880 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | j["paulis"] = box.get_paulis(); | |
881 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | j["phase"] = box.get_phase(); | |
882 | 1 | return j; | ||
883 | } | |||
884 | ||||
885 | 1 | Op_ptr PauliExpBox::from_json(const nlohmann::json &j) { | ||
886 | PauliExpBox box = PauliExpBox( | |||
887 |
5/10✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
|
2 | j.at("paulis").get<std::vector<Pauli>>(), j.at("phase").get<Expr>()); | |
888 | return set_box_id( | |||
889 | box, | |||
890 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
3 | boost::lexical_cast<boost::uuids::uuid>(j.at("id").get<std::string>())); | |
891 | 1 | } | ||
892 | ||||
893 | 1 | nlohmann::json ToffoliBox::to_json(const Op_ptr &op) { | ||
894 | 1 | const auto &box = static_cast<const ToffoliBox &>(*op); | ||
895 | 1 | nlohmann::json j = core_box_json(box); | ||
896 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | j["cycles"] = box.get_cycles(); | |
897 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1 | j["n_qubits"] = box.get_n_qubits(); | |
898 | 1 | return j; | ||
899 | } | |||
900 | ||||
901 | 1 | Op_ptr ToffoliBox::from_json(const nlohmann::json &j) { | ||
902 | ToffoliBox box = ToffoliBox( | |||
903 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | j.at("n_qubits").get<unsigned>(), | |
904 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
2 | j.at("cycles").get<std::set<ToffoliBox::cycle_permutation_t>>()); | |
905 | return set_box_id( | |||
906 | box, | |||
907 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
3 | boost::lexical_cast<boost::uuids::uuid>(j.at("id").get<std::string>())); | |
908 | 1 | } | ||
909 | ||||
910 | 2 | void to_json(nlohmann::json &j, const composite_def_ptr_t &cdef) { | ||
911 |
2/4✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
2 | j["name"] = cdef->get_name(); | |
912 |
2/4✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | j["definition"] = *cdef->get_def(); | |
913 |
2/4✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
2 | j["args"] = cdef->get_args(); | |
914 | 2 | } | ||
915 | ||||
916 | 2 | void from_json(const nlohmann::json &j, composite_def_ptr_t &cdef) { | ||
917 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
4 | cdef = CompositeGateDef::define_gate( | |
918 |
4/8✓ 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.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
|
4 | j.at("name").get<std::string>(), j.at("definition").get<Circuit>(), | |
919 | 6 | j.at("args").get<std::vector<Sym>>()); | ||
920 | 2 | } | ||
921 | ||||
922 | 2 | nlohmann::json CustomGate::to_json(const Op_ptr &op) { | ||
923 | 2 | const auto &box = static_cast<const CustomGate &>(*op); | ||
924 | 2 | nlohmann::json j = core_box_json(box); | ||
925 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | j["gate"] = box.get_gate(); | |
926 |
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 | j["params"] = box.get_params(); | |
927 | 2 | return j; | ||
928 | } | |||
929 | ||||
930 | 2 | Op_ptr CustomGate::from_json(const nlohmann::json &j) { | ||
931 | CustomGate box = CustomGate( | |||
932 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
4 | j.at("gate").get<composite_def_ptr_t>(), | |
933 |
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.
|
4 | j.at("params").get<std::vector<Expr>>()); | |
934 | return set_box_id( | |||
935 | box, | |||
936 |
4/8✓ 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.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
|
6 | boost::lexical_cast<boost::uuids::uuid>(j.at("id").get<std::string>())); | |
937 | 2 | } | ||
938 | ||||
939 | 1 | nlohmann::json QControlBox::to_json(const Op_ptr &op) { | ||
940 | 1 | const auto &box = static_cast<const QControlBox &>(*op); | ||
941 | 1 | nlohmann::json j = core_box_json(box); | ||
942 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1 | j["n_controls"] = box.get_n_controls(); | |
943 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | j["op"] = box.get_op(); | |
944 | 1 | return j; | ||
945 | } | |||
946 | ||||
947 | 1 | Op_ptr QControlBox::from_json(const nlohmann::json &j) { | ||
948 | QControlBox box = | |||
949 |
5/10✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
|
1 | QControlBox(j.at("op").get<Op_ptr>(), j.at("n_controls").get<unsigned>()); | |
950 | return set_box_id( | |||
951 | box, | |||
952 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
3 | boost::lexical_cast<boost::uuids::uuid>(j.at("id").get<std::string>())); | |
953 | 1 | } | ||
954 | ||||
955 | ✗ | nlohmann::json ProjectorAssertionBox::to_json(const Op_ptr &op) { | ||
956 | ✗ | const auto &box = static_cast<const ProjectorAssertionBox &>(*op); | ||
957 | ✗ | nlohmann::json j = core_box_json(box); | ||
958 | ✗ | j["matrix"] = box.get_matrix(); | ||
959 | ✗ | return j; | ||
960 | } | |||
961 | ||||
962 | ✗ | Op_ptr ProjectorAssertionBox::from_json(const nlohmann::json &j) { | ||
963 | ProjectorAssertionBox box = | |||
964 | ✗ | ProjectorAssertionBox(j.at("matrix").get<Eigen::MatrixXcd>()); | ||
965 | return set_box_id( | |||
966 | box, | |||
967 | ✗ | boost::lexical_cast<boost::uuids::uuid>(j.at("id").get<std::string>())); | ||
968 | } | |||
969 | ||||
970 | 1 | nlohmann::json StabiliserAssertionBox::to_json(const Op_ptr &op) { | ||
971 | 1 | const auto &box = static_cast<const StabiliserAssertionBox &>(*op); | ||
972 | 1 | nlohmann::json j = core_box_json(box); | ||
973 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | j["stabilisers"] = box.get_stabilisers(); | |
974 | 1 | return j; | ||
975 | } | |||
976 | ||||
977 | 1 | Op_ptr StabiliserAssertionBox::from_json(const nlohmann::json &j) { | ||
978 | StabiliserAssertionBox box = | |||
979 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | StabiliserAssertionBox(j.at("stabilisers").get<PauliStabiliserList>()); | |
980 | return set_box_id( | |||
981 | box, | |||
982 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
3 | boost::lexical_cast<boost::uuids::uuid>(j.at("id").get<std::string>())); | |
983 | 1 | } | ||
984 | ||||
985 | // use macro to register converters defined in this file with OpJsonFactory | |||
986 | REGISTER_OPFACTORY(CircBox, CircBox) | |||
987 | REGISTER_OPFACTORY(Unitary1qBox, Unitary1qBox) | |||
988 | REGISTER_OPFACTORY(Unitary2qBox, Unitary2qBox) | |||
989 | REGISTER_OPFACTORY(Unitary3qBox, Unitary3qBox) | |||
990 | REGISTER_OPFACTORY(ExpBox, ExpBox) | |||
991 | REGISTER_OPFACTORY(PauliExpBox, PauliExpBox) | |||
992 | REGISTER_OPFACTORY(CustomGate, CustomGate) | |||
993 | REGISTER_OPFACTORY(QControlBox, QControlBox) | |||
994 | REGISTER_OPFACTORY(ProjectorAssertionBox, ProjectorAssertionBox) | |||
995 | REGISTER_OPFACTORY(StabiliserAssertionBox, StabiliserAssertionBox) | |||
996 | REGISTER_OPFACTORY(ToffoliBox, ToffoliBox) | |||
997 | } // namespace tket | |||
998 |