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 "Utils/GraphHeaders.hpp" | |||
16 | #include "ZX/ZXDiagram.hpp" | |||
17 | ||||
18 | namespace tket { | |||
19 | ||||
20 | namespace zx { | |||
21 | ||||
22 | 2 | bool WireProperties::operator==(const WireProperties& other) const { | ||
23 |
3/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
|
4 | return (this->type == other.type) && (this->qtype == other.qtype) && | |
24 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
6 | (this->source_port == other.source_port) && | |
25 | 3 | (this->target_port == other.target_port); | ||
26 | } | |||
27 | ||||
28 | 214 | ZXVertVec ZXDiagram::get_boundary( | ||
29 | std::optional<ZXType> type, std::optional<QuantumType> qtype) const { | |||
30 |
6/8✓ Branch 1 taken 88 times.
✓ Branch 2 taken 126 times.
✓ Branch 4 taken 88 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 88 times.
✓ Branch 7 taken 126 times.
✓ Branch 9 taken 88 times.
✗ Branch 10 not taken.
|
2/2✓ Decision 'true' taken 126 times.
✓ Decision 'false' taken 88 times.
|
214 | if (!type && !qtype) return boundary; |
31 | ||||
32 | 126 | ZXVertVec sub_boundary; | ||
33 |
2/2✓ Branch 5 taken 502 times.
✓ Branch 6 taken 126 times.
|
2/2✓ Decision 'true' taken 502 times.
✓ Decision 'false' taken 126 times.
|
628 | for (const ZXVert& b : boundary) { |
34 |
4/6✓ Branch 1 taken 502 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 502 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 275 times.
✓ Branch 8 taken 227 times.
|
2/2✓ Decision 'true' taken 269 times.
✓ Decision 'false' taken 508 times.
|
777 | if ((!type || get_zxtype(b) == *type) && |
35 |
7/8✓ Branch 1 taken 33 times.
✓ Branch 2 taken 242 times.
✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 27 times.
✓ Branch 9 taken 6 times.
✓ Branch 10 taken 269 times.
✓ Branch 11 taken 233 times.
|
777 | (!qtype || *get_qtype(b) == *qtype)) | |
36 |
1/2✓ Branch 1 taken 269 times.
✗ Branch 2 not taken.
|
269 | sub_boundary.push_back(b); | |
37 | } | |||
38 | 126 | return sub_boundary; | ||
39 | 126 | } | ||
40 | ||||
41 | 29 | std::unique_ptr<ZXGraph>& ZXDiagram::get_graph() { return graph; } | ||
42 | ||||
43 | 122 | void ZXDiagram::add_boundary(ZXVert& vert) { boundary.push_back(vert); } | ||
44 | 80 | const Expr& ZXDiagram::get_scalar() const { return scalar; } | ||
45 | ||||
46 | 121 | void ZXDiagram::multiply_scalar(const Expr& sc) { scalar *= sc; } | ||
47 | ||||
48 | 46 | unsigned ZXDiagram::n_vertices() const { return boost::num_vertices(*graph); } | ||
49 | ||||
50 | 29 | unsigned ZXDiagram::n_wires() const { return boost::num_edges(*graph); } | ||
51 | ||||
52 | 26 | unsigned ZXDiagram::count_vertices(ZXType type) const { | ||
53 | 26 | unsigned count = 0; | ||
54 |
7/8✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1316 times.
✓ Branch 7 taken 26 times.
✓ Branch 9 taken 1316 times.
✓ Branch 10 taken 26 times.
✓ Branch 12 taken 26 times.
✓ Branch 13 taken 26 times.
|
1368 | BGL_FORALL_VERTICES(v, *graph, ZXGraph) { | |
55 |
3/4✓ Branch 1 taken 1316 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✓ Branch 4 taken 1268 times.
|
2/2✓ Decision 'true' taken 26 times.
✓ Decision 'false' taken 1290 times.
|
1316 | if (get_zxtype(v) == type) ++count; |
56 | } | |||
57 | 26 | return count; | ||
58 | } | |||
59 | ||||
60 | 84 | unsigned ZXDiagram::count_vertices(ZXType zxtype, QuantumType qtype) const { | ||
61 | 84 | unsigned count = 0; | ||
62 |
7/8✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2275 times.
✓ Branch 7 taken 84 times.
✓ Branch 9 taken 2275 times.
✓ Branch 10 taken 84 times.
✓ Branch 12 taken 84 times.
✓ Branch 13 taken 84 times.
|
2443 | BGL_FORALL_VERTICES(v, *graph, ZXGraph) { | |
63 |
8/10✓ Branch 1 taken 2275 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 448 times.
✓ Branch 4 taken 1827 times.
✓ Branch 6 taken 448 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 252 times.
✓ Branch 10 taken 196 times.
✓ Branch 11 taken 252 times.
✓ Branch 12 taken 2023 times.
|
2/2✓ Decision 'true' taken 84 times.
✓ Decision 'false' taken 2191 times.
|
2275 | if (get_zxtype(v) == zxtype && get_qtype(v) == qtype) ++count; |
64 | } | |||
65 | 84 | return count; | ||
66 | } | |||
67 | ||||
68 | 3 | unsigned ZXDiagram::count_wires(ZXWireType type) const { | ||
69 | 3 | unsigned count = 0; | ||
70 |
12/18✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 27 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 30 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 27 times.
✓ Branch 14 taken 3 times.
✓ Branch 16 taken 27 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 27 times.
✓ Branch 19 taken 3 times.
✓ Branch 21 taken 6 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 3 times.
✓ Branch 24 taken 3 times.
|
33 | BGL_FORALL_EDGES(w, *graph, ZXGraph) { | |
71 |
3/4✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 19 times.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 24 times.
|
27 | if (get_wire_type(w) == type) ++count; |
72 | } | |||
73 | 3 | return count; | ||
74 | } | |||
75 | ||||
76 | 270 | unsigned ZXDiagram::degree(const ZXVert& v) const { | ||
77 | 270 | return boost::out_degree(v, *graph) + boost::in_degree(v, *graph); | ||
78 | } | |||
79 | ||||
80 | 1284 | ZXVertVec ZXDiagram::neighbours(const ZXVert& v) const { | ||
81 |
1/2✓ Branch 1 taken 1284 times.
✗ Branch 2 not taken.
|
1284 | ZXVertSeqSet neis; | |
82 |
14/22✓ Branch 2 taken 1284 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1111 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1994 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1994 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1994 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 3105 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1994 times.
✓ Branch 20 taken 1111 times.
✓ Branch 22 taken 1994 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1994 times.
✓ Branch 25 taken 1111 times.
✓ Branch 27 taken 2395 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1111 times.
✓ Branch 30 taken 1284 times.
|
4389 | BGL_FORALL_OUTEDGES(v, w, *graph, ZXGraph) neis.insert(target(w)); | |
83 |
14/22✓ Branch 2 taken 1284 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 885 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1241 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1241 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1241 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 2126 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1241 times.
✓ Branch 20 taken 885 times.
✓ Branch 22 taken 1241 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1241 times.
✓ Branch 25 taken 885 times.
✓ Branch 27 taken 2169 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 885 times.
✓ Branch 30 taken 1284 times.
|
3410 | BGL_FORALL_INEDGES(v, w, *graph, ZXGraph) neis.insert(source(w)); | |
84 | 1284 | auto& ordered = neis.get<TagSeq>(); | ||
85 |
1/2✓ Branch 4 taken 1284 times.
✗ Branch 5 not taken.
|
1284 | ZXVertVec neighbours(ordered.begin(), ordered.end()); | |
86 | 2568 | return neighbours; | ||
87 | 1284 | } | ||
88 | ||||
89 | 745 | WireVec ZXDiagram::adj_wires(const ZXVert& v) const { | ||
90 | 745 | WireVec adj; | ||
91 |
13/20✓ Branch 2 taken 745 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 701 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1253 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1253 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1954 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1253 times.
✓ Branch 17 taken 701 times.
✓ Branch 19 taken 1253 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1253 times.
✓ Branch 22 taken 701 times.
✓ Branch 24 taken 1446 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 701 times.
✓ Branch 27 taken 745 times.
|
2699 | BGL_FORALL_OUTEDGES(v, w, *graph, ZXGraph) adj.push_back(w); | |
92 |
12/18✓ Branch 2 taken 745 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 447 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 613 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1060 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 613 times.
✓ Branch 14 taken 447 times.
✓ Branch 16 taken 613 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 613 times.
✓ Branch 19 taken 447 times.
✓ Branch 21 taken 1192 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 447 times.
✓ Branch 24 taken 745 times.
|
1805 | BGL_FORALL_INEDGES(v, w, *graph, ZXGraph) { | |
93 | // Only add self loops once (ignore the in_edge wires for loops) | |||
94 |
4/6✓ Branch 1 taken 613 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 589 times.
✓ Branch 4 taken 24 times.
✓ Branch 6 taken 589 times.
✗ Branch 7 not taken.
|
0/1? Decision couldn't be analyzed.
|
613 | if (source(w) != v) adj.push_back(w); |
95 | } | |||
96 | 745 | return adj; | ||
97 | } | |||
98 | ||||
99 | 1 | WireVec ZXDiagram::wires_between(const ZXVert& u, const ZXVert& v) const { | ||
100 | 1 | WireVec wires; | ||
101 |
3/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 1 times.
|
0/1? Decision couldn't be analyzed.
|
5 | for (const Wire& w : adj_wires(u)) { |
102 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | ZXVert other = other_end(w, u); | |
103 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 3 times.
|
4 | if (other == v) wires.push_back(w); |
104 | 1 | } | ||
105 | 1 | return wires; | ||
106 | } | |||
107 | ||||
108 | 357 | std::optional<Wire> ZXDiagram::wire_between( | ||
109 | const ZXVert& va, const ZXVert& vb, | |||
110 | ZXDiagram::WireSearchOption directed) const { | |||
111 |
1/2✓ Branch 2 taken 357 times.
✗ Branch 3 not taken.
|
357 | const auto& [wire, exists] = boost::edge(va, vb, *graph); | |
112 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 261 times.
|
2/2✓ Decision 'true' taken 96 times.
✓ Decision 'false' taken 261 times.
|
357 | if (exists) |
113 | 96 | return wire; | ||
114 |
2/2✓ Branch 0 taken 151 times.
✓ Branch 1 taken 110 times.
|
2/2✓ Decision 'true' taken 151 times.
✓ Decision 'false' taken 110 times.
|
261 | else if (directed == WireSearchOption::UNDIRECTED) |
115 |
1/2✓ Branch 1 taken 151 times.
✗ Branch 2 not taken.
|
151 | return wire_between(vb, va, WireSearchOption::DIRECTED); | |
116 | else | |||
117 | 110 | return std::nullopt; | ||
118 | } | |||
119 | ||||
120 | 32 | Wire ZXDiagram::wire_at_port( | ||
121 | const ZXVert& v, std::optional<unsigned> port) const { | |||
122 | 32 | Wire w_found; | ||
123 | 32 | unsigned n_found = 0; | ||
124 |
12/18✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 32 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 64 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 32 times.
✓ Branch 14 taken 32 times.
✓ Branch 16 taken 32 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 32 times.
✓ Branch 19 taken 32 times.
✓ Branch 21 taken 64 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 32 times.
✓ Branch 24 taken 32 times.
|
96 | BGL_FORALL_OUTEDGES(v, w, *graph, ZXGraph) { | |
125 |
3/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 16 times.
|
2/2✓ Decision 'true' taken 16 times.
✓ Decision 'false' taken 16 times.
|
32 | if (source_port(w) == port) { |
126 | 16 | w_found = w; | ||
127 | 16 | ++n_found; | ||
128 | } | |||
129 | } | |||
130 |
12/18✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 32 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 64 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 32 times.
✓ Branch 14 taken 32 times.
✓ Branch 16 taken 32 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 32 times.
✓ Branch 19 taken 32 times.
✓ Branch 21 taken 64 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 32 times.
✓ Branch 24 taken 32 times.
|
96 | BGL_FORALL_INEDGES(v, w, *graph, ZXGraph) { | |
131 |
3/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 16 times.
|
2/2✓ Decision 'true' taken 16 times.
✓ Decision 'false' taken 16 times.
|
32 | if (target_port(w) == port) { |
132 | 16 | w_found = w; | ||
133 | 16 | ++n_found; | ||
134 | } | |||
135 | } | |||
136 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 32 times.
|
32 | if (n_found != 1) |
137 | ✗ | throw ZXError( | ||
138 | ✗ | "Expected only one wire at port, found " + std::to_string(n_found)); | ||
139 | 32 | return w_found; | ||
140 | } | |||
141 | ||||
142 | 1925 | ZXGen_ptr ZXDiagram::get_vertex_ZXGen_ptr(const ZXVert& v) const { | ||
143 | 1925 | return (*graph)[v].op; | ||
144 | } | |||
145 | ||||
146 | 3 | std::string ZXDiagram::get_name(const ZXVert& v) const { | ||
147 | 3 | return (*graph)[v].op->get_name(); | ||
148 | } | |||
149 | ||||
150 | 13212 | ZXType ZXDiagram::get_zxtype(const ZXVert& v) const { | ||
151 | 13212 | return (*graph)[v].op->get_type(); | ||
152 | } | |||
153 | ||||
154 | 1376 | std::optional<QuantumType> ZXDiagram::get_qtype(const ZXVert& v) const { | ||
155 | 1376 | return (*graph)[v].op->get_qtype(); | ||
156 | } | |||
157 | ||||
158 | 221 | void ZXDiagram::set_vertex_ZXGen_ptr(const ZXVert& v, const ZXGen_ptr& op) { | ||
159 | 221 | (*graph)[v].op = op; | ||
160 | 221 | } | ||
161 | ||||
162 | 762 | WireProperties ZXDiagram::get_wire_info(const Wire& w) const { | ||
163 | 762 | return (*graph)[w]; | ||
164 | } | |||
165 | ||||
166 | 2289 | QuantumType ZXDiagram::get_qtype(const Wire& w) const { | ||
167 | 2289 | return (*graph)[w].qtype; | ||
168 | } | |||
169 | ||||
170 | 1497 | ZXWireType ZXDiagram::get_wire_type(const Wire& w) const { | ||
171 | 1497 | return (*graph)[w].type; | ||
172 | } | |||
173 | ||||
174 | 5043 | ZXVert ZXDiagram::source(const Wire& w) const { | ||
175 | 5043 | return boost::source(w, *graph); | ||
176 | } | |||
177 | ||||
178 | 5002 | ZXVert ZXDiagram::target(const Wire& w) const { | ||
179 | 5002 | return boost::target(w, *graph); | ||
180 | } | |||
181 | ||||
182 | 786 | std::optional<unsigned> ZXDiagram::source_port(const Wire& w) const { | ||
183 | 786 | return (*graph)[w].source_port; | ||
184 | } | |||
185 | ||||
186 | 800 | std::optional<unsigned> ZXDiagram::target_port(const Wire& w) const { | ||
187 | 800 | return (*graph)[w].target_port; | ||
188 | } | |||
189 | ||||
190 | 1621 | ZXVert ZXDiagram::other_end(const Wire& w, const ZXVert& u) const { | ||
191 | 1621 | ZXVert s = source(w); | ||
192 | 1621 | ZXVert t = target(w); | ||
193 |
2/2✓ Branch 0 taken 1127 times.
✓ Branch 1 taken 494 times.
|
2/2✓ Decision 'true' taken 1127 times.
✓ Decision 'false' taken 494 times.
|
1621 | if (s == u) { |
194 | 1127 | return t; | ||
195 |
1/2✓ Branch 0 taken 494 times.
✗ Branch 1 not taken.
|
1/2✓ Decision 'true' taken 494 times.
✗ Decision 'false' not taken.
|
494 | } else if (t == u) { |
196 | 494 | return s; | ||
197 | } else { | |||
198 | ✗ | throw ZXError("In other_end(w, u), u is not adjacent to w."); | ||
199 | } | |||
200 | } | |||
201 | ||||
202 | 12 | ZXVert ZXDiagram::vertex_at_end(const Wire& w, WireEnd we) const { | ||
203 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
|
2/2✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 7 times.
|
12 | if (we == WireEnd::Source) |
204 | 5 | return source(w); | ||
205 | else | |||
206 | 7 | return target(w); | ||
207 | } | |||
208 | ||||
209 | 111 | WireEnd ZXDiagram::end_of(const Wire& w, const ZXVert& u) const { | ||
210 |
2/2✓ Branch 1 taken 56 times.
✓ Branch 2 taken 55 times.
|
2/2✓ Decision 'true' taken 56 times.
✓ Decision 'false' taken 55 times.
|
111 | if (source(w) == u) { |
211 | 56 | return WireEnd::Source; | ||
212 |
1/2✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
|
1/2✓ Decision 'true' taken 55 times.
✗ Decision 'false' not taken.
|
55 | } else if (target(w) == u) { |
213 | 55 | return WireEnd::Target; | ||
214 | } else { | |||
215 | ✗ | throw ZXError("In end_of(w, u), u is not adjacent to w."); | ||
216 | } | |||
217 | } | |||
218 | ||||
219 | ✗ | void ZXDiagram::set_wire_info(const Wire& w, const WireProperties& wp) { | ||
220 | ✗ | (*graph)[w] = wp; | ||
221 | } | |||
222 | ||||
223 | 1 | void ZXDiagram::set_wire_qtype(const Wire& w, QuantumType qtype) { | ||
224 | 1 | (*graph)[w].qtype = qtype; | ||
225 | 1 | } | ||
226 | ||||
227 | 135 | void ZXDiagram::set_wire_type(const Wire& w, ZXWireType type) { | ||
228 | 135 | (*graph)[w].type = type; | ||
229 | 135 | } | ||
230 | ||||
231 | 34 | bool ZXDiagram::is_pauli_spider(const ZXVert& v) const { | ||
232 |
1/2✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
|
34 | ZXGen_ptr op = get_vertex_ZXGen_ptr(v); | |
233 |
4/6✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 34 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 24 times.
|
2/2✓ Decision 'true' taken 24 times.
✓ Decision 'false' taken 10 times.
|
34 | if (!is_spider_type(op->get_type())) return false; |
234 | 24 | const PhasedGen& bg = static_cast<const PhasedGen&>(*op); | ||
235 |
2/4✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
|
24 | std::optional<unsigned> pi2_mult = equiv_Clifford(bg.get_param()); | |
236 |
4/4✓ Branch 1 taken 21 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 15 times.
|
24 | return (pi2_mult && ((*pi2_mult % 2) == 0)); | |
237 | 34 | } | ||
238 | ||||
239 | 41 | bool ZXDiagram::is_proper_clifford_spider(const ZXVert& v) const { | ||
240 |
1/2✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
|
41 | ZXGen_ptr op = get_vertex_ZXGen_ptr(v); | |
241 |
4/6✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 41 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✓ Branch 8 taken 33 times.
|
2/2✓ Decision 'true' taken 33 times.
✓ Decision 'false' taken 8 times.
|
41 | if (!is_spider_type(op->get_type())) return false; |
242 | 33 | const PhasedGen& bg = static_cast<const PhasedGen&>(*op); | ||
243 |
2/4✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
|
33 | std::optional<unsigned> pi2_mult = equiv_Clifford(bg.get_param()); | |
244 |
4/4✓ Branch 1 taken 29 times.
✓ Branch 2 taken 4 times.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 12 times.
|
33 | return (pi2_mult && ((*pi2_mult % 2) == 1)); | |
245 | 41 | } | ||
246 | ||||
247 | 7 | static std::string graphviz_vertex_props(ZXGen_ptr op) { | ||
248 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | std::stringstream ss; | |
249 | ||||
250 | // Tooltips (rollover text) contains the get_name information | |||
251 |
4/8✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 7 times.
✗ Branch 12 not taken.
|
7 | ss << "tooltip=\"" + op->get_name() + "\" "; | |
252 | ||||
253 | // Classical nodes are drawn thinner | |||
254 |
4/6✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 6 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
1/2✓ Decision 'true' taken 7 times.
✗ Decision 'false' not taken.
|
7 | if (op->get_qtype() == QuantumType::Classical) ss << "penwidth=1 "; |
255 | ||||
256 | // Modify node drawing properties based on this type | |||
257 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | ZXType type = op->get_type(); | |
258 | ||||
259 |
5/7✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
7 | switch (type) { | |
260 | 2 | case ZXType::Input: | ||
261 | case ZXType::Output: | |||
262 | case ZXType::Open: { | |||
263 | ss << "style=\"filled, dashed\" fillcolor=\"white\" shape=circle " | |||
264 | "label=\"" | |||
265 |
4/8✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
|
2 | << op->get_name() << "\""; | |
266 | 2 | break; | ||
267 | } | |||
268 | 2 | case ZXType::ZSpider: | ||
269 | case ZXType::XSpider: { | |||
270 | 2 | const PhasedGen& bg = static_cast<const PhasedGen&>(*op); | ||
271 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | Expr p = bg.get_param(); | |
272 |
3/4✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | std::string colour = (type == ZXType::ZSpider) ? "green" : "red"; | |
273 |
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 | ss << "fillcolor=\"" << colour << "\" shape=circle label=\""; | |
274 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
1/2✓ Decision 'true' taken 2 times.
✗ Decision 'false' not taken.
|
2 | if (!equiv_0(p)) ss << p; |
275 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | ss << "\""; | |
276 | 2 | break; | ||
277 | 2 | } | ||
278 |
1/1✓ Decision 'true' taken 1 times.
|
1 | case ZXType::Hbox: { | |
279 | 1 | const PhasedGen& bg = static_cast<const PhasedGen&>(*op); | ||
280 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Expr p = bg.get_param(); | |
281 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::optional<Complex> ev = eval_expr_c(p); | |
282 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ss << "fillcolor=\"gold\" shape=square label=\""; | |
283 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
|
1/2✓ Decision 'true' taken 1 times.
✗ Decision 'false' not taken.
|
1 | if (!ev || (std::abs(*ev + 1.) >= EPS)) ss << p; |
284 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ss << "\""; | |
285 | 1 | break; | ||
286 | 1 | } | ||
287 | ✗ | case ZXType::XY: | ||
288 | case ZXType::XZ: | |||
289 | case ZXType::YZ: | |||
290 | case ZXType::PX: | |||
291 | case ZXType::PY: | |||
292 | case ZXType::PZ: { | |||
293 | ✗ | ss << "shape=circle width=0.1 fixedsize=shape label=\"" << op->get_name() | ||
294 | ✗ | << "\\n\\n\""; | ||
295 | ✗ | break; | ||
296 | } | |||
297 |
1/1✓ Decision 'true' taken 1 times.
|
1 | case ZXType::Triangle: { | |
298 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ss << "fillcolor=\"gold\" shape=triangle"; | |
299 | 1 | break; | ||
300 | } | |||
301 |
1/1✓ Decision 'true' taken 1 times.
|
1 | case ZXType::ZXBox: { | |
302 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ss << "shape=box3d penwidth=2 label=\"Box\""; | |
303 | 1 | break; | ||
304 | } | |||
305 |
0/1✗ Decision 'true' not taken.
|
✗ | default: { | |
306 | ✗ | throw ZXError( | ||
307 | "Trying to render vertex in a ZXDiagram with unknown " | |||
308 | ✗ | "ZXType"); | ||
309 | } | |||
310 | } | |||
311 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
14 | return ss.str(); | |
312 | 7 | } | ||
313 | ||||
314 | 10 | static std::string graphviz_wire_props(const WireProperties& wp) { | ||
315 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | std::stringstream ss; | |
316 | ||||
317 | // (default assumption is that qtype==Quantum) | |||
318 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1/2✓ Decision 'true' taken 10 times.
✗ Decision 'false' not taken.
|
10 | if (wp.qtype == QuantumType::Classical) ss << "penwidth=1 "; |
319 | ||||
320 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1/2✓ Decision 'true' taken 10 times.
✗ Decision 'false' not taken.
|
10 | if (wp.type == ZXWireType::H) ss << "style=dashed color=\"blue\" "; |
321 | ||||
322 | // port information: | |||
323 | // in graphviz, the 'head' of an edge refers to the `Target` end | |||
324 | // and similarly, the 'tail' of an edge refers to the `Source` end | |||
325 |
5/8✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 5 times.
✗ Branch 12 not taken.
|
1/2✓ Decision 'true' taken 10 times.
✗ Decision 'false' not taken.
|
10 | if (wp.source_port) ss << " taillabel=\"" << *wp.source_port << "\""; |
326 |
5/8✓ Branch 1 taken 1 times.
✓ Branch 2 taken 9 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
|
0/1? Decision couldn't be analyzed.
|
10 | if (wp.target_port) ss << " headlabel=\"" << *wp.target_port << "\""; |
327 | ||||
328 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | return ss.str(); | |
329 | 10 | } | ||
330 | ||||
331 | 1 | std::string ZXDiagram::to_graphviz_str( | ||
332 | const std::set<ZXVert>& highlights) const { | |||
333 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::stringstream out; | |
334 | ||||
335 | // Construct ZXVert index map (used as vertex IDs by graphviz) | |||
336 | 1 | std::map<ZXVert, unsigned> idm; | ||
337 | 1 | unsigned x = 0; | ||
338 |
8/10✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 7 times.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 7 times.
✓ Branch 14 taken 1 times.
✓ Branch 16 taken 1 times.
✓ Branch 17 taken 1 times.
|
9 | BGL_FORALL_VERTICES(v, *graph, ZXGraph) { idm.insert({v, x++}); } | |
339 | ||||
340 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out << "graph G {\n"; | |
341 | ||||
342 | /** | |||
343 | * Draw the vertices. | |||
344 | * By default vertices are assumed to be of type `QuantumType::Quantum`. | |||
345 | * That is, they will be drawn thick: `penwidth=3` sets this. | |||
346 | * If a node is classical, we will draw them thinner: `penwidth=1`. | |||
347 | **/ | |||
348 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out << "node [penwidth=3 style=filled]\n"; | |
349 |
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, *graph, ZXGraph) { | |
350 | // Specifying node ID we are defining properties on | |||
351 |
2/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
7 | out << idm.at(v); | |
352 | ||||
353 | // Defining the properties bracket | |||
354 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | out << " ["; | |
355 | ||||
356 | // Define vertex properties based on ZXGen | |||
357 |
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 | out << graphviz_vertex_props(get_vertex_ZXGen_ptr(v)); | |
358 | ||||
359 | // Additional visual properties on node: | |||
360 | // exterior labels for the node ID information | |||
361 |
4/8✓ 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.
✓ Branch 10 taken 7 times.
✗ Branch 11 not taken.
|
7 | out << " xlabel=<<font color=\"grey\">" << idm.at(v) << "</font>>"; | |
362 | ||||
363 | // Highlight the vertices in `highlights` by red border | |||
364 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | auto loc = highlights.find(v); | |
365 |
1/4✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
1/2✓ Decision 'true' taken 7 times.
✗ Decision 'false' not taken.
|
7 | if (loc != highlights.end()) out << " color=\"red3\""; |
366 | ||||
367 | // Close off the properties list for the vertices | |||
368 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | out << "];\n"; | |
369 | } | |||
370 | ||||
371 | /** | |||
372 | * Draw the edges. | |||
373 | * By default, the edges are assumed to be quantum edges `penwidth=3`, | |||
374 | * that is, they are drawn 'thick'. Classical edges will be made thinner: | |||
375 | * that is, `penwidth=1`. | |||
376 | **/ | |||
377 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out << "edge [penwidth=3]\n"; | |
378 |
12/18✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 11 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 10 times.
✓ Branch 14 taken 1 times.
✓ Branch 16 taken 10 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 10 times.
✓ Branch 19 taken 1 times.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 24 taken 1 times.
|
12 | BGL_FORALL_EDGES(w, *graph, ZXGraph) { | |
379 | // Draw an edge between the Wire's two ends | |||
380 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | ZXVert s = source(w); | |
381 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | ZXVert t = target(w); | |
382 |
5/10✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 10 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 10 times.
✗ Branch 14 not taken.
|
10 | out << idm.at(s) << " -- " << idm.at(t); | |
383 | ||||
384 | // Defining the properties bracket | |||
385 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | out << " ["; | |
386 |
3/6✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
|
10 | out << graphviz_wire_props(get_wire_info(w)); | |
387 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | out << "]\n"; | |
388 | } | |||
389 | ||||
390 | /** | |||
391 | * Invisible nodes & connections to force the same ordering for the | |||
392 | * vertices within the same rank - such that inputs / outputs will be | |||
393 | * at the same level and with it, have a fixed ordering. | |||
394 | **/ | |||
395 | out << "rankdir = LR;\n" | |||
396 | "input_rank [style=invisible];\n" | |||
397 | "output_rank [style=invisible];\n" | |||
398 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | "input_rank -- output_rank [style=invis];\n"; | |
399 | ||||
400 | out << "{ rank = same\n" | |||
401 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | "input_rank"; | |
402 |
3/4✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
|
0/1? Decision couldn't be analyzed.
|
2 | for (const ZXVert& v : get_boundary(ZXType::Input)) |
403 |
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.
|
2 | out << " -- " << idm.at(v); | |
404 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out << " [style=invis]; }\n"; | |
405 | ||||
406 | out << "{ rank = same\n" | |||
407 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | "output_rank"; | |
408 |
3/4✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
|
0/1? Decision couldn't be analyzed.
|
2 | for (const ZXVert& v : get_boundary(ZXType::Output)) |
409 |
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.
|
2 | out << " -- " << idm.at(v); | |
410 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out << " [style=invis]; }\n"; | |
411 | ||||
412 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out << "}\n"; | |
413 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | return out.str(); | |
414 | 1 | } | ||
415 | ||||
416 | } // namespace zx | |||
417 | ||||
418 | } // namespace tket | |||
419 |