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 "DistancesFromArchitecture.hpp" | |||
16 | ||||
17 | #include <sstream> | |||
18 | #include <stdexcept> | |||
19 | ||||
20 | namespace tket { | |||
21 | ||||
22 | 2524 | DistancesFromArchitecture::DistancesFromArchitecture( | ||
23 | 2524 | const ArchitectureMapping& arch_mapping) | ||
24 | 2524 | : m_arch_mapping(arch_mapping) {} | ||
25 | ||||
26 | 90279 | void DistancesFromArchitecture::register_shortest_path( | ||
27 | const std::vector<size_t>& path) { | |||
28 | // To avoid quadratic growth for really long paths, | |||
29 | // just do various slices. | |||
30 |
2/2✓ Branch 1 taken 68588 times.
✓ Branch 2 taken 21691 times.
|
2/2✓ Decision 'true' taken 68588 times.
✓ Decision 'false' taken 21691 times.
|
90279 | if (path.size() <= 5) { |
31 | 68588 | register_shortest_path_with_limits(path, 0, path.size()); | ||
32 | 68588 | return; | ||
33 | } | |||
34 | 21691 | const size_t middle = path.size() / 2; | ||
35 |
2/2✓ Branch 1 taken 20953 times.
✓ Branch 2 taken 738 times.
|
2/2✓ Decision 'true' taken 20953 times.
✓ Decision 'false' taken 738 times.
|
21691 | if (path.size() <= 10) { |
36 | 20953 | register_shortest_path_with_limits(path, 0, middle); | ||
37 | 20953 | register_shortest_path_with_limits(path, middle, path.size()); | ||
38 | 20953 | register_edge(path[middle - 1], path[middle]); | ||
39 | 20953 | return; | ||
40 | } | |||
41 | 738 | register_shortest_path_with_limits(path, 0, 5); | ||
42 | 738 | register_shortest_path_with_limits(path, path.size() - 5, path.size()); | ||
43 |
2/2✓ Branch 1 taken 150 times.
✓ Branch 2 taken 588 times.
|
2/2✓ Decision 'true' taken 150 times.
✓ Decision 'false' taken 588 times.
|
738 | if (path.size() >= 15) { |
44 | 150 | register_shortest_path_with_limits(path, middle - 2, middle + 3); | ||
45 | } | |||
46 | } | |||
47 | ||||
48 | 112120 | void DistancesFromArchitecture::register_shortest_path_with_limits( | ||
49 | const std::vector<size_t>& path, size_t begin, size_t end) { | |||
50 |
2/2✓ Branch 0 taken 397846 times.
✓ Branch 1 taken 112120 times.
|
2/2✓ Decision 'true' taken 397846 times.
✓ Decision 'false' taken 112120 times.
|
509966 | for (size_t ii = begin; ii < end; ++ii) { |
51 |
2/2✓ Branch 0 taken 552014 times.
✓ Branch 1 taken 397846 times.
|
2/2✓ Decision 'true' taken 552014 times.
✓ Decision 'false' taken 397846 times.
|
949860 | for (size_t jj = ii + 1; jj < end; ++jj) { |
52 |
1/2✓ Branch 4 taken 552014 times.
✗ Branch 5 not taken.
|
552014 | m_cached_distances[get_swap(path[ii], path[jj])] = jj - ii; | |
53 | } | |||
54 | } | |||
55 | 112120 | } | ||
56 | ||||
57 | 1372986 | void DistancesFromArchitecture::register_edge(size_t vertex1, size_t vertex2) { | ||
58 |
1/2✓ Branch 2 taken 1372986 times.
✗ Branch 3 not taken.
|
1372986 | m_cached_distances[get_swap(vertex1, vertex2)] = 1; | |
59 | 1372986 | } | ||
60 | ||||
61 | 9103137 | size_t DistancesFromArchitecture::operator()(size_t vertex1, size_t vertex2) { | ||
62 |
2/2✓ Branch 0 taken 2240150 times.
✓ Branch 1 taken 6862987 times.
|
2/2✓ Decision 'true' taken 2240150 times.
✓ Decision 'false' taken 6862987 times.
|
9103137 | if (vertex1 == vertex2) { |
63 | 2240150 | return 0; | ||
64 | } | |||
65 | // Automatically set to zero if it doesn't exist yet. | |||
66 |
1/2✓ Branch 2 taken 6862987 times.
✗ Branch 3 not taken.
|
6862987 | auto& distance_entry = m_cached_distances[get_swap(vertex1, vertex2)]; | |
67 |
2/2✓ Branch 0 taken 351937 times.
✓ Branch 1 taken 6511050 times.
|
2/2✓ Decision 'true' taken 351937 times.
✓ Decision 'false' taken 6511050 times.
|
6862987 | if (distance_entry == 0) { |
68 | 351937 | const auto& arch = m_arch_mapping.get_architecture(); | ||
69 | 351937 | distance_entry = arch.get_distance( | ||
70 | 351937 | m_arch_mapping.get_node(vertex1), m_arch_mapping.get_node(vertex2)); | ||
71 | ||||
72 | // This message should no longer be triggered for disconnected | |||
73 | // architectures, since get_distance now should throw if v1, v2 are in | |||
74 | // different connected components. However, leave the check in, in case some | |||
75 | // other bizarre error causes distance zero to be returned. | |||
76 | // GCOVR_EXCL_START | |||
77 | TKET_ASSERT( | |||
78 | distance_entry > 0 || | |||
79 | AssertMessage() << "DistancesFromArchitecture: architecture has " | |||
80 | << arch.n_nodes() << " vertices, " | |||
81 | << arch.n_connections() << " edges; " | |||
82 | << " and d(" << vertex1 << "," << vertex2 | |||
83 | << ")=0. " | |||
84 | "Is the graph connected?"); | |||
85 | // GCOVR_EXCL_STOP | |||
86 | } | |||
87 | 6862971 | return distance_entry; | ||
88 | } | |||
89 | ||||
90 | } // namespace tket | |||
91 |