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 "ZX/Rewrite.hpp" | |||
16 | ||||
17 | namespace tket { | |||
18 | ||||
19 | namespace zx { | |||
20 | ||||
21 | 3 | bool Rewrite::separate_boundaries_fun(ZXDiagram& diag) { | ||
22 | 3 | bool success = false; | ||
23 |
3/4✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 10 taken 18 times.
✓ Branch 11 taken 3 times.
|
0/1? Decision couldn't be analyzed.
|
21 | for (const ZXVert& b : diag.get_boundary()) { |
24 | // Boundaries in valid diagrams have degree 1 | |||
25 |
2/4✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
|
18 | Wire w = diag.adj_wires(b).at(0); | |
26 | // Since degree is 1, o is distinct from b | |||
27 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | ZXVert o = diag.other_end(w, b); | |
28 | // Other end of the wire needs to either be a boundary type or connected to | |||
29 | // another boundary | |||
30 |
4/6✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✓ Branch 7 taken 1 times.
|
2/2✓ Decision 'true' taken 17 times.
✓ Decision 'false' taken 1 times.
|
18 | if (!is_boundary_type(diag.get_zxtype(o))) { |
31 | 17 | bool o_shared = false; | ||
32 |
3/4✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 40 times.
✓ Branch 9 taken 17 times.
|
0/1? Decision couldn't be analyzed.
|
57 | for (const ZXVert& n : diag.neighbours(o)) { |
33 |
6/10✓ Branch 0 taken 23 times.
✓ Branch 1 taken 17 times.
✓ Branch 3 taken 23 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 23 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 23 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 40 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 40 times.
|
40 | if (n != b && is_boundary_type(diag.get_zxtype(n))) { |
34 | ✗ | o_shared = true; | ||
35 | ✗ | break; | ||
36 | } | |||
37 | 17 | } | ||
38 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 16 times.
|
17 | if (!o_shared) continue; |
39 | } | |||
40 | // New wires will inherit `w`'s `qtype` | |||
41 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | QuantumType wq = diag.get_qtype(w); | |
42 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ZXGen_ptr id = std::make_shared<const PhasedGen>(ZXType::ZSpider, 0., wq); | |
43 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | ZXVert z_at_b = diag.add_vertex(id); | |
44 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1 | diag.add_wire(b, z_at_b, ZXWireType::Basic, wq); | |
45 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | ZXVert z_at_o = diag.add_vertex(id); | |
46 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1 | diag.add_wire(o, z_at_o, ZXWireType::Basic, wq); | |
47 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1/2✓ Decision 'true' taken 1 times.
✗ Decision 'false' not taken.
|
1 | if (diag.get_wire_type(w) == ZXWireType::Basic) { |
48 | // Basic requires two Hadamard edges | |||
49 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | ZXVert middle = diag.add_vertex(id); | |
50 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1 | diag.add_wire(z_at_b, middle, ZXWireType::H, wq); | |
51 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1 | diag.add_wire(z_at_o, middle, ZXWireType::H, wq); | |
52 | } else { | |||
53 | // Hadamard edge | |||
54 | ✗ | diag.add_wire(z_at_b, z_at_o, ZXWireType::H, wq); | ||
55 | } | |||
56 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | diag.remove_wire(w); | |
57 | 1 | success = true; | ||
58 | 4 | } | ||
59 | 3 | return success; | ||
60 | } | |||
61 | ||||
62 | 3 | Rewrite Rewrite::separate_boundaries() { | ||
63 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | return Rewrite(separate_boundaries_fun); | |
64 | } | |||
65 | ||||
66 | 4 | bool Rewrite::io_extension_fun(ZXDiagram& diag) { | ||
67 | 4 | bool success = false; | ||
68 |
3/4✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 10 taken 21 times.
✓ Branch 11 taken 4 times.
|
0/1? Decision couldn't be analyzed.
|
25 | for (const ZXVert& b : diag.get_boundary()) { |
69 | // Boundaries in valid diagrams have degree 1 | |||
70 |
2/4✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
|
21 | Wire w = diag.adj_wires(b).at(0); | |
71 |
1/2✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
|
21 | WireProperties wp = diag.get_wire_info(w); | |
72 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 10 times.
|
2/2✓ Decision 'true' taken 10 times.
✓ Decision 'false' taken 11 times.
|
21 | if (wp.type == ZXWireType::Basic) continue; |
73 | // Extend by an identity spider | |||
74 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | ZXVert u = diag.other_end(w, b); | |
75 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | ZXVert z = diag.add_vertex(ZXType::ZSpider, 0., wp.qtype); | |
76 | // `u` might be directed, so preserve ports by preserving direction | |||
77 |
3/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 4 times.
|
2/2✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 4 times.
|
10 | if (diag.end_of(w, u) == WireEnd::Source) |
78 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | diag.add_wire(u, z, wp); | |
79 | else | |||
80 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | diag.add_wire(z, u, wp); | |
81 |
1/2✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
|
10 | diag.add_wire(b, z, ZXWireType::Basic, wp.qtype); | |
82 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | diag.remove_wire(w); | |
83 | 10 | success = true; | ||
84 | 4 | } | ||
85 | 4 | return success; | ||
86 | } | |||
87 | ||||
88 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | Rewrite Rewrite::io_extension() { return Rewrite(io_extension_fun); } | |
89 | ||||
90 | } // namespace zx | |||
91 | ||||
92 | } // namespace tket | |||
93 |