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 "DAGProperties.hpp" | |||
16 | ||||
17 | #include <algorithm> | |||
18 | #include <tklog/TketLog.hpp> | |||
19 | ||||
20 | #include "OpType/EdgeType.hpp" | |||
21 | #include "Utils/GraphHeaders.hpp" | |||
22 | ||||
23 | namespace tket { | |||
24 | ||||
25 | #ifdef CHECK | |||
26 | #error "Macro already defined!" | |||
27 | #endif | |||
28 | #define CHECK(p) \ | |||
29 | do { \ | |||
30 | if (!(p)) { \ | |||
31 | tket_log()->warn("Invalid DAG: check (" #p ") failed."); \ | |||
32 | return false; \ | |||
33 | } \ | |||
34 | } while (0) | |||
35 | ||||
36 | enum class VertexType { Quantum, Classical, Measure }; | |||
37 | ||||
38 | 57 | bool is_valid(const DAG &G) { | ||
39 |
7/8✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 799 times.
✓ Branch 6 taken 57 times.
✓ Branch 8 taken 799 times.
✓ Branch 9 taken 57 times.
✓ Branch 11 taken 57 times.
✓ Branch 12 taken 57 times.
|
913 | BGL_FORALL_VERTICES(v, G, DAG) { | |
40 | 799 | EdgeSet q_in, c_in, b_in; | ||
41 |
12/18✓ Branch 1 taken 799 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 596 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 809 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1405 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 809 times.
✓ Branch 13 taken 596 times.
✓ Branch 15 taken 809 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 809 times.
✓ Branch 18 taken 596 times.
✓ Branch 20 taken 1395 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 596 times.
✓ Branch 23 taken 799 times.
|
2204 | BGL_FORALL_INEDGES(v, e, G, DAG) { | |
42 |
4/6✓ Branch 1 taken 809 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 658 times.
✓ Branch 4 taken 92 times.
✓ Branch 5 taken 59 times.
✗ Branch 6 not taken.
|
809 | switch (G[e].type) { | |
43 |
1/1✓ Decision 'true' taken 658 times.
|
658 | case EdgeType::Quantum: | |
44 |
1/2✓ Branch 1 taken 658 times.
✗ Branch 2 not taken.
|
658 | q_in.insert(e); | |
45 | 658 | break; | ||
46 |
1/1✓ Decision 'true' taken 92 times.
|
92 | case EdgeType::Classical: | |
47 |
1/2✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
|
92 | c_in.insert(e); | |
48 | 92 | break; | ||
49 |
1/1✓ Decision 'true' taken 59 times.
|
59 | case EdgeType::Boolean: | |
50 |
1/2✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
|
59 | b_in.insert(e); | |
51 | 59 | break; | ||
52 |
0/1✗ Decision 'true' not taken.
|
✗ | default: | |
53 | ✗ | CHECK(!"unknown edge type"); | ||
54 | } | |||
55 | } | |||
56 | 799 | EdgeSet q_out, c_out, b_out; | ||
57 |
12/18✓ Branch 1 taken 799 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 596 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 809 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1405 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 809 times.
✓ Branch 13 taken 596 times.
✓ Branch 15 taken 809 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 809 times.
✓ Branch 18 taken 596 times.
✓ Branch 20 taken 1395 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 596 times.
✓ Branch 23 taken 799 times.
|
2204 | BGL_FORALL_OUTEDGES(v, e, G, DAG) { | |
58 |
4/6✓ Branch 1 taken 809 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 658 times.
✓ Branch 4 taken 92 times.
✓ Branch 5 taken 59 times.
✗ Branch 6 not taken.
|
809 | switch (G[e].type) { | |
59 |
1/1✓ Decision 'true' taken 658 times.
|
658 | case EdgeType::Quantum: | |
60 |
1/2✓ Branch 1 taken 658 times.
✗ Branch 2 not taken.
|
658 | q_out.insert(e); | |
61 | 658 | break; | ||
62 |
1/1✓ Decision 'true' taken 92 times.
|
92 | case EdgeType::Classical: | |
63 |
1/2✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
|
92 | c_out.insert(e); | |
64 | 92 | break; | ||
65 |
1/1✓ Decision 'true' taken 59 times.
|
59 | case EdgeType::Boolean: | |
66 |
1/2✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
|
59 | b_out.insert(e); | |
67 | 59 | break; | ||
68 |
0/1✗ Decision 'true' not taken.
|
✗ | default: | |
69 | ✗ | CHECK(!"unknown edge type"); | ||
70 | } | |||
71 | } | |||
72 | 799 | std::set<port_t> in_ports, q_in_ports, q_out_ports, c_in_ports, c_out_ports, | ||
73 | 799 | b_in_ports; | ||
74 |
2/2✓ Branch 5 taken 658 times.
✓ Branch 6 taken 799 times.
|
2/2✓ Decision 'true' taken 658 times.
✓ Decision 'false' taken 799 times.
|
1457 | for (const auto &e : q_in) { |
75 |
1/2✓ Branch 1 taken 658 times.
✗ Branch 2 not taken.
|
658 | port_t p = G[e].ports.second; | |
76 |
1/2✓ Branch 1 taken 658 times.
✗ Branch 2 not taken.
|
658 | in_ports.insert(p); | |
77 |
1/2✓ Branch 1 taken 658 times.
✗ Branch 2 not taken.
|
658 | q_in_ports.insert(p); | |
78 | } | |||
79 |
2/2✓ Branch 5 taken 658 times.
✓ Branch 6 taken 799 times.
|
2/2✓ Decision 'true' taken 658 times.
✓ Decision 'false' taken 799 times.
|
1457 | for (const auto &e : q_out) { |
80 |
2/4✓ Branch 1 taken 658 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 658 times.
✗ Branch 5 not taken.
|
658 | q_out_ports.insert(G[e].ports.first); | |
81 | } | |||
82 |
2/2✓ Branch 5 taken 92 times.
✓ Branch 6 taken 799 times.
|
2/2✓ Decision 'true' taken 92 times.
✓ Decision 'false' taken 799 times.
|
891 | for (const auto &e : c_in) { |
83 |
1/2✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
|
92 | port_t p = G[e].ports.second; | |
84 |
1/2✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
|
92 | in_ports.insert(p); | |
85 |
1/2✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
|
92 | c_in_ports.insert(p); | |
86 | } | |||
87 |
2/2✓ Branch 5 taken 92 times.
✓ Branch 6 taken 799 times.
|
2/2✓ Decision 'true' taken 92 times.
✓ Decision 'false' taken 799 times.
|
891 | for (const auto &e : c_out) { |
88 |
2/4✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 92 times.
✗ Branch 5 not taken.
|
92 | c_out_ports.insert(G[e].ports.first); | |
89 | } | |||
90 |
2/2✓ Branch 5 taken 59 times.
✓ Branch 6 taken 799 times.
|
2/2✓ Decision 'true' taken 59 times.
✓ Decision 'false' taken 799 times.
|
858 | for (const auto &e : b_in) { |
91 |
1/2✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
|
59 | port_t p = G[e].ports.second; | |
92 |
1/2✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
|
59 | in_ports.insert(p); | |
93 |
1/2✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
|
59 | b_in_ports.insert(p); | |
94 | } | |||
95 | ||||
96 | // Now check the required properties. | |||
97 | ||||
98 |
1/8✗ Branch 4 not taken.
✓ Branch 5 taken 799 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
799 | CHECK( | |
99 | in_ports.size() == | |||
100 | q_in_ports.size() + c_in_ports.size() + b_in_ports.size()); | |||
101 | ||||
102 | // Every Boolean out port matches a Classical out port. | |||
103 |
2/2✓ Branch 5 taken 59 times.
✓ Branch 6 taken 799 times.
|
2/2✓ Decision 'true' taken 59 times.
✓ Decision 'false' taken 799 times.
|
858 | for (const Edge &e : b_out) { |
104 |
1/2✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
|
59 | port_t p = G[e].ports.first; | |
105 |
2/10✓ Branch 3 taken 59 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 59 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
|
121 | CHECK(std::any_of(c_out.cbegin(), c_out.cend(), [&](const Edge &f) { | |
106 | return G[f].ports.first == p; | |||
107 | })); | |||
108 | } | |||
109 | ||||
110 |
6/6✓ Branch 1 taken 715 times.
✓ Branch 2 taken 84 times.
✓ Branch 4 taken 668 times.
✓ Branch 5 taken 47 times.
✓ Branch 6 taken 668 times.
✓ Branch 7 taken 131 times.
|
2/2✓ Decision 'true' taken 668 times.
✓ Decision 'false' taken 131 times.
|
799 | if (c_in.empty() && c_out.empty()) { |
111 | // It is a Quantum vertex. | |||
112 | 668 | unsigned in_deg = q_in.size(); | ||
113 | 668 | unsigned out_deg = q_out.size(); | ||
114 |
1/8✗ Branch 1 not taken.
✓ Branch 2 taken 668 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
668 | CHECK(q_in_ports.size() == in_deg); | |
115 |
1/8✗ Branch 1 not taken.
✓ Branch 2 taken 668 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
668 | CHECK(q_out_ports.size() == out_deg); | |
116 |
10/20✓ Branch 0 taken 156 times.
✓ Branch 1 taken 512 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 156 times.
✓ Branch 4 taken 391 times.
✓ Branch 5 taken 121 times.
✓ Branch 6 taken 235 times.
✓ Branch 7 taken 156 times.
✓ Branch 9 taken 356 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 356 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 668 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
|
668 | CHECK( | |
117 | (in_deg == 0 && out_deg == 1) || (in_deg == 1 && out_deg == 0) || | |||
118 | (q_in_ports == q_out_ports)); // bijection between in and out ports | |||
119 |
1/8✗ Branch 1 not taken.
✓ Branch 2 taken 668 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
668 | CHECK(b_out.empty()); | |
120 |
5/6✓ Branch 1 taken 110 times.
✓ Branch 2 taken 21 times.
✓ Branch 4 taken 110 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 110 times.
✓ Branch 7 taken 21 times.
|
2/2✓ Decision 'true' taken 110 times.
✓ Decision 'false' taken 21 times.
|
131 | } else if (q_in.empty() && q_out.empty()) { |
121 | // It is a Classical vertex. | |||
122 | 110 | unsigned in_deg = c_in.size(); | ||
123 | 110 | unsigned out_deg = c_out.size(); | ||
124 |
1/8✗ Branch 1 not taken.
✓ Branch 2 taken 110 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
110 | CHECK(c_in_ports.size() == in_deg); | |
125 |
1/8✗ Branch 1 not taken.
✓ Branch 2 taken 110 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
110 | CHECK(c_out_ports.size() == out_deg); | |
126 |
10/20✓ Branch 0 taken 47 times.
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 47 times.
✓ Branch 4 taken 58 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 47 times.
✓ Branch 9 taken 16 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 16 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 110 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
|
110 | CHECK( | |
127 | (in_deg == 0 && out_deg == 1) || (in_deg == 1 && out_deg == 0) || | |||
128 | (c_in_ports == c_out_ports)); // bijection between in and out ports | |||
129 | } else { | |||
130 | // Check that it is a Measure vertex. | |||
131 |
5/16✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 21 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 21 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 21 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
|
21 | CHECK( | |
132 | q_in.size() == 1 && q_out.size() == 1 && c_in.size() == 1 && | |||
133 | c_out.size() == 1); | |||
134 |
5/16✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 21 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 21 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
21 | CHECK(q_in_ports == q_out_ports && c_in_ports == c_out_ports); | |
135 | } | |||
136 |
3/6✓ Branch 1 taken 799 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 799 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 799 times.
✗ Branch 8 not taken.
|
799 | } | |
137 | 57 | return true; | ||
138 | } | |||
139 | ||||
140 | #undef CHECK | |||
141 | ||||
142 | } // namespace tket | |||
143 |