GCC Code Coverage Report


Directory: ./
File: ZX/ZXDGettersSetters.cpp
Date: 2022-10-15 05:10:18
Warnings: 5 unchecked decisions!
Exec Total Coverage
Lines: 216 229 94.3%
Functions: 39 40 97.5%
Branches: 332 543 61.1%
Decisions: 45 66 68.2%

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