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 "Circuit.hpp" | |||
16 | ||||
17 | #include <fstream> | |||
18 | #include <numeric> | |||
19 | #include <optional> | |||
20 | #include <set> | |||
21 | #include <string> | |||
22 | #include <tklog/TketLog.hpp> | |||
23 | #include <utility> | |||
24 | ||||
25 | #include "Utils/Expression.hpp" | |||
26 | #include "Utils/GraphHeaders.hpp" | |||
27 | #include "Utils/HelperFunctions.hpp" | |||
28 | ||||
29 | namespace tket { | |||
30 | ||||
31 | //////////////////////////// | |||
32 | // Public Circuit Methods // | |||
33 | //////////////////////////// | |||
34 | ||||
35 | // Out stream of graphviz code describing the circuit from Top-Bottom, | |||
36 | // information apart from qubit path and slices can be seen easily. | |||
37 | // Very useful for debugging and eyeball comparison of circuits. | |||
38 | // out << "\nrankdir=\"LR\"" <--- put this in for Left-Right circuit | |||
39 | 1 | void Circuit::to_graphviz(std::ostream &out) const { | ||
40 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | IndexMap im = index_map(); | |
41 | ||||
42 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out << "digraph G {\n"; | |
43 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out << "{ rank = same\n"; | |
44 |
3/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
|
0/1? Decision couldn't be analyzed.
|
3 | for (const Vertex &v : all_inputs()) { |
45 |
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 | out << im[v] << " "; | |
46 | 1 | } | ||
47 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out << "}\n"; | |
48 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out << "{ rank = same\n"; | |
49 |
3/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
|
0/1? Decision couldn't be analyzed.
|
3 | for (const Vertex &v : all_outputs()) { |
50 |
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 | out << im[v] << " "; | |
51 | 1 | } | ||
52 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out << "}\n"; | |
53 | ||||
54 |
7/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
|
7 | BGL_FORALL_VERTICES(v, dag, DAG) { | |
55 |
3/6✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
|
15 | out << im[v] << " [label = \"" << get_Op_ptr_from_Vertex(v)->get_name() | |
56 |
7/14✓ 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.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 5 times.
✗ Branch 20 not taken.
|
10 | << ", " << im[v] << "\"];\n"; | |
57 | } | |||
58 |
12/18✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✓ Branch 13 taken 1 times.
✓ Branch 15 taken 4 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 4 times.
✓ Branch 18 taken 1 times.
✓ Branch 20 taken 2 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✓ Branch 23 taken 1 times.
|
6 | BGL_FORALL_EDGES(e, dag, DAG) { | |
59 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | Vertex v_so = source(e); | |
60 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | Vertex v_ta = target(e); | |
61 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | unsigned v_s = im[v_so]; | |
62 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | unsigned v_t = im[v_ta]; | |
63 |
7/14✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 4 times.
✗ Branch 20 not taken.
|
4 | out << v_s << " -> " << v_t << " [label = \"" << get_source_port(e) << ", " | |
64 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
4 | << get_target_port(e) << "\"];\n"; | |
65 | } | |||
66 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out << "}"; | |
67 | 1 | } | ||
68 | ||||
69 | ✗ | void Circuit::to_graphviz_file(const std::string &filename) const { | ||
70 | ✗ | std::ofstream dot_file(filename); | ||
71 | ✗ | to_graphviz(dot_file); | ||
72 | } | |||
73 | ||||
74 | 1 | std::string Circuit::to_graphviz_str() const { | ||
75 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::stringstream dot_string; | |
76 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | to_graphviz(dot_string); | |
77 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | return dot_string.str(); | |
78 | 1 | } | ||
79 | ||||
80 | 1 | void Circuit::extract_slice_segment(unsigned slice_one, unsigned slice_two) { | ||
81 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | SliceVec slices = get_slices(); | |
82 | 1 | VertexList bin; | ||
83 |
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 | for (unsigned i = 0; i < slice_one - 1; ++i) { |
84 |
2/2✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 1 times.
|
2 | for (Vertex it : slices[i]) { |
85 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | bin.push_back(it); | |
86 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | remove_vertex(it, GraphRewiring::Yes, VertexDeletion::No); | |
87 | } | |||
88 | } | |||
89 |
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 | for (unsigned i = slice_two; i < slices.size(); ++i) { |
90 |
2/2✓ Branch 6 taken 2 times.
✓ Branch 7 taken 2 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 2 times.
|
4 | for (Vertex it : slices[i]) { |
91 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | bin.push_back(it); | |
92 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | remove_vertex(it, GraphRewiring::Yes, VertexDeletion::No); | |
93 | } | |||
94 | } | |||
95 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | remove_vertices(bin, GraphRewiring::No, VertexDeletion::Yes); | |
96 | 1 | } | ||
97 | ||||
98 | 250 | std::vector<Command> Circuit::get_commands() const { | ||
99 | 250 | std::vector<Command> coms; | ||
100 |
4/6✓ Branch 1 taken 250 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1485 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1235 times.
✓ Branch 9 taken 250 times.
|
0/1? Decision couldn't be analyzed.
|
1485 | for (CommandIterator it = begin(); it != end(); ++it) { |
101 |
3/6✓ Branch 1 taken 1235 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1235 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1235 times.
✗ Branch 9 not taken.
|
1235 | coms.push_back(*it); | |
102 | 250 | } | ||
103 | 250 | return coms; | ||
104 | } | |||
105 | ||||
106 | 446 | void Circuit::index_vertices() /*const*/ { | ||
107 |
1/2✓ Branch 1 taken 446 times.
✗ Branch 2 not taken.
|
446 | VIndex index = boost::get(boost::vertex_index, dag); | |
108 | 446 | int i = 0; | ||
109 |
8/10✓ Branch 1 taken 446 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19796 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 19796 times.
✓ Branch 9 taken 446 times.
✓ Branch 11 taken 19796 times.
✓ Branch 12 taken 446 times.
✓ Branch 14 taken 446 times.
✓ Branch 15 taken 446 times.
|
20688 | BGL_FORALL_VERTICES(v, dag, DAG) { boost::put(index, v, i++); } | |
110 | 446 | } | ||
111 | ||||
112 | 446 | VertexVec Circuit::vertices_in_order() /*const*/ { | ||
113 | 446 | index_vertices(); | ||
114 | 446 | VertexVec vertices; | ||
115 |
2/4✓ Branch 1 taken 446 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 446 times.
✗ Branch 5 not taken.
|
446 | boost::topological_sort(dag, std::back_inserter(vertices)); | |
116 |
1/2✓ Branch 3 taken 446 times.
✗ Branch 4 not taken.
|
446 | std::reverse(vertices.begin(), vertices.end()); | |
117 | 446 | return vertices; | ||
118 | } | |||
119 | ||||
120 | 41291 | IndexMap Circuit::index_map() const { | ||
121 | 41291 | IndexMap im; | ||
122 | 41291 | unsigned i = 0; | ||
123 |
8/10✓ Branch 1 taken 41291 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 565596 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 565596 times.
✓ Branch 9 taken 41291 times.
✓ Branch 11 taken 565596 times.
✓ Branch 12 taken 41291 times.
✓ Branch 14 taken 41291 times.
✓ Branch 15 taken 41291 times.
|
648178 | BGL_FORALL_VERTICES(v, dag, DAG) { im[v] = i++; } | |
124 | 41291 | return im; | ||
125 | } | |||
126 | ||||
127 | 498106 | Expr Circuit::get_phase() const { | ||
128 |
1/2✓ Branch 1 taken 498106 times.
✗ Branch 2 not taken.
|
498106 | std::optional<double> x = eval_expr_mod(phase); | |
129 |
2/2✓ Branch 1 taken 498100 times.
✓ Branch 2 taken 6 times.
|
2/2✓ Decision 'true' taken 498100 times.
✓ Decision 'false' taken 6 times.
|
498106 | if (x) { |
130 |
2/4✓ Branch 1 taken 498100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 498100 times.
✗ Branch 5 not taken.
|
498100 | return x.value(); | |
131 | } else | |||
132 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | return phase; | |
133 | } | |||
134 | ||||
135 | 391248 | void Circuit::add_phase(Expr a) { phase += a; } | ||
136 | ||||
137 | 222 | void Circuit::symbol_substitution(const symbol_map_t &symbol_map) { | ||
138 | 222 | SymEngine::map_basic_basic sub_map; | ||
139 |
2/2✓ Branch 5 taken 330 times.
✓ Branch 6 taken 222 times.
|
2/2✓ Decision 'true' taken 330 times.
✓ Decision 'false' taken 222 times.
|
552 | for (const std::pair<const Sym, Expr> &p : symbol_map) { |
140 |
1/2✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
|
330 | ExprPtr s = p.first; | |
141 |
1/2✓ Branch 2 taken 330 times.
✗ Branch 3 not taken.
|
330 | ExprPtr e = p.second; | |
142 | // This is a workaround for a symengine issue: symengine currently has poor | |||
143 | // handling of symbolic evaluations for atan2. However, this may not catch | |||
144 | // every such issue, so we should revisit it. | |||
145 |
4/6✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 330 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✓ Branch 8 taken 321 times.
|
2/2✓ Decision 'true' taken 9 times.
✓ Decision 'false' taken 321 times.
|
330 | if (approx_0(e)) { |
146 |
3/6✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
|
9 | sub_map[s] = SymEngine::zero; | |
147 | } else { | |||
148 |
2/4✓ Branch 1 taken 321 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 321 times.
✗ Branch 5 not taken.
|
321 | sub_map[s] = e; | |
149 | } | |||
150 | 330 | } | ||
151 |
2/4✓ Branch 1 taken 222 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 222 times.
✗ Branch 5 not taken.
|
222 | symbol_substitution(sub_map); | |
152 | 222 | } | ||
153 | ||||
154 | 15 | void Circuit::symbol_substitution( | ||
155 | const std::map<Sym, double, SymEngine::RCPBasicKeyLess> &symbol_map) { | |||
156 | 15 | symbol_map_t s_map; | ||
157 |
3/4✓ Branch 4 taken 65 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 65 times.
✓ Branch 9 taken 15 times.
|
0/1? Decision couldn't be analyzed.
|
80 | for (std::pair<Sym, Expr> p : symbol_map) { |
158 |
2/4✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 65 times.
✗ Branch 5 not taken.
|
65 | s_map[p.first] = Expr(p.second); | |
159 | 65 | } | ||
160 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | symbol_substitution(s_map); | |
161 | 15 | } | ||
162 | ||||
163 | 222 | void Circuit::symbol_substitution(const SymEngine::map_basic_basic sub_map) { | ||
164 |
7/8✓ Branch 1 taken 222 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3300 times.
✓ Branch 6 taken 222 times.
✓ Branch 8 taken 3300 times.
✓ Branch 9 taken 222 times.
✓ Branch 11 taken 222 times.
✓ Branch 12 taken 222 times.
|
3744 | BGL_FORALL_VERTICES(v, dag, DAG) { | |
165 |
2/4✓ Branch 1 taken 3300 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3300 times.
✗ Branch 6 not taken.
|
3300 | Op_ptr new_op = get_Op_ptr_from_Vertex(v)->symbol_substitution(sub_map); | |
166 |
2/2✓ Branch 1 taken 2400 times.
✓ Branch 2 taken 900 times.
|
2/2✓ Decision 'true' taken 2400 times.
✓ Decision 'false' taken 900 times.
|
3300 | if (new_op) { |
167 |
2/4✓ Branch 3 taken 2400 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2400 times.
✗ Branch 7 not taken.
|
2400 | dag[v] = {new_op}; | |
168 | } | |||
169 | 3300 | } | ||
170 | 222 | phase = phase.subs(sub_map); | ||
171 | 222 | } | ||
172 | ||||
173 | 95 | const SymSet Circuit::free_symbols() const { | ||
174 | 95 | SymSet symbols; | ||
175 |
7/8✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 906 times.
✓ Branch 6 taken 95 times.
✓ Branch 8 taken 906 times.
✓ Branch 9 taken 95 times.
✓ Branch 11 taken 95 times.
✓ Branch 12 taken 95 times.
|
1096 | BGL_FORALL_VERTICES(v, dag, DAG) { | |
176 |
2/4✓ Branch 1 taken 906 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 906 times.
✗ Branch 6 not taken.
|
906 | const SymSet s = get_Op_ptr_from_Vertex(v)->free_symbols(); | |
177 |
1/2✓ Branch 3 taken 906 times.
✗ Branch 4 not taken.
|
906 | symbols.insert(s.begin(), s.end()); | |
178 | 906 | } | ||
179 |
1/2✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
|
95 | SymSet phase_s = expr_free_symbols(phase); | |
180 |
1/2✓ Branch 3 taken 95 times.
✗ Branch 4 not taken.
|
95 | symbols.insert(phase_s.begin(), phase_s.end()); | |
181 | 190 | return symbols; | ||
182 | 95 | } | ||
183 | ||||
184 | 38 | bool Circuit::is_symbolic() const { return !free_symbols().empty(); } | ||
185 | ||||
186 | // check aspects of circuit for equality, and optionally throw exceptions when | |||
187 | // not met | |||
188 | 158 | bool Circuit::circuit_equality( | ||
189 | const Circuit &other, const std::set<Check> &except, | |||
190 | bool throw_error) const { | |||
191 | 158 | bool check = true; | ||
192 | 158 | check &= check_iterators_equality(*this, other); | ||
193 |
3/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 145 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 158 times.
|
158 | if (throw_error && !check) { |
194 | ✗ | throw CircuitInequality(std::string("Circuit operations do not match.")); | ||
195 | } | |||
196 | ||||
197 |
2/4✓ Branch 1 taken 158 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 158 times.
✗ Branch 4 not taken.
|
1/2✓ Decision 'true' taken 158 times.
✗ Decision 'false' not taken.
|
158 | if (except.count(Check::Phase) == 0) { |
198 |
1/2✓ Branch 1 taken 158 times.
✗ Branch 2 not taken.
|
158 | const Expr thisphase = this->get_phase(); | |
199 |
1/2✓ Branch 1 taken 158 times.
✗ Branch 2 not taken.
|
158 | const Expr othephase = other.get_phase(); | |
200 |
1/2✓ Branch 1 taken 158 times.
✗ Branch 2 not taken.
|
158 | check &= equiv_expr(thisphase, othephase); | |
201 |
4/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 157 times.
|
158 | if (throw_error && !check) { |
202 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | throw CircuitInequality( | |
203 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2 | std::string("Circuit phases do not match: ") + | |
204 |
4/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
|
4 | ExprPtr(thisphase)->__str__() + | |
205 |
4/8✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
|
4 | " != " + ExprPtr(othephase)->__str__()); | |
206 | } | |||
207 | 159 | } | ||
208 |
2/4✓ Branch 1 taken 157 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 157 times.
✗ Branch 4 not taken.
|
1/2✓ Decision 'true' taken 157 times.
✗ Decision 'false' not taken.
|
157 | if (except.count(Check::Units) == 0) { |
209 |
2/4✓ Branch 2 taken 157 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 157 times.
✗ Branch 6 not taken.
|
157 | check &= (this->all_qubits() == other.all_qubits()); | |
210 |
4/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 11 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 156 times.
|
157 | if (throw_error && !check) { |
211 |
2/4✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
1 | throw CircuitInequality(std::string("Circuit qubits do not match.")); | |
212 | } | |||
213 | ||||
214 |
2/4✓ Branch 2 taken 156 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 156 times.
✗ Branch 6 not taken.
|
156 | check &= (this->all_bits() == other.all_bits()); | |
215 |
4/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 10 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 155 times.
|
156 | if (throw_error && !check) { |
216 |
2/4✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
1 | throw CircuitInequality(std::string("Circuit bits do not match.")); | |
217 | } | |||
218 |
2/4✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 155 times.
✗ Branch 6 not taken.
|
155 | check &= (this->created_qubits() == other.created_qubits()); | |
219 |
4/4✓ Branch 0 taken 10 times.
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 9 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 154 times.
|
155 | if (throw_error && !check) { |
220 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | throw CircuitInequality( | |
221 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | std::string("Circuit created qubits do not match.")); | |
222 | } | |||
223 |
2/4✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 154 times.
✗ Branch 6 not taken.
|
154 | check &= (this->discarded_qubits() == other.discarded_qubits()); | |
224 |
4/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 8 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 153 times.
|
154 | if (throw_error && !check) { |
225 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | throw CircuitInequality( | |
226 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | std::string("Circuit discarded qubits do not match.")); | |
227 | } | |||
228 | } | |||
229 | ||||
230 |
3/4✓ Branch 1 taken 153 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 152 times.
✓ Branch 4 taken 1 times.
|
2/2✓ Decision 'true' taken 152 times.
✓ Decision 'false' taken 1 times.
|
153 | if (except.count(Check::ImplicitPermutation) == 0) { |
231 | 152 | check &= | ||
232 |
2/4✓ Branch 1 taken 152 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 152 times.
✗ Branch 5 not taken.
|
152 | (this->implicit_qubit_permutation() == | |
233 | 304 | other.implicit_qubit_permutation()); | ||
234 |
4/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 151 times.
|
152 | if (throw_error && !check) { |
235 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | throw CircuitInequality( | |
236 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | std::string("Circuit implicit permutations do not match.")); | |
237 | } | |||
238 | } | |||
239 |
2/4✓ Branch 1 taken 152 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 152 times.
✗ Branch 4 not taken.
|
1/2✓ Decision 'true' taken 152 times.
✗ Decision 'false' not taken.
|
152 | if (except.count(Check::Name) == 0) { |
240 |
1/2✓ Branch 2 taken 152 times.
✗ Branch 3 not taken.
|
152 | check &= (this->get_name() == other.get_name()); | |
241 |
4/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 151 times.
|
152 | if (throw_error && !check) { |
242 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const std::optional<std::string> thisname = this->get_name(); | |
243 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const std::optional<std::string> othename = other.get_name(); | |
244 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::string errormsg = "Circuit names do not match: "; | |
245 |
5/14✓ 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 11 not taken.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
1 | errormsg += (thisname ? thisname.value() : "None"); | |
246 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | errormsg += " != "; | |
247 |
4/14✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
1 | errormsg += (othename ? othename.value() : "None"); | |
248 | ||||
249 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | throw CircuitInequality(errormsg); | |
250 | 3 | } | ||
251 | } | |||
252 | 151 | return check; | ||
253 | } | |||
254 | ||||
255 | // Performs a traversal from the given vertex forwards through the dag, looking | |||
256 | // for something on the target qubit We can prune a path if it reaches the depth | |||
257 | // of the target forward = true returns true if target is in causal future of | |||
258 | // from forward = false checks for causal past (v_to_depth should give reverse | |||
259 | // depth) | |||
260 | // TODO:: rewrite to work with classical boxes | |||
261 | 911 | bool Circuit::in_causal_order( | ||
262 | const Vertex &target, const Vertex &from, bool forward, | |||
263 | const std::map<Vertex, unsigned> &v_to_depth, | |||
264 | const std::map<Vertex, unit_set_t> &v_to_units, bool strict) const { | |||
265 |
1/2✓ Branch 1 taken 911 times.
✗ Branch 2 not taken.
|
911 | unsigned target_depth = v_to_depth.at(target); | |
266 |
4/4✓ Branch 0 taken 801 times.
✓ Branch 1 taken 110 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 800 times.
|
2/2✓ Decision 'true' taken 910 times.
✓ Decision 'false' taken 1 times.
|
911 | if (!strict && from == target) return true; |
267 |
3/4✓ Branch 1 taken 910 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 872 times.
✓ Branch 4 taken 38 times.
|
2/2✓ Decision 'true' taken 362 times.
✓ Decision 'false' taken 548 times.
|
910 | if (v_to_depth.at(from) >= target_depth) return false; |
268 | typedef std::function<bool(Vertex, Vertex)> Comp; | |||
269 | 362 | Comp c = [&](Vertex a, Vertex b) { | ||
270 | 362 | unsigned deptha = v_to_depth.at(a); | ||
271 | 362 | unsigned depthb = v_to_depth.at(b); | ||
272 |
2/2✓ Branch 0 taken 160 times.
✓ Branch 1 taken 202 times.
|
2/2✓ Decision 'true' taken 160 times.
✓ Decision 'false' taken 202 times.
|
362 | if (deptha == depthb) { |
273 |
2/4✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 160 times.
✗ Branch 5 not taken.
|
160 | unit_set_t unitsa = v_to_units.at(a); | |
274 |
2/4✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 160 times.
✗ Branch 5 not taken.
|
160 | unit_set_t unitsb = v_to_units.at(b); | |
275 |
1/2✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
|
160 | return unitsa < unitsb; | |
276 | 160 | } | ||
277 | 202 | return deptha < depthb; | ||
278 | 38 | }; | ||
279 |
1/2✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
|
38 | std::set<Vertex, Comp> to_search(c); | |
280 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 1 times.
|
2/2✓ Decision 'true' taken 37 times.
✓ Decision 'false' taken 1 times.
|
38 | if (forward) { |
281 |
1/2✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
|
37 | VertexVec succs = get_successors(from); | |
282 |
2/2✓ Branch 5 taken 64 times.
✓ Branch 6 taken 37 times.
|
2/2✓ Decision 'true' taken 64 times.
✓ Decision 'false' taken 37 times.
|
101 | for (const Vertex &s : succs) { |
283 |
2/4✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 64 times.
✗ Branch 6 not taken.
|
1/2✓ Decision 'true' taken 64 times.
✗ Decision 'false' not taken.
|
64 | if (v_to_depth.find(s) != v_to_depth.end()) { |
284 |
1/2✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
|
64 | to_search.insert(s); | |
285 | } | |||
286 | } | |||
287 | 37 | } else { | ||
288 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | VertexVec preds = get_predecessors(from); | |
289 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1 | to_search.insert(preds.begin(), preds.end()); | |
290 | 1 | } | ||
291 |
2/4✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
|
38 | unit_set_t lookup_units = v_to_units.at(target); | |
292 |
2/2✓ Branch 1 taken 255 times.
✓ Branch 2 taken 22 times.
|
2/2✓ Decision 'true' taken 255 times.
✓ Decision 'false' taken 22 times.
|
277 | while (!to_search.empty()) { |
293 | 255 | Vertex v = *to_search.begin(); | ||
294 |
1/2✓ Branch 2 taken 255 times.
✗ Branch 3 not taken.
|
255 | to_search.erase(to_search.begin()); | |
295 |
3/4✓ Branch 1 taken 255 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 228 times.
|
2/2✓ Decision 'true' taken 228 times.
✓ Decision 'false' taken 27 times.
|
255 | if (v_to_depth.at(v) > target_depth) continue; |
296 |
2/4✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 228 times.
✗ Branch 5 not taken.
|
228 | unit_set_t v_units = v_to_units.at(v); | |
297 |
2/2✓ Branch 5 taken 253 times.
✓ Branch 6 taken 212 times.
|
2/2✓ Decision 'true' taken 253 times.
✓ Decision 'false' taken 212 times.
|
465 | for (const UnitID &u : lookup_units) { |
298 |
3/4✓ Branch 2 taken 253 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 16 times.
✓ Branch 6 taken 237 times.
|
2/2✓ Decision 'true' taken 16 times.
✓ Decision 'false' taken 237 times.
|
253 | if (v_units.find(u) != v_units.end()) { |
299 | 16 | return true; | ||
300 | } | |||
301 | } | |||
302 |
1/2✓ Branch 0 taken 212 times.
✗ Branch 1 not taken.
|
1/2✓ Decision 'true' taken 212 times.
✗ Decision 'false' not taken.
|
212 | if (forward) { |
303 |
1/2✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
|
212 | VertexVec succs = get_successors(v); | |
304 |
2/2✓ Branch 5 taken 219 times.
✓ Branch 6 taken 212 times.
|
2/2✓ Decision 'true' taken 219 times.
✓ Decision 'false' taken 212 times.
|
431 | for (const Vertex &s : succs) { |
305 |
3/4✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 205 times.
✓ Branch 6 taken 14 times.
|
2/2✓ Decision 'true' taken 205 times.
✓ Decision 'false' taken 14 times.
|
219 | if (v_to_depth.find(s) != v_to_depth.end()) { |
306 |
1/2✓ Branch 1 taken 205 times.
✗ Branch 2 not taken.
|
205 | to_search.insert(s); | |
307 | } | |||
308 | } | |||
309 | 212 | } else { | ||
310 | ✗ | VertexVec preds = get_predecessors(v); | ||
311 | ✗ | to_search.insert(preds.begin(), preds.end()); | ||
312 | } | |||
313 |
2/2✓ Branch 1 taken 212 times.
✓ Branch 2 taken 16 times.
|
228 | } | |
314 | 22 | return false; | ||
315 | 38 | } | ||
316 | ||||
317 | } // namespace tket | |||
318 |