GCC Code Coverage Report


Directory: ./
File: Mapping/include/Mapping/LexiRoute.hpp
Date: 2022-10-15 05:10:18
Exec Total Coverage
Lines: 2 2 100.0%
Functions: 1 1 100.0%
Branches: 0 0 -%
Decisions: 0 0 -%

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 #pragma once
16
17 #include "Mapping/LexicographicalComparison.hpp"
18 #include "Mapping/MappingFrontier.hpp"
19 #include "Mapping/RoutingMethod.hpp"
20 #include "Mapping/RoutingMethodJson.hpp"
21
22 namespace tket {
23
24 class LexiRouteError : public std::logic_error {
25 public:
26 3 explicit LexiRouteError(const std::string& message)
27 3 : std::logic_error(message) {}
28 };
29
30 /**
31 * A class for modifiying a Circuit held in a MappingFrontier object
32 * with either an Architecture permitted single SWAP gate or BRIDGE gate.
33 * Used in the LexiRouteRoutingMethod class which provides a subcircuit
34 * modification method for MappingManager. Used in solution presented in "On the
35 * qubit routing problem" -> arXiv:1902.08091
36 */
37 class LexiRoute {
38 public:
39 /**
40 * Class Constructor
41 * @param _architecture Architecture object added operations must respect
42 * @param _mapping_frontier Contains Circuit object to be modified
43 */
44 LexiRoute(
45 const ArchitecturePtr& _architecture,
46 MappingFrontier_ptr& _mapping_frontier);
47
48 /**
49 * When called, LexiRoute::solve will modify the Circuit held in
50 * MappingFrontier object passed at class construction. Either a SWAP gate
51 * will be inserted at the input boundary of the held Circuit or a CX gate
52 * will be transformed into a BRIDGE gate. The added SWAP or BRIDGE gate will
53 * be valid for the Architecture passed at class construction.
54 * The decision making is based on the heuristic outlined in arXiv:1902.08091.
55 *
56 * @param lookahead Number of slices to lookahead at when determining best
57 * SWAP or BRIDGE
58 *
59 * @return True if solve has modified circuit for mapping purposes
60 */
61 bool solve(unsigned lookahead);
62
63 /**
64 * When called an "unlabelled" Qubit in the Circuit may be relabelled to a
65 * Node in the Architecture, or an "unlabelled" Qubit may have its path merged
66 * with an ancilla qubit. The decision making is based on the heuristic
67 * outlined in arXiv:1902.08091.
68 *
69 * @return True if solve_labelling has modified circuit for mapping purposes
70 */
71 bool solve_labelling();
72
73 private:
74 /** Only considers two-qubit vertices if both qubits are labelled to
75 * Architecture */
76 enum class AssignedOnly { Yes, No };
77 /** Returns a bool confirming if vertices are valid for LexiRoute::solve */
78 enum class CheckRoutingValidity { Yes, No };
79 /** Returns a bool confirming if vertices are valid for
80 * LexiRoute::solve_labelling */
81 enum class CheckLabellingValidity { Yes, No };
82
83 /**
84 * this->interacting_uids_ attribute is a map where key is one UnitID
85 * and value is the UnitID it needs to be adjacent to.
86 * This map is implicitly updated whenever a logical SWAP is inserted.
87 * set_interacting_uids determines this map for the first parallel set of
88 * interacting UnitID in the Circuit held in this->mapping_frontier_
89 * @param assigned_only If Yes, only include interactions where both UnitID
90 * are in this->architecture_.
91 * @param route_check If Yes, return false if solve not possible
92 * @param label_check If Yes, return false if solve_labelling not possible
93 *
94 * @return bool depending on ENUM conditions
95 */
96 bool set_interacting_uids(
97 AssignedOnly assigned_only, CheckRoutingValidity route_check,
98 CheckLabellingValidity label_check);
99
100 /**
101 * If there is some "free" Node in Architecture at distance "distances" on
102 * the connectivity graph, assign (relable) UnitID assignee to it. "free"
103 * => not in Circuit. If no unassigned node at distances from root, return
104 * false.
105 * @param assignee UnitID not in Architecture to relabel
106 * @param root Node in Architecture
107 * @param distances Distance at which to find free Node from root at
108 * @return True if assigned, else False
109 */
110 bool assign_at_distance(
111 const UnitID& assignee, const Node& root, unsigned distances);
112
113 /**
114 * If this->set_interacting_uids assigned_only bool is false then the
115 * this->interacting_uids attribute may have key and value UnitID not in
116 * this->architecture_.
117 * update_labelling assigns these non-architecture UnitID to some Architecture
118 * UnitID, updating the this->labelling_ attribute.
119 * @return True if anything relabelled, else false
120 */
121 bool update_labelling();
122
123 /**
124 * Returns a set of pair of UnitID, each denoting a SWAP.
125 * Returned SWAP have at least one UnitID in interacting_uids_.
126 * This is such that enacting any of these SWAP will alter the distance
127 * between some interacting UnitID.
128 * @return std::pair<UnitID, UnitID> suitable for addition to Circuit
129 */
130 swap_set_t get_candidate_swaps();
131
132 /**
133 * Proposed swap will have two Node
134 * Each of these Node may be in some interaction in the first layer of circuit
135 * held in mapping_frontier. If either of these Node are in an interaction,
136 * check whether said interaction is a CX interaction, and if the pair of Node
137 * in the interaction are at distance 2. If true, compare lexicographical
138 * distances between no swap and given swap assuming distance 2 interactions
139 * are complete. If no swap is better, update return object to reflect this.
140 * @param swap Pair of Node comprising SWAP for checking
141 * @param lookahead Number of steps of lookahead emplyed for comparison
142 * @return Pair of bool, where true implies BRIDGE to be added
143 */
144 std::pair<bool, bool> check_bridge(
145 const std::pair<Node, Node>& swap, unsigned lookahead);
146
147 /**
148 * Returns a pair of distances, where the distances are between n1 & p1, and
149 * n2 & p2. Pair object is ordered such that the greatest distance is first.
150 *
151 * @param p0_first First Node in first interaction to find distance between
152 * @param p0_second Second Node in first interaction to find distance between
153 * @param p1_first First Node in second interaction to find distance between
154 * @param p1_second Second Node in second interaction to find distance between
155 * @return Pair of size_t, being distances on architecture graph
156 */
157 const std::pair<size_t, size_t> pair_distances(
158 const Node& p0_first, const Node& p0_second, const Node& p1_first,
159 const Node& p1_second) const;
160
161 /**
162 * It is always expected that at least one Node in a SWAP will be in some
163 * interaction. This method checks that the given swap will strictly decrease
164 * the distance for this interaction, and removes it from the swaps set if
165 * not.
166 *
167 * @param swaps Potential swaps to remove from
168 */
169 void remove_swaps_decreasing(swap_set_t& swaps);
170
171 // Architecture all new physical operations must respect
172 ArchitecturePtr architecture_;
173 // Contains circuit for finding SWAP from and non-routed/routed boundary
174 MappingFrontier_ptr& mapping_frontier_;
175 // Map between UnitID and UnitID they interact with at boundary
176 unit_map_t interacting_uids_;
177 // Map between original circuit UnitID and new UnitID due to dynamic
178 // placement
179 unit_map_t labelling_;
180 // Set tracking which Architecture Node are present in Circuit
181 std::set<Node> assigned_nodes_;
182 };
183
184 } // namespace tket
185