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 "SubgraphMonomorphisms.hpp" | |||
16 | ||||
17 | #include <set> | |||
18 | #include <tkassert/Assert.hpp> | |||
19 | #include <tkwsm/EndToEndWrappers/MainSolver.hpp> | |||
20 | ||||
21 | namespace tket { | |||
22 | ||||
23 | using namespace WeightedSubgraphMonomorphism; | |||
24 | ||||
25 | 6 | static GraphEdgeWeights get_weight_one_edges( | ||
26 | const std::vector<Swap>& edges, size_t number_of_vertices) { | |||
27 | 6 | GraphEdgeWeights result; | ||
28 |
2/2✓ Branch 4 taken 45 times.
✓ Branch 5 taken 6 times.
|
2/2✓ Decision 'true' taken 45 times.
✓ Decision 'false' taken 6 times.
|
51 | for (const auto& edge : edges) { |
29 | TKET_ASSERT(edge.first < number_of_vertices); | |||
30 | TKET_ASSERT(edge.second < number_of_vertices); | |||
31 |
2/4✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 45 times.
✗ Branch 5 not taken.
|
45 | result[get_edge(edge.first, edge.second)] = 1; | |
32 | } | |||
33 | TKET_ASSERT(edges.size() == result.size()); | |||
34 | 6 | return result; | ||
35 | } | |||
36 | ||||
37 | 3 | static void add_solver_solutions( | ||
38 | const std::vector<SolutionWSM>& solutions, size_t pattern_n_vertices, | |||
39 | size_t target_n_vertices, SubgraphMonomorphisms& monomorphisms) { | |||
40 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | monomorphisms.mappings.reserve(solutions.size()); | |
41 | ||||
42 | // The solver ignores isolated vertices, so we'll fill them in separately. | |||
43 | 3 | std::set<size_t> used_pattern_vertices; | ||
44 | 3 | std::set<size_t> used_pattern_vertices_copy; | ||
45 | 3 | std::set<size_t> used_target_vertices; | ||
46 | ||||
47 |
2/2✓ Branch 5 taken 36 times.
✓ Branch 6 taken 3 times.
|
2/2✓ Decision 'true' taken 36 times.
✓ Decision 'false' taken 3 times.
|
39 | for (const auto& solution : solutions) { |
48 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 | monomorphisms.mappings.emplace_back(); | |
49 |
1/2✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
|
36 | monomorphisms.mappings.back().resize(pattern_n_vertices); | |
50 | 36 | used_pattern_vertices.clear(); | ||
51 | 36 | used_target_vertices.clear(); | ||
52 |
2/2✓ Branch 4 taken 180 times.
✓ Branch 5 taken 36 times.
|
2/2✓ Decision 'true' taken 180 times.
✓ Decision 'false' taken 36 times.
|
216 | for (const auto& pair : solution.assignments) { |
53 | 180 | const auto& pv = pair.first; | ||
54 | 180 | const auto& tv = pair.second; | ||
55 | TKET_ASSERT(used_pattern_vertices.insert(pv).second); | |||
56 | TKET_ASSERT(used_target_vertices.insert(tv).second); | |||
57 |
2/2✓ Branch 1 taken 165 times.
✓ Branch 2 taken 15 times.
|
1/2✓ Decision 'true' taken 180 times.
✗ Decision 'false' not taken.
|
180 | if (!used_pattern_vertices_copy.empty()) { |
58 | // It's always the same nonisolated pattern vertices. | |||
59 | TKET_ASSERT(used_pattern_vertices_copy.count(pv) != 0); | |||
60 | } | |||
61 | // The architecture mapping guarantees | |||
62 | // contiguous vertex numbers {0,1,2,...,N} | |||
63 | TKET_ASSERT(pv < pattern_n_vertices); | |||
64 | TKET_ASSERT(tv < target_n_vertices); | |||
65 | 180 | monomorphisms.mappings.back()[pv] = tv; | ||
66 | } | |||
67 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 33 times.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 33 times.
|
36 | if (used_pattern_vertices_copy.empty()) { |
68 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | used_pattern_vertices_copy = used_pattern_vertices; | |
69 | } else { | |||
70 |
1/104✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 150 not taken.
✗ Branch 151 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 156 not taken.
✗ Branch 157 not taken.
✗ Branch 159 not taken.
✗ Branch 160 not taken.
✗ Branch 163 not taken.
✗ Branch 164 not taken.
✗ Branch 167 not taken.
✗ Branch 168 not taken.
✗ Branch 170 not taken.
✗ Branch 171 not taken.
|
33 | TKET_ASSERT( | |
71 | used_pattern_vertices_copy.size() == used_pattern_vertices.size()); | |||
72 | } | |||
73 | ||||
74 | // Now, fill in isolated p-vertex values. | |||
75 | 36 | size_t next_tv = 0; | ||
76 |
2/2✓ Branch 0 taken 216 times.
✓ Branch 1 taken 36 times.
|
2/2✓ Decision 'true' taken 216 times.
✓ Decision 'false' taken 36 times.
|
252 | for (size_t pv = 0; pv < pattern_n_vertices; ++pv) { |
77 | // We could save time by saving the isolated PVs, | |||
78 | // but surely not worth it | |||
79 |
3/4✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 180 times.
✓ Branch 4 taken 36 times.
|
2/2✓ Decision 'true' taken 180 times.
✓ Decision 'false' taken 36 times.
|
216 | if (used_pattern_vertices.count(pv) != 0) { |
80 | 180 | continue; | ||
81 | } | |||
82 |
3/4✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
✓ Branch 4 taken 36 times.
|
0/1? Decision couldn't be analyzed.
|
120 | while (used_target_vertices.count(next_tv) != 0) { |
83 | 84 | ++next_tv; | ||
84 | } | |||
85 | 36 | monomorphisms.mappings.back()[pv] = next_tv; | ||
86 | 36 | ++next_tv; | ||
87 | } | |||
88 | } | |||
89 | 3 | } | ||
90 | ||||
91 | // Strictly speaking, we should go through all (T choose k) subsets | |||
92 | // of target vertices, and all permutations of k pattern vertices, | |||
93 | // but don't bother for now - just give one solution. | |||
94 | ✗ | static void fill_with_all_isolated_pattern_vertices( | ||
95 | SubgraphMonomorphisms& monomorphisms, size_t pattern_n_vertices) { | |||
96 | ✗ | monomorphisms.mappings.resize(1); | ||
97 | ✗ | monomorphisms.mappings[0].resize(pattern_n_vertices); | ||
98 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | for (size_t ii = 0; ii < pattern_n_vertices; ++ii) { | |
99 | ✗ | monomorphisms.mappings[0][ii] = ii; | ||
100 | } | |||
101 | } | |||
102 | ||||
103 | 4 | SubgraphMonomorphisms::SubgraphMonomorphisms( | ||
104 | const ArchitectureMapping& pattern_arch_mapping, | |||
105 | const ArchitectureMapping& target_arch_mapping, | |||
106 | 4 | const Parameters& parameters) | ||
107 | 4 | : time_taken_ms(0) { | ||
108 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 3 times.
|
4 | if (parameters.max_number_of_mappings == 0) { |
109 | 1 | return; | ||
110 | } | |||
111 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | const auto pattern_n_vertices = pattern_arch_mapping.number_of_vertices(); | |
112 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | const auto target_n_vertices = target_arch_mapping.number_of_vertices(); | |
113 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 3 times.
|
4 | if (pattern_n_vertices > target_n_vertices) { |
114 | 1 | return; | ||
115 | } | |||
116 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | const auto pattern_edges = pattern_arch_mapping.get_edges(); | |
117 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | const auto target_edges = target_arch_mapping.get_edges(); | |
118 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 3 times.
|
3 | if (pattern_edges.size() > target_edges.size()) { |
119 | ✗ | return; | ||
120 | } | |||
121 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 3 times.
|
3 | if (pattern_edges.empty()) { |
122 | // A pointless special case: all pattern vertices are isolated! | |||
123 | ✗ | fill_with_all_isolated_pattern_vertices(*this, pattern_n_vertices); | ||
124 | ✗ | return; | ||
125 | } | |||
126 | const auto pattern_edges_and_weights = | |||
127 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | get_weight_one_edges(pattern_edges, pattern_n_vertices); | |
128 | const auto target_edges_and_weights = | |||
129 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | get_weight_one_edges(target_edges, target_n_vertices); | |
130 | ||||
131 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | MainSolverParameters solver_parameters; | |
132 | 3 | solver_parameters.terminate_with_first_full_solution = false; | ||
133 | 3 | solver_parameters.for_multiple_full_solutions_the_max_number_to_obtain = | ||
134 | 3 | parameters.max_number_of_mappings; | ||
135 | 3 | solver_parameters.timeout_ms = parameters.timeout_ms; | ||
136 | ||||
137 | const MainSolver main_solver( | |||
138 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | pattern_edges_and_weights, target_edges_and_weights, solver_parameters); | |
139 | ||||
140 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | const auto& solution_data = main_solver.get_solution_data(); | |
141 | ||||
142 | 3 | time_taken_ms = | ||
143 | 3 | solution_data.initialisation_time_ms + solution_data.search_time_ms; | ||
144 | ||||
145 | 3 | add_solver_solutions( | ||
146 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | solution_data.solutions, pattern_n_vertices, target_n_vertices, *this); | |
147 |
2/4✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
|
3 | } | |
148 | ||||
149 | } // namespace tket | |||
150 |