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/Constants.hpp" | |||
16 | #include "Utils/GraphHeaders.hpp" | |||
17 | #include "ZX/Rewrite.hpp" | |||
18 | ||||
19 | namespace tket { | |||
20 | ||||
21 | namespace zx { | |||
22 | ||||
23 | 5 | bool Rewrite::decompose_boxes_fun(ZXDiagram& diag) { | ||
24 | 5 | bool success = false; | ||
25 | 5 | std::list<ZXVert> to_decompose; | ||
26 |
7/8✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 17 times.
✓ Branch 7 taken 5 times.
✓ Branch 9 taken 17 times.
✓ Branch 10 taken 5 times.
✓ Branch 12 taken 5 times.
✓ Branch 13 taken 5 times.
|
27 | BGL_FORALL_VERTICES(v, *diag.graph, ZXGraph) { | |
27 |
4/6✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 14 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
2/2✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 9 times.
|
17 | if (diag.get_zxtype(v) == ZXType::ZXBox) to_decompose.push_back(v); |
28 | } | |||
29 |
2/2✓ Branch 5 taken 3 times.
✓ Branch 6 taken 5 times.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 5 times.
|
8 | for (const ZXVert& box : to_decompose) { |
30 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | const ZXBox& zxb = diag.get_vertex_ZXGen<ZXBox>(box); | |
31 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
|
3 | ZXDiagram inner(*zxb.get_diagram()); | |
32 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | decompose_boxes_fun(inner); | |
33 |
2/4✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
|
3 | std::vector<std::pair<Wire, WireEnd>> sub_boundary(zxb.n_ports()); | |
34 |
3/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 7 times.
✓ Branch 9 taken 3 times.
|
0/1? Decision couldn't be analyzed.
|
10 | for (const Wire& w : diag.adj_wires(box)) { |
35 |
3/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1 times.
|
2/2✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 1 times.
|
7 | if (diag.source(w) == box) |
36 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
|
6 | sub_boundary.at(*diag.source_port(w)) = {w, WireEnd::Source}; | |
37 |
3/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 6 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 6 times.
|
7 | if (diag.target(w) == box) |
38 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
1 | sub_boundary.at(*diag.target_port(w)) = {w, WireEnd::Target}; | |
39 | 3 | } | ||
40 |
3/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
|
6 | ZXDiagram::Subdiagram sub{sub_boundary, {box}}; | |
41 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | diag.substitute(inner, sub); | |
42 | 3 | success = true; | ||
43 | 3 | } | ||
44 | 5 | return success; | ||
45 | 5 | } | ||
46 | ||||
47 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | Rewrite Rewrite::decompose_boxes() { return Rewrite(decompose_boxes_fun); } | |
48 | ||||
49 | 2 | bool Rewrite::basic_wires_fun(ZXDiagram& diag) { | ||
50 | ZXGen_ptr qhad = | |||
51 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | std::make_shared<const PhasedGen>(ZXType::Hbox, -1, QuantumType::Quantum); | |
52 | 4 | ZXGen_ptr chad = std::make_shared<const PhasedGen>( | ||
53 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | ZXType::Hbox, -1, QuantumType::Classical); | |
54 | 2 | WireVec targets; | ||
55 |
12/18✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 10 times.
✓ Branch 14 taken 2 times.
✓ Branch 16 taken 10 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 10 times.
✓ Branch 19 taken 2 times.
✓ Branch 21 taken 4 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 2 times.
✓ Branch 24 taken 2 times.
|
14 | BGL_FORALL_EDGES(w, *diag.graph, ZXGraph) { | |
56 |
4/6✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 8 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
2/2✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 6 times.
|
10 | if (diag.get_wire_type(w) == ZXWireType::H) targets.push_back(w); |
57 | } | |||
58 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 2 times.
|
4 | for (const Wire& w : targets) { |
59 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | WireProperties wp = diag.get_wire_info(w); | |
60 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | ZXGen_ptr had = (wp.qtype == QuantumType::Quantum) ? qhad : chad; | |
61 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | ZXVert h = diag.add_vertex(had); | |
62 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | ZXVert s = diag.source(w); | |
63 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | ZXVert t = diag.target(w); | |
64 | 2 | wp.type = ZXWireType::Basic; | ||
65 | 2 | WireProperties wp2 = wp; | ||
66 | 2 | wp.target_port = std::nullopt; | ||
67 | 2 | wp2.source_port = std::nullopt; | ||
68 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | diag.add_wire(s, h, wp); | |
69 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | diag.add_wire(h, t, wp); | |
70 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | diag.remove_wire(w); | |
71 | 2 | } | ||
72 | 4 | return !targets.empty(); | ||
73 | 2 | } | ||
74 | ||||
75 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | Rewrite Rewrite::basic_wires() { return Rewrite(basic_wires_fun); } | |
76 | ||||
77 | 5 | bool Rewrite::rebase_to_zx_fun(ZXDiagram& diag) { | ||
78 | 5 | ZXVertVec verts; | ||
79 |
7/8✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 60 times.
✓ Branch 7 taken 5 times.
✓ Branch 9 taken 60 times.
✓ Branch 10 taken 5 times.
✓ Branch 12 taken 5 times.
✓ Branch 13 taken 5 times.
|
70 | BGL_FORALL_VERTICES(v, *diag.graph, ZXGraph) { | |
80 |
1/2✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
|
60 | ZXType t = diag.get_zxtype(v); | |
81 |
9/12✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 18 times.
✓ Branch 6 taken 42 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 26 times.
✓ Branch 9 taken 16 times.
✓ Branch 10 taken 26 times.
✓ Branch 11 taken 34 times.
✓ Branch 13 taken 26 times.
✗ Branch 14 not taken.
|
2/2✓ Decision 'true' taken 31 times.
✓ Decision 'false' taken 29 times.
|
60 | if (!is_boundary_type(t) && !is_spider_type(t)) verts.push_back(v); |
82 | } | |||
83 |
2/2✓ Branch 5 taken 26 times.
✓ Branch 6 taken 5 times.
|
2/2✓ Decision 'true' taken 26 times.
✓ Decision 'false' taken 5 times.
|
31 | for (const ZXVert& v : verts) { |
84 |
9/11✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 16 times.
✗ Branch 11 not taken.
|
26 | switch (diag.get_zxtype(v)) { | |
85 |
0/1✗ Decision 'true' not taken.
|
4 | case ZXType::Hbox: { | |
86 | // Use a combination of the equations in doi:10.1145/3209108.3209128 and | |||
87 | // doi:10.4204/EPTCS.340.16 Iteratively decompose based on the phase, so | |||
88 | // cannot be applied to symbolic phases | |||
89 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | const PhasedGen& vg = diag.get_vertex_ZXGen<PhasedGen>(v); | |
90 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | std::optional<Complex> opt_ph = eval_expr_c(vg.get_param()); | |
91 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 4 times.
|
4 | if (!opt_ph) |
92 | ✗ | throw ZXError( | ||
93 | "Hbox with symbolic phase cannot be decomposed into ZX " | |||
94 | ✗ | "generators"); | ||
95 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | QuantumType qt = *vg.get_qtype(); | |
96 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | unsigned deg = diag.degree(v); | |
97 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | WireVec v_ws = diag.adj_wires(v); | |
98 | 4 | std::vector<std::pair<Wire, WireEnd>> v_bounds; | ||
99 | ||||
100 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | ZXDiagram rep(0, 0, 0, 0); | |
101 | 4 | double r = std::abs(*opt_ph - 1.); | ||
102 | 4 | double ph = std::arg(*opt_ph - 1.) / PI; | ||
103 | // Reduce r to the range [0, 2] | |||
104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 4 times.
|
4 | if (r < 0.) { |
105 | ✗ | r *= -1.; | ||
106 | ✗ | ph += 1.; | ||
107 | } | |||
108 | // Core is an algebraic Zbox surrounded by triangles | |||
109 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | ZXVert zph = rep.add_vertex(ZXType::ZSpider, Expr(ph), qt); | |
110 | // Not every will may have the same QuantumType in general | |||
111 | 4 | bool all_same_qt = true; | ||
112 |
3/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 11 times.
✓ Branch 9 taken 4 times.
|
0/1? Decision couldn't be analyzed.
|
15 | for (const Wire& w : diag.adj_wires(v)) { |
113 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | QuantumType wqt = diag.get_qtype(w); | |
114 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
|
1/2✓ Decision 'true' taken 11 times.
✗ Decision 'false' not taken.
|
11 | if (qt != wqt) all_same_qt = false; |
115 |
3/4✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 5 times.
|
2/2✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 5 times.
|
11 | if (diag.source(w) == v) { |
116 |
1/2✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | v_bounds.push_back({w, WireEnd::Source}); | |
117 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | ZXVert bound = rep.add_vertex(ZXType::Open, wqt); | |
118 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | rep.boundary.push_back(bound); | |
119 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | ZXVert tri = rep.add_vertex(ZXType::Triangle, wqt); | |
120 |
1/2✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 | rep.add_wire(bound, tri, ZXWireType::Basic, wqt, std::nullopt, 0); | |
121 |
1/2✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 | rep.add_wire(tri, zph, ZXWireType::Basic, wqt, 1, std::nullopt); | |
122 | } | |||
123 |
3/4✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 5 times.
|
2/2✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 5 times.
|
11 | if (diag.target(w) == v) { |
124 |
1/2✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | v_bounds.push_back({w, WireEnd::Target}); | |
125 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | ZXVert bound = rep.add_vertex(ZXType::Open, wqt); | |
126 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | rep.boundary.push_back(bound); | |
127 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | ZXVert tri = rep.add_vertex(ZXType::Triangle, wqt); | |
128 |
1/2✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 | rep.add_wire(bound, tri, ZXWireType::Basic, wqt, std::nullopt, 0); | |
129 |
1/2✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 | rep.add_wire(tri, zph, ZXWireType::Basic, wqt, 1, std::nullopt); | |
130 | } | |||
131 | 4 | } | ||
132 | // Special cases for degree 2 | |||
133 |
5/8✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 4 times.
|
6 | if (deg == 2 && all_same_qt && approx_eq(opt_ph->real(), -1.) && |
134 |
7/12✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
6 | approx_0(opt_ph->imag())) { | |
135 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | WireVec ws = diag.adj_wires(v); | |
136 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 2 times.
|
2 | if (ws.size() == 1) { |
137 | // self-loop | |||
138 | ✗ | diag.multiply_scalar(0.); | ||
139 | } else { | |||
140 | // Replace with a Hadamard edge | |||
141 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | ZXVert s = diag.other_end(ws.at(0), v); | |
142 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | ZXVert t = diag.other_end(ws.at(1), v); | |
143 | 2 | unsigned n_hs = 0; | ||
144 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
|
1/2✓ Decision 'true' taken 2 times.
✗ Decision 'false' not taken.
|
2 | if (diag.get_wire_type(ws.at(0)) == ZXWireType::H) ++n_hs; |
145 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
|
0/1? Decision couldn't be analyzed.
|
2 | if (diag.get_wire_type(ws.at(1)) == ZXWireType::H) ++n_hs; |
146 | 4 | diag.add_wire( | ||
147 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | s, t, (n_hs == 1) ? ZXWireType::Basic : ZXWireType::H, qt); | |
148 | } | |||
149 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | diag.remove_vertex(v); | |
150 | 2 | break; | ||
151 | 2 | } | ||
152 | // Using the algebraic fusion rule, can break off 2-boxes (0-phase | |||
153 | // ZSpider and a triangle) | |||
154 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
2/2✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 2 times.
|
8 | for (; r > 2.; r -= 1) { |
155 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | ZXVert tri = rep.add_vertex(ZXType::Triangle, qt); | |
156 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | ZXVert one = rep.add_vertex(ZXType::ZSpider, qt); | |
157 |
1/2✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 | rep.add_wire(zph, tri, ZXWireType::Basic, qt, std::nullopt, 0); | |
158 |
1/2✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 | rep.add_wire(tri, one, ZXWireType::Basic, qt, 1, std::nullopt); | |
159 | } | |||
160 | // Identify alpha s.t. r = e^{i*pi*alpha} + e^{-i*pi*alpha} = | |||
161 | // 2*cos(alpha) and implement the algebraic Zbox | |||
162 | 2 | double alpha = std::acos(r / 2.); | ||
163 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | ZXVert tri = rep.add_vertex(ZXType::Triangle, qt); | |
164 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | ZXVert negal = rep.add_vertex(ZXType::ZSpider, Expr(-alpha), qt); | |
165 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | ZXVert xmerge = rep.add_vertex(ZXType::XSpider, qt); | |
166 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | ZXVert al = rep.add_vertex(ZXType::ZSpider, Expr(alpha), qt); | |
167 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
2 | rep.add_wire(zph, tri, ZXWireType::Basic, qt, std::nullopt, 0); | |
168 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
2 | rep.add_wire(tri, negal, ZXWireType::Basic, qt, 1, std::nullopt); | |
169 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
2 | rep.add_wire(zph, xmerge, ZXWireType::Basic, qt); | |
170 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
2 | rep.add_wire(negal, xmerge, ZXWireType::Basic, qt); | |
171 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
2 | rep.add_wire(xmerge, al, ZXWireType::Basic, qt); | |
172 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | rep.multiply_scalar( | |
173 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
6 | (qt == QuantumType::Quantum) ? Expr(2.) | |
174 |
4/12✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
|
4 | : Expr(SymEngine::sqrt(Expr(2.)))); | |
175 | ||||
176 | // Decompose triangles | |||
177 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | rebase_to_zx_fun(rep); | |
178 | ||||
179 | // Substitute | |||
180 |
3/6✓ 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.
|
4 | ZXDiagram::Subdiagram sub{v_bounds, {v}}; | |
181 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | diag.substitute(rep, sub); | |
182 | 2 | break; | ||
183 | 4 | } | ||
184 |
1/1✓ Decision 'true' taken 1 times.
|
1 | case ZXType::XY: { | |
185 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ZXGen_ptr vgen = diag.get_vertex_ZXGen_ptr(v); | |
186 | 1 | const PhasedGen& vg = static_cast<const PhasedGen&>(*vgen); | ||
187 | ZXGen_ptr new_gen = ZXGen::create_gen( | |||
188 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
|
2 | ZXType::ZSpider, -vg.get_param(), *vg.get_qtype()); | |
189 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | diag.set_vertex_ZXGen_ptr(v, new_gen); | |
190 | 1 | break; | ||
191 | 1 | } | ||
192 |
1/1✓ Decision 'true' taken 1 times.
|
1 | case ZXType::XZ: { | |
193 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ZXGen_ptr vgen = diag.get_vertex_ZXGen_ptr(v); | |
194 | 1 | const PhasedGen& vg = static_cast<const PhasedGen&>(*vgen); | ||
195 | ZXVert phase_v = | |||
196 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
1 | diag.add_vertex(ZXType::XSpider, vg.get_param(), *vg.get_qtype()); | |
197 | ZXGen_ptr new_gen = | |||
198 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
1 | ZXGen::create_gen(ZXType::ZSpider, Expr(0.5), *vg.get_qtype()); | |
199 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | diag.set_vertex_ZXGen_ptr(v, new_gen); | |
200 |
2/4✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | diag.add_wire(v, phase_v, ZXWireType::Basic, *vg.get_qtype()); | |
201 | 1 | break; | ||
202 | 1 | } | ||
203 |
1/1✓ Decision 'true' taken 1 times.
|
1 | case ZXType::YZ: { | |
204 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ZXGen_ptr vgen = diag.get_vertex_ZXGen_ptr(v); | |
205 | 1 | const PhasedGen& vg = static_cast<const PhasedGen&>(*vgen); | ||
206 | ZXVert phase_v = | |||
207 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
1 | diag.add_vertex(ZXType::XSpider, vg.get_param(), *vg.get_qtype()); | |
208 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | ZXGen_ptr new_gen = ZXGen::create_gen(ZXType::ZSpider, *vg.get_qtype()); | |
209 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | diag.set_vertex_ZXGen_ptr(v, new_gen); | |
210 |
2/4✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | diag.add_wire(v, phase_v, ZXWireType::Basic, *vg.get_qtype()); | |
211 | 1 | break; | ||
212 | 1 | } | ||
213 |
1/1✓ Decision 'true' taken 1 times.
|
1 | case ZXType::PX: { | |
214 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ZXGen_ptr vgen = diag.get_vertex_ZXGen_ptr(v); | |
215 | 1 | const CliffordGen& vg = static_cast<const CliffordGen&>(*vgen); | ||
216 | ZXGen_ptr new_gen = ZXGen::create_gen( | |||
217 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
1 | ZXType::ZSpider, vg.get_param() ? Expr(1.) : Expr(0.), | |
218 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
2 | *vg.get_qtype()); | |
219 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | diag.set_vertex_ZXGen_ptr(v, new_gen); | |
220 | 1 | break; | ||
221 | 1 | } | ||
222 |
1/1✓ Decision 'true' taken 1 times.
|
1 | case ZXType::PY: { | |
223 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ZXGen_ptr vgen = diag.get_vertex_ZXGen_ptr(v); | |
224 | 1 | const CliffordGen& vg = static_cast<const CliffordGen&>(*vgen); | ||
225 | ZXGen_ptr new_gen = ZXGen::create_gen( | |||
226 |
2/6✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
1 | ZXType::ZSpider, vg.get_param() ? Expr(0.5) : Expr(-0.5), | |
227 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
2 | *vg.get_qtype()); | |
228 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | diag.set_vertex_ZXGen_ptr(v, new_gen); | |
229 | 1 | break; | ||
230 | 1 | } | ||
231 |
1/1✓ Decision 'true' taken 1 times.
|
1 | case ZXType::PZ: { | |
232 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ZXGen_ptr vgen = diag.get_vertex_ZXGen_ptr(v); | |
233 | 1 | const CliffordGen& vg = static_cast<const CliffordGen&>(*vgen); | ||
234 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ZXVert phase_v = diag.add_vertex( | |
235 |
3/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
1 | ZXType::XSpider, vg.get_param() ? Expr(1.) : Expr(0.), | |
236 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | *vg.get_qtype()); | |
237 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | ZXGen_ptr new_gen = ZXGen::create_gen(ZXType::ZSpider, *vg.get_qtype()); | |
238 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | diag.set_vertex_ZXGen_ptr(v, new_gen); | |
239 |
2/4✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | diag.add_wire(v, phase_v, ZXWireType::Basic, *vg.get_qtype()); | |
240 | 1 | break; | ||
241 | 1 | } | ||
242 |
0/1✗ Decision 'true' not taken.
|
16 | case ZXType::Triangle: { | |
243 | // Decomposition of the triangle given in Lemma 3.3, "Completeness of | |||
244 | // the ZX-calculus for Pure Qubit Clifford+T Quantum Mechanics", K. Feng | |||
245 | // Ng, Q. Wang, 2018 | |||
246 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ZXDiagram tri(0, 0, 0, 0); | |
247 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | QuantumType qt = *diag.get_qtype(v); | |
248 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ZXVert in = tri.add_vertex(ZXType::Input, qt); | |
249 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | tri.boundary.push_back(in); | |
250 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ZXVert out = tri.add_vertex(ZXType::Output, qt); | |
251 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | tri.boundary.push_back(out); | |
252 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | tri.multiply_scalar( | |
253 |
4/6✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
|
44 | (qt == QuantumType::Quantum) ? Expr(2.) | |
254 |
6/12✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✓ Branch 8 taken 4 times.
✓ Branch 10 taken 12 times.
✓ Branch 11 taken 4 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
|
28 | : Expr(SymEngine::sqrt(Expr(2.)))); | |
255 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ZXVert split = tri.add_vertex(ZXType::XSpider, qt); | |
256 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
|
16 | ZXVert lrz = tri.add_vertex(ZXType::ZSpider, -0.25, qt); | |
257 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
|
16 | ZXVert rrz = tri.add_vertex(ZXType::ZSpider, 0.25, qt); | |
258 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ZXVert laxis = tri.add_vertex(ZXType::XSpider, qt); | |
259 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ZXVert raxis = tri.add_vertex(ZXType::XSpider, qt); | |
260 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
|
16 | ZXVert lph = tri.add_vertex(ZXType::ZSpider, -0.25, qt); | |
261 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
|
16 | ZXVert rph = tri.add_vertex(ZXType::ZSpider, 0.25, qt); | |
262 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ZXVert merge = tri.add_vertex(ZXType::ZSpider, qt); | |
263 | // Flat of the triangle is the output/port 1 | |||
264 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | tri.add_wire(out, split, ZXWireType::Basic, qt); | |
265 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | tri.add_wire(split, lrz, ZXWireType::Basic, qt); | |
266 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | tri.add_wire(split, rrz, ZXWireType::Basic, qt); | |
267 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | tri.add_wire(lrz, laxis, ZXWireType::Basic, qt); | |
268 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | tri.add_wire(rrz, raxis, ZXWireType::Basic, qt); | |
269 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | tri.add_wire(laxis, lph, ZXWireType::Basic, qt); | |
270 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | tri.add_wire(raxis, rph, ZXWireType::Basic, qt); | |
271 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | tri.add_wire(laxis, merge, ZXWireType::Basic, qt); | |
272 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | tri.add_wire(raxis, merge, ZXWireType::Basic, qt); | |
273 | // Point of the triangle is the input/port 0 | |||
274 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | tri.add_wire(merge, in, ZXWireType::Basic, qt); | |
275 | ||||
276 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | Wire w0 = diag.wire_at_port(v, 0); | |
277 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | Wire w1 = diag.wire_at_port(v, 1); | |
278 | WireEnd we0, we1; | |||
279 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 16 times.
|
16 | if (w0 == w1) { |
280 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | if (diag.source_port(w0) == 0) { | |
281 | ✗ | we0 = WireEnd::Source; | ||
282 | ✗ | we1 = WireEnd::Target; | ||
283 | } else { | |||
284 | ✗ | we0 = WireEnd::Target; | ||
285 | ✗ | we1 = WireEnd::Source; | ||
286 | } | |||
287 | } else { | |||
288 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | we0 = diag.end_of(w0, v); | |
289 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | we1 = diag.end_of(w1, v); | |
290 | } | |||
291 |
4/8✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 16 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 16 times.
✗ Branch 15 not taken.
|
32 | ZXDiagram::Subdiagram sub{{{w0, we0}, {w1, we1}}, {v}}; | |
292 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | diag.substitute(tri, sub); | |
293 | 16 | break; | ||
294 | 16 | } | ||
295 |
0/1✗ Decision 'true' not taken.
|
✗ | default: | |
296 | ✗ | break; | ||
297 | } | |||
298 | } | |||
299 | 10 | return !verts.empty(); | ||
300 | 5 | } | ||
301 | ||||
302 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | Rewrite Rewrite::rebase_to_zx() { return Rewrite(rebase_to_zx_fun); } | |
303 | ||||
304 | 3 | bool Rewrite::rebase_to_mbqc_fun(ZXDiagram& diag) { | ||
305 | 3 | ZXVertVec verts; | ||
306 |
7/8✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 91 times.
✓ Branch 7 taken 3 times.
✓ Branch 9 taken 91 times.
✓ Branch 10 taken 3 times.
✓ Branch 12 taken 3 times.
✓ Branch 13 taken 3 times.
|
97 | BGL_FORALL_VERTICES(v, *diag.graph, ZXGraph) { | |
307 |
1/2✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
|
91 | ZXType t = diag.get_zxtype(v); | |
308 |
9/12✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
✓ Branch 4 taken 10 times.
✓ Branch 6 taken 81 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 75 times.
✓ Branch 9 taken 6 times.
✓ Branch 10 taken 75 times.
✓ Branch 11 taken 16 times.
✓ Branch 13 taken 75 times.
✗ Branch 14 not taken.
|
2/2✓ Decision 'true' taken 78 times.
✓ Decision 'false' taken 13 times.
|
91 | if (!is_boundary_type(t) && !is_MBQC_type(t)) verts.push_back(v); |
309 | } | |||
310 |
2/2✓ Branch 5 taken 75 times.
✓ Branch 6 taken 3 times.
|
2/2✓ Decision 'true' taken 75 times.
✓ Decision 'false' taken 3 times.
|
78 | for (const ZXVert& v : verts) { |
311 |
4/7✓ Branch 1 taken 75 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 47 times.
✓ Branch 4 taken 26 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
75 | switch (diag.get_zxtype(v)) { | |
312 |
1/1✓ Decision 'true' taken 47 times.
|
47 | case ZXType::ZSpider: { | |
313 |
1/2✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
|
47 | ZXGen_ptr vgen = diag.get_vertex_ZXGen_ptr(v); | |
314 | 47 | const PhasedGen& vg = static_cast<const PhasedGen&>(*vgen); | ||
315 | ZXGen_ptr new_gen = | |||
316 |
4/8✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 47 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 47 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 47 times.
✗ Branch 12 not taken.
|
94 | ZXGen::create_gen(ZXType::XY, -vg.get_param(), *vg.get_qtype()); | |
317 |
1/2✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
|
47 | diag.set_vertex_ZXGen_ptr(v, new_gen); | |
318 | 47 | break; | ||
319 | 47 | } | ||
320 |
1/1✓ Decision 'true' taken 26 times.
|
26 | case ZXType::XSpider: { | |
321 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | ZXGen_ptr vgen = diag.get_vertex_ZXGen_ptr(v); | |
322 | 26 | const PhasedGen& vg = static_cast<const PhasedGen&>(*vgen); | ||
323 | ZXGen_ptr new_gen = | |||
324 |
4/8✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 26 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 26 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 26 times.
✗ Branch 12 not taken.
|
52 | ZXGen::create_gen(ZXType::XY, -vg.get_param(), *vg.get_qtype()); | |
325 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | diag.set_vertex_ZXGen_ptr(v, new_gen); | |
326 |
3/4✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 77 times.
✓ Branch 9 taken 26 times.
|
0/1? Decision couldn't be analyzed.
|
103 | for (const Wire& w : diag.adj_wires(v)) { |
327 |
1/2✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
|
77 | ZXWireType wt = diag.get_wire_type(w); | |
328 |
2/4✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 77 times.
✗ Branch 4 not taken.
|
77 | diag.set_wire_type( | |
329 | w, (wt == ZXWireType::Basic) ? ZXWireType::H : ZXWireType::Basic); | |||
330 | 26 | } | ||
331 | 26 | break; | ||
332 | 26 | } | ||
333 |
1/1✓ Decision 'true' taken 2 times.
|
2 | case ZXType::Hbox: { | |
334 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | WireVec v_ws = diag.adj_wires(v); | |
335 | 2 | std::vector<std::pair<Wire, WireEnd>> v_bounds; | ||
336 |
2/2✓ Branch 5 taken 5 times.
✓ Branch 6 taken 2 times.
|
2/2✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 2 times.
|
7 | for (const Wire& w : v_ws) { |
337 |
4/6✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
|
1/2✓ Decision 'true' taken 5 times.
✗ Decision 'false' not taken.
|
5 | if (diag.source(w) == v) v_bounds.push_back({w, WireEnd::Source}); |
338 |
4/6✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
|
2/2✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 1 times.
|
5 | if (diag.target(w) == v) v_bounds.push_back({w, WireEnd::Target}); |
339 | } | |||
340 |
3/6✓ 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.
|
4 | ZXDiagram::Subdiagram sub{v_bounds, {v}}; | |
341 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | ZXDiagram h = sub.to_diagram(diag); | |
342 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | rebase_to_zx_fun(h); | |
343 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | rebase_to_mbqc_fun(h); | |
344 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | diag.substitute(h, sub); | |
345 | 2 | break; | ||
346 | 2 | } | ||
347 |
0/1✗ Decision 'true' not taken.
|
✗ | case ZXType::Triangle: { | |
348 | ✗ | Wire w0 = diag.wire_at_port(v, 0); | ||
349 | ✗ | Wire w1 = diag.wire_at_port(v, 1); | ||
350 | WireEnd we0, we1; | |||
351 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | if (w0 == w1) { | |
352 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | if (diag.source_port(w0) == 0) { | |
353 | ✗ | we0 = WireEnd::Source; | ||
354 | ✗ | we1 = WireEnd::Target; | ||
355 | } else { | |||
356 | ✗ | we0 = WireEnd::Target; | ||
357 | ✗ | we1 = WireEnd::Source; | ||
358 | } | |||
359 | } else { | |||
360 | ✗ | we0 = diag.end_of(w0, v); | ||
361 | ✗ | we1 = diag.end_of(w1, v); | ||
362 | } | |||
363 | ✗ | ZXDiagram::Subdiagram sub{{{w0, we0}, {w1, we1}}, {v}}; | ||
364 | ✗ | ZXDiagram tri = sub.to_diagram(diag); | ||
365 | ✗ | rebase_to_zx_fun(tri); | ||
366 | ✗ | rebase_to_mbqc_fun(tri); | ||
367 | ✗ | diag.substitute(tri, sub); | ||
368 | ✗ | break; | ||
369 | } | |||
370 |
0/1✗ Decision 'true' not taken.
|
✗ | default: | |
371 | ✗ | break; | ||
372 | } | |||
373 | } | |||
374 | 6 | return !verts.empty(); | ||
375 | 3 | } | ||
376 | ||||
377 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | Rewrite Rewrite::rebase_to_mbqc() { return Rewrite(rebase_to_mbqc_fun); } | |
378 | ||||
379 | } // namespace zx | |||
380 | ||||
381 | } // namespace tket | |||
382 |