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 "ColouringPriority.hpp" | |||
16 | ||||
17 | #include <sstream> | |||
18 | #include <stdexcept> | |||
19 | #include <tkassert/Assert.hpp> | |||
20 | ||||
21 | #include "AdjacencyData.hpp" | |||
22 | ||||
23 | using std::map; | |||
24 | using std::set; | |||
25 | using std::size_t; | |||
26 | using std::string; | |||
27 | using std::vector; | |||
28 | ||||
29 | namespace tket { | |||
30 | namespace graphs { | |||
31 | ||||
32 | 302476 | static void fill_initial_node_sequence( | ||
33 | ColouringPriority::Nodes& nodes, const AdjacencyData& adjacency_data, | |||
34 | const set<size_t>& vertices_in_component, | |||
35 | const set<size_t>& initial_clique) { | |||
36 | 302476 | nodes.reserve(vertices_in_component.size()); | ||
37 | 302476 | nodes.clear(); | ||
38 | ||||
39 | try { | |||
40 |
2/2✓ Branch 4 taken 336746 times.
✓ Branch 5 taken 302476 times.
|
2/2✓ Decision 'true' taken 336746 times.
✓ Decision 'false' taken 302476 times.
|
639222 | for (size_t clique_vertex : initial_clique) { |
41 | // GCOVR_EXCL_START | |||
42 | if (vertices_in_component.count(clique_vertex) == 0) { | |||
43 | std::stringstream ss; | |||
44 | ss << "initial clique vertex " << clique_vertex | |||
45 | << " is not in this component"; | |||
46 | throw std::runtime_error(ss.str()); | |||
47 | } | |||
48 | // GCOVR_EXCL_STOP | |||
49 |
1/2✓ Branch 1 taken 336746 times.
✗ Branch 2 not taken.
|
336746 | nodes.emplace_back(); | |
50 | 336746 | nodes.back().vertex = clique_vertex; | ||
51 | } | |||
52 | // Now, we do a breadth-first traversal of the remaining vertices, | |||
53 | // adding all vertices only one step away from the current set. | |||
54 | 302476 | size_t current_nodes_begin = 0; | ||
55 | ||||
56 |
1/2✓ Branch 1 taken 302476 times.
✗ Branch 2 not taken.
|
302476 | set<size_t> vertices_seen = initial_clique; | |
57 | 302476 | set<size_t> vertices_to_add; | ||
58 | ||||
59 |
1/2✓ Branch 1 taken 331813 times.
✗ Branch 2 not taken.
|
1/2✓ Decision 'true' taken 331813 times.
✗ Decision 'false' not taken.
|
331813 | for (size_t counter = 0; counter < 2 * vertices_in_component.size(); |
60 | ++counter) { | |||
61 | 331813 | const size_t current_nodes_end = nodes.size(); | ||
62 | ||||
63 |
2/2✓ Branch 0 taken 484931 times.
✓ Branch 1 taken 331813 times.
|
2/2✓ Decision 'true' taken 484931 times.
✓ Decision 'false' taken 331813 times.
|
816744 | for (size_t i = current_nodes_begin; i < current_nodes_end; ++i) { |
64 |
1/2✓ Branch 2 taken 484931 times.
✗ Branch 3 not taken.
|
484931 | const auto& neighbours = adjacency_data.get_neighbours(nodes[i].vertex); | |
65 |
2/2✓ Branch 5 taken 754004 times.
✓ Branch 6 taken 484931 times.
|
2/2✓ Decision 'true' taken 754004 times.
✓ Decision 'false' taken 484931 times.
|
1238935 | for (size_t neighbour : neighbours) { |
66 |
3/4✓ Branch 1 taken 754004 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 197503 times.
✓ Branch 4 taken 556501 times.
|
2/2✓ Decision 'true' taken 197503 times.
✓ Decision 'false' taken 556501 times.
|
754004 | if (vertices_seen.count(neighbour) == 0) { |
67 |
1/2✓ Branch 1 taken 197503 times.
✗ Branch 2 not taken.
|
197503 | vertices_to_add.insert(neighbour); | |
68 | } | |||
69 | } | |||
70 | } | |||
71 |
2/2✓ Branch 1 taken 302476 times.
✓ Branch 2 taken 29337 times.
|
2/2✓ Decision 'true' taken 302476 times.
✓ Decision 'false' taken 29337 times.
|
331813 | if (vertices_to_add.empty()) { |
72 | 302476 | break; | ||
73 | } | |||
74 |
2/2✓ Branch 4 taken 148185 times.
✓ Branch 5 taken 29337 times.
|
2/2✓ Decision 'true' taken 148185 times.
✓ Decision 'false' taken 29337 times.
|
177522 | for (size_t neighbour : vertices_to_add) { |
75 |
1/2✓ Branch 1 taken 148185 times.
✗ Branch 2 not taken.
|
148185 | vertices_seen.insert(neighbour); | |
76 |
1/2✓ Branch 1 taken 148185 times.
✗ Branch 2 not taken.
|
148185 | nodes.emplace_back(); | |
77 | 148185 | nodes.back().vertex = neighbour; | ||
78 | } | |||
79 | 29337 | vertices_to_add.clear(); | ||
80 | 29337 | current_nodes_begin = current_nodes_end; | ||
81 | } | |||
82 | // GCOVR_EXCL_START | |||
83 | if (nodes.size() != vertices_in_component.size()) { | |||
84 | throw std::runtime_error( | |||
85 | "Final size check: number of filled " | |||
86 | "nodes does not match number of vertices in this component"); | |||
87 | } | |||
88 | // GCOVR_EXCL_STOP | |||
89 |
0/2✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
302476 | } catch (const std::exception& e) { | |
90 | // GCOVR_EXCL_START | |||
91 | TKET_ASSERT( | |||
92 | AssertMessage() | |||
93 | << "ColouringPriority: fill_initial_node_sequence: initial" | |||
94 | << " clique size " << initial_clique.size() << ", " | |||
95 | << vertices_in_component.size() << " vertices in" | |||
96 | << " this component (full graph has " | |||
97 | << adjacency_data.get_number_of_vertices() << " vertices)." | |||
98 | << " So far, filled " << nodes.size() << " nodes." | |||
99 | << " Error: " << e.what()); | |||
100 | // GCOVR_EXCL_STOP | |||
101 | } | |||
102 | 302476 | } | ||
103 | ||||
104 | // Quadratic, but we're not afraid; the main brute force colouring is | |||
105 | // exponential! Assumes that "fill_initial_node_sequence" has just been called. | |||
106 | // Fills in "earlier_neighbour_node_indices". | |||
107 | 302476 | static void fill_node_dependencies( | ||
108 | ColouringPriority::Nodes& nodes, const AdjacencyData& adjacency_data) { | |||
109 |
2/2✓ Branch 1 taken 182455 times.
✓ Branch 2 taken 302476 times.
|
2/2✓ Decision 'true' taken 182455 times.
✓ Decision 'false' taken 302476 times.
|
484931 | for (size_t node_index = 1; node_index < nodes.size(); ++node_index) { |
110 | 182455 | auto& this_node = nodes[node_index]; | ||
111 | ||||
112 |
2/2✓ Branch 0 taken 2879499 times.
✓ Branch 1 taken 182455 times.
|
2/2✓ Decision 'true' taken 2879499 times.
✓ Decision 'false' taken 182455 times.
|
3061954 | for (size_t other_index = 0; other_index < node_index; ++other_index) { |
113 |
3/4✓ Branch 1 taken 2879499 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 377002 times.
✓ Branch 4 taken 2502497 times.
|
2/2✓ Decision 'true' taken 377002 times.
✓ Decision 'false' taken 2502497 times.
|
2879499 | if (adjacency_data.edge_exists( |
114 | 2879499 | this_node.vertex, nodes[other_index].vertex)) { | ||
115 |
1/2✓ Branch 1 taken 377002 times.
✗ Branch 2 not taken.
|
377002 | this_node.earlier_neighbour_node_indices.emplace_back(other_index); | |
116 | } | |||
117 | } | |||
118 | } | |||
119 | 302476 | } | ||
120 | ||||
121 | 642548 | const ColouringPriority::Nodes& ColouringPriority::get_nodes() const { | ||
122 | 642548 | return m_nodes; | ||
123 | } | |||
124 | ||||
125 | // GCOVR_EXCL_START | |||
126 | // currently used only within a tket assert macro | |||
127 | string ColouringPriority::print_raw_data(bool relabel_to_simplify) const { | |||
128 | map<size_t, size_t> old_vertex_to_new_vertex; | |||
129 | if (relabel_to_simplify) { | |||
130 | for (size_t i = 0; i < m_nodes.size(); ++i) { | |||
131 | old_vertex_to_new_vertex[m_nodes[i].vertex] = i; | |||
132 | } | |||
133 | } else { | |||
134 | for (const auto& node : m_nodes) { | |||
135 | const auto v = node.vertex; | |||
136 | old_vertex_to_new_vertex[v] = v; | |||
137 | } | |||
138 | } | |||
139 | map<size_t, set<size_t>> data; | |||
140 | for (const auto& node : m_nodes) { | |||
141 | const auto this_v = old_vertex_to_new_vertex.at(node.vertex); | |||
142 | const auto& earlier_v_indices = node.earlier_neighbour_node_indices; | |||
143 | for (size_t i : earlier_v_indices) { | |||
144 | const auto other_v = old_vertex_to_new_vertex.at(m_nodes[i].vertex); | |||
145 | data[this_v].insert(other_v); | |||
146 | data[other_v].insert(this_v); | |||
147 | } | |||
148 | } | |||
149 | // Compress: remove (i,j) edges if i>j. | |||
150 | { | |||
151 | vector<size_t> v_to_erase; | |||
152 | for (auto& entry : data) { | |||
153 | v_to_erase.clear(); | |||
154 | for (auto v : entry.second) { | |||
155 | if (v < entry.first) { | |||
156 | v_to_erase.push_back(v); | |||
157 | } | |||
158 | } | |||
159 | for (auto v : v_to_erase) { | |||
160 | entry.second.erase(v); | |||
161 | } | |||
162 | } | |||
163 | } | |||
164 | std::stringstream ss; | |||
165 | ||||
166 | ss << "\nNeighbours:\nconst std::map<std::size_t, std::vector<std::size_t>> " | |||
167 | "data { "; | |||
168 | for (const auto& entry : data) { | |||
169 | if (!entry.second.empty()) { | |||
170 | ss << "\n { " << entry.first << ", { "; | |||
171 | for (auto v : entry.second) { | |||
172 | ss << v << ", "; | |||
173 | } | |||
174 | ss << "} },"; | |||
175 | } | |||
176 | } | |||
177 | ss << "\n};\n\n"; | |||
178 | return ss.str(); | |||
179 | } | |||
180 | // GCOVR_EXCL_STOP | |||
181 | ||||
182 | 302476 | ColouringPriority::ColouringPriority( | ||
183 | const AdjacencyData& adjacency_data, | |||
184 | 302476 | const set<size_t>& vertices_in_component, const set<size_t>& initial_clique) | ||
185 | 302476 | : m_initial_clique(initial_clique) { | ||
186 | 302476 | fill_initial_node_sequence( | ||
187 |
1/2✓ Branch 1 taken 302476 times.
✗ Branch 2 not taken.
|
302476 | m_nodes, adjacency_data, vertices_in_component, initial_clique); | |
188 | ||||
189 |
1/2✓ Branch 1 taken 302476 times.
✗ Branch 2 not taken.
|
302476 | fill_node_dependencies(m_nodes, adjacency_data); | |
190 | 302476 | } | ||
191 | ||||
192 | 15078 | const set<size_t>& ColouringPriority::get_initial_clique() const { | ||
193 | 15078 | return m_initial_clique; | ||
194 | } | |||
195 | ||||
196 | } // namespace graphs | |||
197 | } // namespace tket | |||
198 |