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 "Characterisation/FrameRandomisation.hpp" | |||
16 | ||||
17 | #include <random> | |||
18 | ||||
19 | #include "Ops/MetaOp.hpp" | |||
20 | #include "PauliGraph/ConjugatePauliFunctions.hpp" | |||
21 | #include "Utils/PauliStrings.hpp" | |||
22 | ||||
23 | namespace tket { | |||
24 | ||||
25 | class FrameRandomisationError : public std::logic_error { | |||
26 | public: | |||
27 | ✗ | explicit FrameRandomisationError(const std::string& message) | ||
28 | ✗ | : std::logic_error(message) {} | ||
29 | }; | |||
30 | ||||
31 | ✗ | std::string FrameRandomisation::to_string() const { | ||
32 | ✗ | std::string str = "<tket::FrameRandomisation, Cycle OpTypeSet: "; | ||
33 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | for (const OpType& ot : cycle_types_) { | |
34 | ✗ | OpDesc od(ot); | ||
35 | ✗ | str.append(od.name() + " "); | ||
36 | } | |||
37 | ✗ | str.append(", Frame OpTypeSet: "); | ||
38 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | for (const OpType& ot : frame_types_) { | |
39 | ✗ | OpDesc od(ot); | ||
40 | ✗ | str.append(od.name() + " "); | ||
41 | } | |||
42 | ✗ | str.append(">"); | ||
43 | ✗ | return str; | ||
44 | } | |||
45 | ||||
46 | // Wires Identity gates into each cycle edge. Identity gates then relabelled | |||
47 | // with Ops from OpTypeSet to create instances of Frame Randomisation | |||
48 | 15 | void add_noop_frames(std::vector<Cycle>& cycles, Circuit& circ) { | ||
49 | 15 | std::map<Edge, Edge> replacement_rewiring_edges; | ||
50 |
2/2✓ Branch 5 taken 18 times.
✓ Branch 6 taken 15 times.
|
2/2✓ Decision 'true' taken 18 times.
✓ Decision 'false' taken 15 times.
|
33 | for (Cycle& full_cycle : cycles) { |
51 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | std::vector<edge_pair_t> cycle = full_cycle.boundary_edges_; | |
52 | // wire "noop" vertices into each cycle edge | |||
53 | // these are later relabelled with frame gates | |||
54 | // also wire "barrier" vertices between "noop" vertices and cycle gates | |||
55 | // i.e. something like this: | |||
56 | // ---C--- | |||
57 | // | | |||
58 | // ---X--- | |||
59 | // to | |||
60 | // -noop--B--C--B--noop- | |||
61 | // A | A | |||
62 | // -noop--R--X--R--noop- | |||
63 | // R R | |||
64 | // I I | |||
65 | // E E | |||
66 | // R R | |||
67 | ||||
68 | 18 | EdgeVec barrier_ins; | ||
69 | 18 | EdgeVec barrier_outs; | ||
70 |
2/2✓ Branch 4 taken 44 times.
✓ Branch 5 taken 18 times.
|
2/2✓ Decision 'true' taken 44 times.
✓ Decision 'false' taken 18 times.
|
62 | for (const std::pair<Edge, Edge>& boundary : cycle) { |
71 |
1/2✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
|
44 | Vertex input_noop_vert = circ.add_vertex(OpType::noop); | |
72 |
1/2✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
|
44 | Vertex output_noop_vert = circ.add_vertex(OpType::noop); | |
73 | 44 | Edge in_edge = boundary.first; | ||
74 | // boundary out edges can be equal to other boundary in edges | |||
75 | // rewiring a vertex into these out edges replace the edge | |||
76 | // first see if its been rewired and use new edge if necessary | |||
77 | std::map<Edge, Edge>::iterator it = | |||
78 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
44 | replacement_rewiring_edges.find(in_edge); | |
79 |
2/2✓ Branch 2 taken 1 times.
✓ Branch 3 taken 43 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 43 times.
|
44 | if (it != replacement_rewiring_edges.end()) { |
80 | 1 | in_edge = (*it).second; | ||
81 | } | |||
82 | ||||
83 |
3/6✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 44 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 44 times.
✗ Branch 10 not taken.
|
44 | circ.rewire(input_noop_vert, {in_edge}, {EdgeType::Quantum}); | |
84 |
3/6✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 44 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 44 times.
✗ Branch 10 not taken.
|
44 | circ.rewire(output_noop_vert, {boundary.second}, {EdgeType::Quantum}); | |
85 | ||||
86 | // Can guarantee both have one output edge only as just rewired | |||
87 | Edge input_noop_out_edge = | |||
88 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
44 | circ.get_out_edges_of_type(input_noop_vert, EdgeType::Quantum)[0]; | |
89 | Edge output_noop_in_edge = | |||
90 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
44 | circ.get_in_edges_of_type(output_noop_vert, EdgeType::Quantum)[0]; | |
91 | ||||
92 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
44 | barrier_ins.push_back(input_noop_out_edge); | |
93 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
44 | barrier_outs.push_back(output_noop_in_edge); | |
94 | ||||
95 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
44 | replacement_rewiring_edges[boundary.second] = | |
96 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
88 | circ.get_out_edges_of_type(output_noop_vert, EdgeType::Quantum)[0]; | |
97 |
1/2✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
|
44 | full_cycle.add_vertex_pair({input_noop_vert, output_noop_vert}); | |
98 | } | |||
99 |
1/2✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
|
18 | std::vector<EdgeType> sig(barrier_ins.size(), EdgeType::Quantum); | |
100 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | Op_ptr o_ptr = std::make_shared<MetaOp>(OpType::Barrier, sig); | |
101 |
1/2✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
|
18 | Vertex input_barrier_vert = circ.add_vertex(o_ptr); | |
102 |
1/2✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
|
18 | Vertex output_barrier_vert = circ.add_vertex(o_ptr); | |
103 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | circ.rewire(input_barrier_vert, barrier_ins, sig); | |
104 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | circ.rewire(output_barrier_vert, barrier_outs, sig); | |
105 | 18 | } | ||
106 | 15 | } | ||
107 | ||||
108 | 6 | std::vector<std::vector<OpTypeVector>> get_all_frame_permutations( | ||
109 | const unsigned& max_frame_size, const OpTypeSet& frame_types) { | |||
110 |
1/2✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | OpTypeVector base_otv(frame_types.begin(), frame_types.end()); | |
111 |
1/2✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 | std::sort(base_otv.begin(), base_otv.end()); | |
112 | 6 | std::vector<OpTypeVector> base_frame; | ||
113 |
2/2✓ Branch 4 taken 20 times.
✓ Branch 5 taken 6 times.
|
2/2✓ Decision 'true' taken 20 times.
✓ Decision 'false' taken 6 times.
|
26 | for (const OpType& ot : base_otv) { |
114 |
2/4✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
|
20 | base_frame.push_back({ot}); | |
115 | } | |||
116 |
1/2✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 | std::sort(base_frame.begin(), base_frame.end()); | |
117 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
18 | std::vector<std::vector<OpTypeVector>> out({base_frame}); | |
118 | ||||
119 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
2/2✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 6 times.
|
12 | for (unsigned i = 1; i < max_frame_size; i++) { |
120 | 6 | std::vector<OpTypeVector> new_ops; | ||
121 |
2/2✓ Branch 6 taken 20 times.
✓ Branch 7 taken 6 times.
|
2/2✓ Decision 'true' taken 20 times.
✓ Decision 'false' taken 6 times.
|
26 | for (const OpTypeVector& base_ops : out[0]) { |
122 |
2/2✓ Branch 6 taken 72 times.
✓ Branch 7 taken 20 times.
|
2/2✓ Decision 'true' taken 72 times.
✓ Decision 'false' taken 20 times.
|
92 | for (const OpTypeVector& merge_ops : out[i - 1]) { |
123 |
1/2✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
|
72 | OpTypeVector new_base(base_ops); | |
124 |
2/4✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 72 times.
✗ Branch 7 not taken.
|
72 | std::copy( | |
125 | merge_ops.begin(), merge_ops.end(), std::back_inserter(new_base)); | |||
126 |
1/2✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
|
72 | new_ops.push_back(new_base); | |
127 | 72 | } | ||
128 | } | |||
129 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | out.push_back(new_ops); | |
130 | 6 | } | ||
131 | 12 | return out; | ||
132 | 6 | } | ||
133 | ||||
134 | 3 | std::vector<std::vector<OpTypeVector>> combine_vectors( | ||
135 | const std::vector<std::vector<OpTypeVector>>& vec_0, | |||
136 | const std::vector<OpTypeVector>& vec_1) { | |||
137 | 3 | std::vector<std::vector<OpTypeVector>> new_vec; | ||
138 | ||||
139 |
2/2✓ Branch 5 taken 36 times.
✓ Branch 6 taken 3 times.
|
2/2✓ Decision 'true' taken 36 times.
✓ Decision 'false' taken 3 times.
|
39 | for (const std::vector<OpTypeVector>& base_frame : vec_0) { |
140 |
2/2✓ Branch 5 taken 336 times.
✓ Branch 6 taken 36 times.
|
2/2✓ Decision 'true' taken 336 times.
✓ Decision 'false' taken 36 times.
|
372 | for (const OpTypeVector& new_frame : vec_1) { |
141 |
1/2✓ Branch 1 taken 336 times.
✗ Branch 2 not taken.
|
336 | std::vector<OpTypeVector> copy = base_frame; | |
142 |
1/2✓ Branch 1 taken 336 times.
✗ Branch 2 not taken.
|
336 | copy.push_back(new_frame); | |
143 |
1/2✓ Branch 1 taken 336 times.
✗ Branch 2 not taken.
|
336 | new_vec.push_back(copy); | |
144 | 336 | } | ||
145 | } | |||
146 | 3 | return new_vec; | ||
147 | } | |||
148 | ||||
149 | 6 | std::vector<std::vector<OpTypeVector>> get_all_permutation_combinations( | ||
150 | const std::vector<unsigned>& frame_sizes, | |||
151 | const std::vector<std::vector<OpTypeVector>>& frame_permutations) { | |||
152 | 6 | std::vector<std::vector<OpTypeVector>> all_combinations; | ||
153 | ||||
154 |
2/2✓ Branch 6 taken 72 times.
✓ Branch 7 taken 6 times.
|
2/2✓ Decision 'true' taken 72 times.
✓ Decision 'false' taken 6 times.
|
78 | for (const OpTypeVector& frame : frame_permutations[frame_sizes[0] - 1]) { |
155 |
5/10✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 72 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 72 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 72 times.
✓ Branch 13 taken 72 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
144 | all_combinations.push_back({frame}); | |
156 | } | |||
157 | ||||
158 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 6 times.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 6 times.
|
9 | for (unsigned i = 1; i < frame_sizes.size(); i++) { |
159 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
6 | all_combinations = combine_vectors( | |
160 | 6 | all_combinations, frame_permutations[frame_sizes[i] - 1]); | ||
161 | } | |||
162 | 6 | return all_combinations; | ||
163 | } | |||
164 | ||||
165 | 200 | std::pair<OpTypeVector, std::vector<Vertex>> FrameRandomisation::get_out_frame( | ||
166 | const OpTypeVector& in_frame, const Cycle& cycle) { | |||
167 |
1/2✓ Branch 1 taken 200 times.
✗ Branch 2 not taken.
|
200 | OpTypeVector out_frame = in_frame; | |
168 |
2/2✓ Branch 5 taken 600 times.
✓ Branch 6 taken 200 times.
|
2/2✓ Decision 'true' taken 600 times.
✓ Decision 'false' taken 200 times.
|
800 | for (const CycleCom& cycle_op : cycle.coms_) { |
169 | 600 | OpTypeVector current_frame; | ||
170 |
2/2✓ Branch 5 taken 656 times.
✓ Branch 6 taken 600 times.
|
2/2✓ Decision 'true' taken 656 times.
✓ Decision 'false' taken 600 times.
|
1256 | for (const unsigned& u : cycle_op.indices) |
171 |
1/2✓ Branch 2 taken 656 times.
✗ Branch 3 not taken.
|
656 | current_frame.push_back(out_frame[u]); | |
172 |
3/4✓ Branch 1 taken 600 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 456 times.
✓ Branch 4 taken 144 times.
|
2/2✓ Decision 'true' taken 456 times.
✓ Decision 'false' taken 144 times.
|
600 | if (!is_initial_q_type(cycle_op.type)) { |
173 | current_frame = | |||
174 |
3/6✓ Branch 1 taken 456 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 456 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 456 times.
✗ Branch 8 not taken.
|
456 | (frame_cycle_conjugates_.at(cycle_op.type)).at(current_frame); | |
175 | } | |||
176 |
2/2✓ Branch 1 taken 656 times.
✓ Branch 2 taken 600 times.
|
2/2✓ Decision 'true' taken 656 times.
✓ Decision 'false' taken 600 times.
|
1256 | for (unsigned i = 0; i < current_frame.size(); i++) { |
177 | 656 | out_frame[cycle_op.indices[i]] = current_frame[i]; | ||
178 | } | |||
179 | 600 | } | ||
180 |
1/2✓ Branch 2 taken 200 times.
✗ Branch 3 not taken.
|
400 | return {out_frame, {}}; | |
181 | 200 | } | ||
182 | ||||
183 | std::pair<OpTypeVector, std::vector<Vertex>> | |||
184 | 36 | PauliFrameRandomisation::get_out_frame( | ||
185 | const OpTypeVector& in_frame, const Cycle& cycle) { | |||
186 | 36 | QubitPauliMap qpm; | ||
187 |
2/2✓ Branch 1 taken 92 times.
✓ Branch 2 taken 36 times.
|
2/2✓ Decision 'true' taken 92 times.
✓ Decision 'false' taken 36 times.
|
128 | for (unsigned i = 0; i < in_frame.size(); i++) { |
188 |
4/5✓ Branch 1 taken 27 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
|
92 | switch (in_frame[i]) { | |
189 |
1/1✓ Decision 'true' taken 27 times.
|
27 | case OpType::noop: | |
190 |
3/6✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 27 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 27 times.
✗ Branch 9 not taken.
|
27 | qpm[Qubit("frame", i)] = Pauli::I; | |
191 | 27 | break; | ||
192 |
1/1✓ Decision 'true' taken 21 times.
|
21 | case OpType::X: | |
193 |
3/6✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 21 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 21 times.
✗ Branch 9 not taken.
|
21 | qpm[Qubit("frame", i)] = Pauli::X; | |
194 | 21 | break; | ||
195 |
1/1✓ Decision 'true' taken 19 times.
|
19 | case OpType::Y: | |
196 |
3/6✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 19 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 19 times.
✗ Branch 9 not taken.
|
19 | qpm[Qubit("frame", i)] = Pauli::Y; | |
197 | 19 | break; | ||
198 |
1/1✓ Decision 'true' taken 25 times.
|
25 | case OpType::Z: | |
199 |
3/6✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 25 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 25 times.
✗ Branch 9 not taken.
|
25 | qpm[Qubit("frame", i)] = Pauli::Z; | |
200 | 25 | break; | ||
201 |
0/1✗ Decision 'true' not taken.
|
✗ | default: { | |
202 | ✗ | throw FrameRandomisationError(std::string( | ||
203 | ✗ | "Frame OpType " + OpDesc(in_frame[i]).name() + | ||
204 | ✗ | " not a Pauli OpType.")); | ||
205 | } | |||
206 | } | |||
207 | } | |||
208 | ||||
209 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
72 | QubitPauliTensor qpt(qpm); | |
210 | ||||
211 |
2/2✓ Branch 5 taken 198 times.
✓ Branch 6 taken 36 times.
|
2/2✓ Decision 'true' taken 198 times.
✓ Decision 'false' taken 36 times.
|
234 | for (const CycleCom& cycle_op : cycle.coms_) { |
212 |
3/5✓ Branch 0 taken 92 times.
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 66 times.
✗ Branch 4 not taken.
|
198 | switch (cycle_op.type) { | |
213 | 92 | case OpType::noop: | ||
214 | case OpType::Input: | |||
215 | case OpType::Create: | |||
216 | case OpType::Output: | |||
217 | case OpType::Discard: | |||
218 | 92 | break; | ||
219 | 40 | case OpType::H: | ||
220 | case OpType::S: | |||
221 | case OpType::X: | |||
222 | case OpType::V: | |||
223 | case OpType::Z: | |||
224 | case OpType::Y: | |||
225 | 40 | conjugate_PauliTensor( | ||
226 |
3/6✓ Branch 3 taken 40 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 40 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 40 times.
✗ Branch 10 not taken.
|
40 | qpt, cycle_op.type, Qubit("frame", cycle_op.indices[0]), false); | |
227 | 40 | break; | ||
228 | ✗ | case OpType::Vdg: | ||
229 | case OpType::Sdg: | |||
230 | ✗ | conjugate_PauliTensor( | ||
231 | ✗ | qpt, cycle_op.type, Qubit("frame", cycle_op.indices[0]), true); | ||
232 | ✗ | break; | ||
233 |
1/1✓ Decision 'true' taken 66 times.
|
66 | case OpType::CX: | |
234 | 66 | conjugate_PauliTensor( | ||
235 |
3/6✓ Branch 3 taken 66 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 66 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 66 times.
✗ Branch 10 not taken.
|
66 | qpt, cycle_op.type, Qubit("frame", cycle_op.indices[0]), | |
236 |
2/4✓ Branch 3 taken 66 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 66 times.
✗ Branch 7 not taken.
|
132 | Qubit("frame", cycle_op.indices[1])); | |
237 | 66 | break; | ||
238 |
0/1✗ Decision 'true' not taken.
|
✗ | default: { | |
239 | ✗ | throw FrameRandomisationError(std::string( | ||
240 | ✗ | "Cycle OpType " + OpDesc(cycle_op.type).name() + | ||
241 | ✗ | " not supported for PauliFrameRandomisation.")); | ||
242 | } | |||
243 | } | |||
244 | } | |||
245 | ||||
246 |
1/2✓ Branch 3 taken 36 times.
✗ Branch 4 not taken.
|
36 | OpTypeVector out_frame(in_frame.size()); | |
247 |
2/2✓ Branch 5 taken 92 times.
✓ Branch 6 taken 36 times.
|
2/2✓ Decision 'true' taken 92 times.
✓ Decision 'false' taken 36 times.
|
128 | for (const auto& entry : qpt.string.map) { |
248 |
4/5✓ Branch 0 taken 26 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
|
92 | switch (entry.second) { | |
249 |
1/1✓ Decision 'true' taken 26 times.
|
26 | case Pauli::I: | |
250 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | out_frame[entry.first.index()[0]] = OpType::noop; | |
251 | 26 | break; | ||
252 |
1/1✓ Decision 'true' taken 20 times.
|
20 | case Pauli::X: | |
253 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | out_frame[entry.first.index()[0]] = OpType::X; | |
254 | 20 | break; | ||
255 |
1/1✓ Decision 'true' taken 20 times.
|
20 | case Pauli::Y: | |
256 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | out_frame[entry.first.index()[0]] = OpType::Y; | |
257 | 20 | break; | ||
258 |
1/1✓ Decision 'true' taken 26 times.
|
26 | case Pauli::Z: | |
259 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | out_frame[entry.first.index()[0]] = OpType::Z; | |
260 | 26 | break; | ||
261 | } | |||
262 | } | |||
263 |
1/2✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
|
72 | return {out_frame, {}}; | |
264 | 36 | } | ||
265 | ||||
266 | std::pair<OpTypeVector, std::vector<Vertex>> | |||
267 | 544 | UniversalFrameRandomisation::get_out_frame( | ||
268 | const OpTypeVector& in_frame, const Cycle& cycle) { | |||
269 | 544 | QubitPauliMap qpm; | ||
270 | 544 | std::vector<Vertex> to_dagger; | ||
271 |
2/2✓ Branch 1 taken 1088 times.
✓ Branch 2 taken 544 times.
|
2/2✓ Decision 'true' taken 1088 times.
✓ Decision 'false' taken 544 times.
|
1632 | for (unsigned i = 0; i < in_frame.size(); i++) { |
272 |
4/5✓ Branch 1 taken 272 times.
✓ Branch 2 taken 272 times.
✓ Branch 3 taken 272 times.
✓ Branch 4 taken 272 times.
✗ Branch 5 not taken.
|
1088 | switch (in_frame[i]) { | |
273 |
1/1✓ Decision 'true' taken 272 times.
|
272 | case OpType::noop: | |
274 |
3/6✓ Branch 2 taken 272 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 272 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 272 times.
✗ Branch 9 not taken.
|
272 | qpm[Qubit("frame", i)] = Pauli::I; | |
275 | 272 | break; | ||
276 |
1/1✓ Decision 'true' taken 272 times.
|
272 | case OpType::X: | |
277 |
3/6✓ Branch 2 taken 272 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 272 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 272 times.
✗ Branch 9 not taken.
|
272 | qpm[Qubit("frame", i)] = Pauli::X; | |
278 | 272 | break; | ||
279 |
1/1✓ Decision 'true' taken 272 times.
|
272 | case OpType::Y: | |
280 |
3/6✓ Branch 2 taken 272 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 272 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 272 times.
✗ Branch 9 not taken.
|
272 | qpm[Qubit("frame", i)] = Pauli::Y; | |
281 | 272 | break; | ||
282 |
1/1✓ Decision 'true' taken 272 times.
|
272 | case OpType::Z: | |
283 |
3/6✓ Branch 2 taken 272 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 272 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 272 times.
✗ Branch 9 not taken.
|
272 | qpm[Qubit("frame", i)] = Pauli::Z; | |
284 | 272 | break; | ||
285 |
0/1✗ Decision 'true' not taken.
|
✗ | default: { | |
286 | ✗ | throw FrameRandomisationError(std::string( | ||
287 | ✗ | "Frame OpType " + OpDesc(in_frame[i]).name() + | ||
288 | ✗ | " not a Pauli OpType.")); | ||
289 | } | |||
290 | } | |||
291 | } | |||
292 | ||||
293 |
1/2✓ Branch 1 taken 544 times.
✗ Branch 2 not taken.
|
1088 | QubitPauliTensor qpt(qpm); | |
294 | ||||
295 |
2/2✓ Branch 5 taken 1232 times.
✓ Branch 6 taken 544 times.
|
2/2✓ Decision 'true' taken 1232 times.
✓ Decision 'false' taken 544 times.
|
1776 | for (const CycleCom& cycle_op : cycle.coms_) { |
296 |
2/2✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1168 times.
|
2/2✓ Decision 'true' taken 64 times.
✓ Decision 'false' taken 1168 times.
|
1232 | if (cycle_op.type == OpType::Rz) { |
297 |
3/6✓ Branch 3 taken 64 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 64 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 64 times.
✗ Branch 10 not taken.
|
64 | Pauli frame_type = qpt.string.map[Qubit("frame", cycle_op.indices[0])]; | |
298 |
4/4✓ Branch 0 taken 48 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 32 times.
|
2/2✓ Decision 'true' taken 32 times.
✓ Decision 'false' taken 32 times.
|
64 | if (frame_type == Pauli::X || frame_type == Pauli::Y) { |
299 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | to_dagger.push_back(cycle_op.address); | |
300 | } | |||
301 | // don't conjugate Pauli Tensor as no frame changes for Rz | |||
302 | } | |||
303 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1200 times.
|
2/2✓ Decision 'true' taken 32 times.
✓ Decision 'false' taken 1200 times.
|
1232 | if (cycle_op.type == OpType::H) { |
304 | 32 | conjugate_PauliTensor( | ||
305 |
3/6✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 32 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 32 times.
✗ Branch 10 not taken.
|
32 | qpt, cycle_op.type, Qubit("frame", cycle_op.indices[0]), false); | |
306 | } | |||
307 |
2/2✓ Branch 0 taken 560 times.
✓ Branch 1 taken 672 times.
|
2/2✓ Decision 'true' taken 560 times.
✓ Decision 'false' taken 672 times.
|
1232 | if (cycle_op.type == OpType::CX) { |
308 | 560 | conjugate_PauliTensor( | ||
309 |
3/6✓ Branch 3 taken 560 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 560 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 560 times.
✗ Branch 10 not taken.
|
560 | qpt, cycle_op.type, Qubit("frame", cycle_op.indices[0]), | |
310 |
2/4✓ Branch 3 taken 560 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 560 times.
✗ Branch 7 not taken.
|
1120 | Qubit("frame", cycle_op.indices[1])); | |
311 | } | |||
312 | } | |||
313 | ||||
314 |
1/2✓ Branch 3 taken 544 times.
✗ Branch 4 not taken.
|
1088 | OpTypeVector out_frame(in_frame.size()); | |
315 |
2/2✓ Branch 5 taken 1088 times.
✓ Branch 6 taken 544 times.
|
2/2✓ Decision 'true' taken 1088 times.
✓ Decision 'false' taken 544 times.
|
1632 | for (const auto& entry : qpt.string.map) { |
316 |
4/5✓ Branch 0 taken 272 times.
✓ Branch 1 taken 272 times.
✓ Branch 2 taken 272 times.
✓ Branch 3 taken 272 times.
✗ Branch 4 not taken.
|
1088 | switch (entry.second) { | |
317 |
1/1✓ Decision 'true' taken 272 times.
|
272 | case Pauli::I: | |
318 |
1/2✓ Branch 1 taken 272 times.
✗ Branch 2 not taken.
|
272 | out_frame[entry.first.index()[0]] = OpType::noop; | |
319 | 272 | break; | ||
320 |
1/1✓ Decision 'true' taken 272 times.
|
272 | case Pauli::X: | |
321 |
1/2✓ Branch 1 taken 272 times.
✗ Branch 2 not taken.
|
272 | out_frame[entry.first.index()[0]] = OpType::X; | |
322 | 272 | break; | ||
323 |
1/1✓ Decision 'true' taken 272 times.
|
272 | case Pauli::Y: | |
324 |
1/2✓ Branch 1 taken 272 times.
✗ Branch 2 not taken.
|
272 | out_frame[entry.first.index()[0]] = OpType::Y; | |
325 | 272 | break; | ||
326 |
1/1✓ Decision 'true' taken 272 times.
|
272 | case Pauli::Z: | |
327 |
1/2✓ Branch 1 taken 272 times.
✗ Branch 2 not taken.
|
272 | out_frame[entry.first.index()[0]] = OpType::Z; | |
328 | 272 | break; | ||
329 | } | |||
330 | } | |||
331 |
1/2✓ Branch 1 taken 544 times.
✗ Branch 2 not taken.
|
1088 | return {out_frame, to_dagger}; | |
332 | 544 | } | ||
333 | ||||
334 | 7 | std::vector<Circuit> FrameRandomisation::label_frames( | ||
335 | const std::vector<std::vector<OpTypeVector>>& all_frame_ops, | |||
336 | const std::vector<Cycle>& cycles) { | |||
337 | 7 | std::vector<Circuit> output_circuit_list; | ||
338 | // make instances of all circuits using | |||
339 |
2/2✓ Branch 5 taken 374 times.
✓ Branch 6 taken 7 times.
|
2/2✓ Decision 'true' taken 374 times.
✓ Decision 'false' taken 7 times.
|
381 | for (const std::vector<OpTypeVector>& cycle_frames : all_frame_ops) { |
340 | 374 | std::vector<Vertex> dagger_vertices; | ||
341 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 374 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 374 times.
|
374 | if (cycle_frames.size() != cycles.size()) { |
342 | ✗ | throw FrameRandomisationError( | ||
343 | ✗ | std::string("Length of combination of Frame Permutations does not " | ||
344 | ✗ | "equal number of Cycles.")); | ||
345 | } | |||
346 |
2/2✓ Branch 1 taken 758 times.
✓ Branch 2 taken 374 times.
|
2/2✓ Decision 'true' taken 758 times.
✓ Decision 'false' taken 374 times.
|
1132 | for (unsigned i = 0; i < cycle_frames.size(); i++) { |
347 |
2/4✓ Branch 4 taken 758 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 758 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 758 times.
|
758 | if (cycle_frames[i].size() != cycles[i].size()) { |
348 | ✗ | throw FrameRandomisationError( | ||
349 | ✗ | std::string("Size of frame does not match the number " | ||
350 | ✗ | "of qubits in Cycles.")); | ||
351 | } | |||
352 |
1/2✓ Branch 2 taken 758 times.
✗ Branch 3 not taken.
|
758 | OpTypeVector in_frame = cycle_frames[i]; | |
353 | std::pair<OpTypeVector, std::vector<Vertex>> frame_and_vertices = | |||
354 |
1/2✓ Branch 2 taken 758 times.
✗ Branch 3 not taken.
|
758 | get_out_frame(in_frame, cycles[i]); | |
355 |
1/2✓ Branch 4 taken 758 times.
✗ Branch 5 not taken.
|
1516 | dagger_vertices.insert( | |
356 | 758 | dagger_vertices.end(), frame_and_vertices.second.begin(), | ||
357 | frame_and_vertices.second.end()); | |||
358 |
1/2✓ Branch 1 taken 758 times.
✗ Branch 2 not taken.
|
758 | assign_vertices( | |
359 |
1/2✓ Branch 2 taken 758 times.
✗ Branch 3 not taken.
|
1516 | in_frame, frame_and_vertices.first, cycles[i].get_frame()); | |
360 | 758 | } | ||
361 | ||||
362 |
2/2✓ Branch 4 taken 32 times.
✓ Branch 5 taken 374 times.
|
2/2✓ Decision 'true' taken 32 times.
✓ Decision 'false' taken 374 times.
|
406 | for (const Vertex& v : dagger_vertices) { |
363 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | circuit_.set_vertex_Op_ptr( | |
364 |
2/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
|
64 | v, circuit_.get_Op_ptr_from_Vertex(v)->dagger()); | |
365 | } | |||
366 |
2/4✓ Branch 1 taken 374 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 374 times.
✗ Branch 5 not taken.
|
374 | output_circuit_list.push_back(Circuit(circuit_)); | |
367 | ||||
368 |
2/2✓ Branch 4 taken 32 times.
✓ Branch 5 taken 374 times.
|
2/2✓ Decision 'true' taken 32 times.
✓ Decision 'false' taken 374 times.
|
406 | for (const Vertex& v : dagger_vertices) { |
369 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | circuit_.set_vertex_Op_ptr( | |
370 |
2/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
|
64 | v, circuit_.get_Op_ptr_from_Vertex(v)->dagger()); | |
371 | } | |||
372 | 374 | } | ||
373 | 7 | return output_circuit_list; | ||
374 | } | |||
375 | ||||
376 | 15 | std::pair<std::vector<unsigned>, unsigned> get_frame_sizes( | ||
377 | const std::vector<Cycle>& cycles) { | |||
378 | 15 | unsigned max_frame_size = 0; | ||
379 | 15 | std::vector<unsigned> frame_sizes; | ||
380 |
2/2✓ Branch 5 taken 18 times.
✓ Branch 6 taken 15 times.
|
2/2✓ Decision 'true' taken 18 times.
✓ Decision 'false' taken 15 times.
|
33 | for (const Cycle& cycle : cycles) { |
381 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | unsigned frame_size = cycle.size(); | |
382 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | frame_sizes.push_back(frame_size); | |
383 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 3 times.
|
2/2✓ Decision 'true' taken 15 times.
✓ Decision 'false' taken 3 times.
|
18 | if (frame_size > max_frame_size) { |
384 | 15 | max_frame_size = frame_size; | ||
385 | } | |||
386 | } | |||
387 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
30 | return {frame_sizes, max_frame_size}; | |
388 | 15 | } | ||
389 | ||||
390 | 6 | std::vector<Circuit> FrameRandomisation::get_all_circuits(const Circuit& circ) { | ||
391 | // Get all cycle boundaries | |||
392 | // Get all sizes | |||
393 | // Get all possible frames for all possible cycles | |||
394 | // Apply every permutation of frames to cycles | |||
395 | // Return as vector | |||
396 | // get all cycles in circuit, wire noop vertices for relabelling into | |||
397 | // boundaries | |||
398 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | this->circuit_ = circ; | |
399 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | std::vector<Cycle> all_cycles = get_cycles(circuit_); | |
400 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 6 times.
|
6 | if (all_cycles.size() == 0) { |
401 | ✗ | throw FrameRandomisationError( | ||
402 | ✗ | std::string("Circuit has no gates with OpType in Cycle OpTypes.")); | ||
403 | } | |||
404 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | add_noop_frames(all_cycles, circuit_); | |
405 | std::pair<std::vector<unsigned>, unsigned> frame_sizes = | |||
406 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | get_frame_sizes(all_cycles); | |
407 | ||||
408 | // work out all possible permutations of given ops for all frame sizes | |||
409 | std::vector<std::vector<OpTypeVector>> all_frame_perms = | |||
410 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | get_all_frame_permutations(frame_sizes.second, frame_types_); | |
411 | // combine all these permutations | |||
412 | std::vector<std::vector<OpTypeVector>> all_permutation_combinations = | |||
413 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | get_all_permutation_combinations(frame_sizes.first, all_frame_perms); | |
414 | std::vector<Circuit> output_circuit_list = | |||
415 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | label_frames(all_permutation_combinations, all_cycles); | |
416 | 12 | return output_circuit_list; | ||
417 | 6 | } | ||
418 | 10 | OpTypeVector FrameRandomisation::sample_frame(const unsigned& size) const { | ||
419 | 10 | OpTypeVector frame; | ||
420 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 10 times.
|
2/2✓ Decision 'true' taken 28 times.
✓ Decision 'false' taken 10 times.
|
38 | for (unsigned i = 0; i < size; i++) |
421 |
2/4✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 28 times.
✗ Branch 7 not taken.
|
28 | std::sample( | |
422 | frame_types_.begin(), frame_types_.end(), std::back_inserter(frame), 1, | |||
423 |
3/6✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 28 times.
✗ Branch 8 not taken.
|
56 | std::mt19937{std::random_device{}()}); | |
424 | 10 | return frame; | ||
425 | } | |||
426 | ||||
427 | 9 | std::vector<std::vector<OpTypeVector>> FrameRandomisation::get_all_samples( | ||
428 | const unsigned& samples, const std::vector<unsigned>& frame_sizes) const { | |||
429 | 9 | std::vector<std::vector<OpTypeVector>> output_frames; | ||
430 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
|
2/2✓ Decision 'true' taken 10 times.
✓ Decision 'false' taken 9 times.
|
19 | for (unsigned i = 0; i < samples; i++) { |
431 | 10 | std::vector<OpTypeVector> single_sample; | ||
432 |
2/2✓ Branch 4 taken 10 times.
✓ Branch 5 taken 10 times.
|
2/2✓ Decision 'true' taken 10 times.
✓ Decision 'false' taken 10 times.
|
20 | for (const unsigned& size : frame_sizes) |
433 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | single_sample.push_back(sample_frame(size)); | |
434 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | output_frames.push_back(single_sample); | |
435 | 10 | } | ||
436 | 9 | return output_frames; | ||
437 | } | |||
438 | ||||
439 | 778 | void FrameRandomisation::assign_vertices( | ||
440 | const OpTypeVector& in_frame, const OpTypeVector& out_frame, | |||
441 | const std::vector<std::pair<Vertex, Vertex>>& frame_vertices) { | |||
442 |
3/6✓ Branch 2 taken 778 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 778 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 778 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1556 times.
|
1556 | if (in_frame.size() != out_frame.size() || |
443 | 778 | in_frame.size() != frame_vertices.size()) { | ||
444 | ✗ | throw FrameRandomisationError( | ||
445 | ✗ | std::string("Number of gates in sampled frame doesn't match " | ||
446 | ✗ | "number of qubits in frame")); | ||
447 | } | |||
448 |
2/2✓ Branch 1 taken 1576 times.
✓ Branch 2 taken 778 times.
|
2/2✓ Decision 'true' taken 1576 times.
✓ Decision 'false' taken 778 times.
|
2354 | for (unsigned i = 0; i < frame_vertices.size(); i++) { |
449 | 3152 | circuit_.set_vertex_Op_ptr( | ||
450 |
2/4✓ Branch 3 taken 1576 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1576 times.
✗ Branch 8 not taken.
|
1576 | frame_vertices[i].first, get_op_ptr(in_frame[i])); | |
451 | 3152 | circuit_.set_vertex_Op_ptr( | ||
452 |
2/4✓ Branch 3 taken 1576 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1576 times.
✗ Branch 8 not taken.
|
1576 | frame_vertices[i].second, get_op_ptr(out_frame[i])); | |
453 | } | |||
454 | 778 | } | ||
455 | ||||
456 | 1 | std::vector<Circuit> FrameRandomisation::sample_randomisation_circuits( | ||
457 | const Circuit& circ, unsigned samples) { | |||
458 | // get all cycles in circuit, wire noop vertices for relabelling into | |||
459 | // boundaries | |||
460 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | this->circuit_ = circ; | |
461 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::vector<Cycle> all_cycles = get_cycles(circuit_); | |
462 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1 times.
|
1 | if (all_cycles.size() == 0) { |
463 | ✗ | throw FrameRandomisationError( | ||
464 | ✗ | std::string("Circuit has no gates with OpType in Cycle OpTypes.")); | ||
465 | } | |||
466 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | add_noop_frames(all_cycles, circuit_); | |
467 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::vector<unsigned> frame_sizes = get_frame_sizes(all_cycles).first; | |
468 | std::vector<std::vector<OpTypeVector>> all_samples = | |||
469 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | get_all_samples(samples, frame_sizes); | |
470 | std::vector<Circuit> output_circuit_list = | |||
471 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | label_frames(all_samples, all_cycles); | |
472 | 2 | return output_circuit_list; | ||
473 | 1 | } | ||
474 | ||||
475 | 19 | std::vector<Cycle> FrameRandomisation::get_cycles(const Circuit& circ) const { | ||
476 |
1/2✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
|
19 | CycleFinder cf(circ, this->cycle_types_); | |
477 |
1/2✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
|
38 | return cf.get_cycles(); | |
478 | 19 | } | ||
479 | ||||
480 | 8 | std::vector<Circuit> PowerCycle::sample_cycles( | ||
481 | const Circuit& circ, unsigned total_cycles, unsigned samples) { | |||
482 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | this->circuit_ = circ; | |
483 | 8 | std::vector<Circuit> out; | ||
484 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | std::vector<Cycle> all_cycles = get_cycles(circuit_); | |
485 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 8 times.
|
8 | if (all_cycles.size() == 0) { |
486 | ✗ | throw FrameRandomisationError( | ||
487 | ✗ | std::string("Circuit has no gates with OpType in Clifford gates.")); | ||
488 | } | |||
489 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 8 times.
|
8 | if (all_cycles.size() > 1) { |
490 | ✗ | throw FrameRandomisationError( | ||
491 | ✗ | std::string("Circuit has non-Clifford gates.")); | ||
492 | } | |||
493 | ||||
494 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | add_noop_frames(all_cycles, circuit_); | |
495 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | std::vector<unsigned> frame_sizes = get_frame_sizes(all_cycles).first; | |
496 | std::vector<std::vector<OpTypeVector>> all_samples = | |||
497 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | get_all_samples(samples, frame_sizes); | |
498 |
2/2✓ Branch 5 taken 8 times.
✓ Branch 6 taken 8 times.
|
2/2✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 8 times.
|
16 | for (const std::vector<OpTypeVector>& sample : all_samples) { |
499 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 8 times.
|
8 | if (sample.size() > 1) { |
500 | ✗ | throw FrameRandomisationError( | ||
501 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | std::string("Frames have been sampled for more than one cycle.")); | |
502 | } | |||
503 |
1/2✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | OpTypeVector in_frame = sample[0]; | |
504 | 8 | OpTypeVector noop_frame; | ||
505 |
2/2✓ Branch 1 taken 24 times.
✓ Branch 2 taken 8 times.
|
2/2✓ Decision 'true' taken 24 times.
✓ Decision 'false' taken 8 times.
|
32 | for (unsigned i = 0; i < in_frame.size(); i++) { |
506 |
1/2✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
|
24 | noop_frame.push_back(OpType::noop); | |
507 | } | |||
508 | std::pair<OpTypeVector, std::vector<Vertex>> frame_and_vertices = | |||
509 |
1/2✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | get_out_frame(in_frame, all_cycles[0]); | |
510 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | assign_vertices( | |
511 |
1/2✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
16 | in_frame, frame_and_vertices.first, all_cycles[0].get_frame()); | |
512 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | Circuit full_circ = circuit_; | |
513 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 8 times.
|
2/2✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 8 times.
|
20 | for (unsigned i = 0; i < total_cycles - 1; i++) { |
514 | frame_and_vertices = | |||
515 |
1/2✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 | get_out_frame(frame_and_vertices.first, all_cycles[0]); | |
516 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | assign_vertices( | |
517 |
1/2✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
24 | noop_frame, frame_and_vertices.first, all_cycles[0].get_frame()); | |
518 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | full_circ.append(circuit_); | |
519 | } | |||
520 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | out.push_back(full_circ); | |
521 | 8 | } | ||
522 | 16 | return out; | ||
523 | 8 | } | ||
524 | ||||
525 | } // namespace tket | |||
526 |