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 "Mapping/AASRoute.hpp" | |||
16 | ||||
17 | namespace tket { | |||
18 | ||||
19 | 17 | AASRouteRoutingMethod::AASRouteRoutingMethod( | ||
20 | 17 | unsigned _aaslookahead, aas::CNotSynthType _cnotsynthtype) | ||
21 | 17 | : cnotsynthtype_(_cnotsynthtype), aaslookahead_(_aaslookahead) {} | ||
22 | ||||
23 | 105 | std::pair<bool, unit_map_t> AASRouteRoutingMethod::routing_method( | ||
24 | std::shared_ptr<MappingFrontier>& mapping_frontier, | |||
25 | const ArchitecturePtr& architecture) const { | |||
26 | std::shared_ptr<unit_frontier_t> next_frontier = | |||
27 | frontier_convert_vertport_to_edge( | |||
28 |
1/2✓ Branch 3 taken 105 times.
✗ Branch 4 not taken.
|
105 | mapping_frontier->circuit_, mapping_frontier->linear_boundary); | |
29 | ||||
30 | 105 | CutFrontier next_cut = mapping_frontier->circuit_.next_cut( | ||
31 |
2/4✓ Branch 1 taken 105 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 105 times.
✗ Branch 7 not taken.
|
210 | next_frontier, std::make_shared<b_frontier_t>()); | |
32 | ||||
33 | // search for ppb in slice | |||
34 |
2/2✓ Branch 6 taken 214 times.
✓ Branch 7 taken 89 times.
|
2/2✓ Decision 'true' taken 214 times.
✓ Decision 'false' taken 89 times.
|
303 | for (const Vertex& v : *next_cut.slice) { |
35 |
3/4✓ Branch 2 taken 214 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 195 times.
|
2/2✓ Decision 'true' taken 16 times.
✓ Decision 'false' taken 198 times.
|
214 | if (mapping_frontier->circuit_.get_OpType_from_Vertex(v) == |
36 | OpType::PhasePolyBox) { | |||
37 | TKET_ASSERT(mapping_frontier->circuit_.is_quantum_node(v)); | |||
38 | ||||
39 |
1/2✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
|
19 | unsigned number_of_qubits = mapping_frontier->circuit_.n_in_edges(v); | |
40 |
1/2✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
|
19 | unit_vector_t qubit_vec(number_of_qubits); | |
41 | ||||
42 | // check all qubits of the ppb if they are placed | |||
43 | 19 | bool box_placed = true; | ||
44 |
2/2✓ Branch 0 taken 129 times.
✓ Branch 1 taken 19 times.
|
148 | for (unsigned i = 0; i < number_of_qubits; ++i) { | |
45 |
1/2✓ Branch 2 taken 129 times.
✗ Branch 3 not taken.
|
129 | const Edge& e = mapping_frontier->circuit_.get_nth_in_edge(v, i); | |
46 | 129 | for (const std::pair<UnitID, Edge>& pair : | ||
47 |
5/8✓ Branch 5 taken 1179 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1179 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1308 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1179 times.
✓ Branch 14 taken 129 times.
|
1437 | next_frontier->get<TagKey>()) { | |
48 |
3/4✓ Branch 1 taken 1179 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 129 times.
✓ Branch 4 taken 1050 times.
|
1179 | if (pair.second == e) { | |
49 |
1/2✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
|
129 | qubit_vec[i] = Qubit(pair.first); | |
50 |
4/6✓ Branch 2 taken 129 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 129 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 17 times.
✓ Branch 9 taken 112 times.
|
129 | if (!architecture->node_exists(Node(pair.first))) { | |
51 | 17 | box_placed = false; | ||
52 | } | |||
53 | } | |||
54 | } | |||
55 | } | |||
56 | ||||
57 | // check that the box we are working on is really placed and the check | |||
58 | // method has been executed | |||
59 | // this is imporant if the circuit contains more than one ppb and only one | |||
60 | // of them is placed | |||
61 | ||||
62 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 3 times.
|
19 | if (box_placed) { | |
63 | // get ppb from op | |||
64 | Op_ptr op_ptr_ppb = | |||
65 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | mapping_frontier->circuit_.get_Op_ptr_from_Vertex(v); | |
66 | 16 | const PhasePolyBox& ppb = static_cast<const PhasePolyBox&>(*op_ptr_ppb); | ||
67 | ||||
68 | // Circuit circuit_ppb_place(*ppb.to_circuit()); | |||
69 | ||||
70 | // generate aritecture to make sure that the result can be inserted into | |||
71 | // the given circuit by using flatten_registers | |||
72 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | auto nodes_vec = architecture->get_all_nodes_vec(); | |
73 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | auto edges_vec = architecture->get_all_edges_vec(); | |
74 | ||||
75 | // create maps from qubits/node to int | |||
76 | 16 | std::map<UnitID, Node> orig_node_to_int_node; | ||
77 | 16 | std::map<UnitID, Node> orig_qubit_to_int_node; | ||
78 | ||||
79 | 16 | unsigned id_node = 0; | ||
80 | ||||
81 | 16 | unsigned n_nodes = architecture->n_nodes(); | ||
82 | ||||
83 |
2/2✓ Branch 6 taken 112 times.
✓ Branch 7 taken 16 times.
|
128 | for (Node orig_node : nodes_vec) { | |
84 |
2/4✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 112 times.
✗ Branch 6 not taken.
|
112 | orig_node_to_int_node.insert({orig_node, Node(n_nodes)}); | |
85 | 112 | } | ||
86 | ||||
87 |
2/2✓ Branch 6 taken 112 times.
✓ Branch 7 taken 16 times.
|
128 | for (auto orig_qubit : qubit_vec) { | |
88 |
2/4✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
|
112 | orig_node_to_int_node[orig_qubit] = Node(id_node); | |
89 | 112 | ++id_node; | ||
90 | 112 | } | ||
91 | ||||
92 |
2/2✓ Branch 6 taken 112 times.
✓ Branch 7 taken 16 times.
|
128 | for (Node orig_node : nodes_vec) { | |
93 |
4/8✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 112 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 112 times.
|
112 | if (orig_node_to_int_node[orig_node] == Node(n_nodes)) { | |
94 | ✗ | orig_node_to_int_node[orig_node] = Node(id_node); | ||
95 | ✗ | ++id_node; | ||
96 | } | |||
97 | 112 | } | ||
98 | ||||
99 | // define new arcitecture with int nodes for ppb | |||
100 | 16 | std::vector<Architecture::Connection> new_con; | ||
101 |
3/4✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 10 taken 96 times.
✓ Branch 11 taken 16 times.
|
112 | for (auto pair : architecture->get_all_edges_vec()) { | |
102 |
1/2✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
|
96 | new_con.push_back( | |
103 |
1/2✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
|
96 | {orig_node_to_int_node[UnitID(pair.first)], | |
104 |
1/2✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
|
192 | orig_node_to_int_node[UnitID(pair.second)]}); | |
105 | 112 | } | ||
106 | ||||
107 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | Architecture new_int_arch = Architecture(new_con); | |
108 | ||||
109 | TKET_ASSERT(architecture->n_nodes() == new_int_arch.n_nodes()); | |||
110 | ||||
111 | Circuit result = aas::phase_poly_synthesis( | |||
112 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | new_int_arch, ppb, aaslookahead_, cnotsynthtype_); | |
113 | ||||
114 | // make sure the circuit can be inserted | |||
115 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | result.flatten_registers(); | |
116 | ||||
117 | // substitute the ppb vertex in the initial circuit with the routed | |||
118 | // result | |||
119 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | mapping_frontier->circuit_.substitute(result, v); | |
120 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | return {true, {}}; | |
121 | 16 | } | ||
122 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 16 times.
|
19 | } | |
123 | } | |||
124 |
1/2✓ Branch 2 taken 89 times.
✗ Branch 3 not taken.
|
89 | return {false, {}}; | |
125 | 105 | } | ||
126 | ||||
127 | 1 | aas::CNotSynthType AASRouteRoutingMethod::get_cnotsynthtype() const { | ||
128 | 1 | return this->cnotsynthtype_; | ||
129 | } | |||
130 | ||||
131 | 1 | unsigned AASRouteRoutingMethod::get_aaslookahead() const { | ||
132 | 1 | return this->aaslookahead_; | ||
133 | } | |||
134 | ||||
135 | 1 | nlohmann::json AASRouteRoutingMethod::serialize() const { | ||
136 | 1 | nlohmann::json j; | ||
137 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | j["aaslookahead"] = this->get_aaslookahead(); | |
138 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | j["cnotsynthtype"] = (unsigned)this->get_cnotsynthtype(); | |
139 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | j["name"] = "AASRouteRoutingMethod"; | |
140 | 1 | return j; | ||
141 | } | |||
142 | ||||
143 | 1 | AASRouteRoutingMethod AASRouteRoutingMethod::deserialize( | ||
144 | const nlohmann::json& j) { | |||
145 | 1 | unsigned aaslookahead = j.at("aaslookahead").get<unsigned>(); | ||
146 | aas::CNotSynthType cnotsynthtype = | |||
147 | 1 | (aas::CNotSynthType)j.at("cnotsynthtype").get<unsigned>(); | ||
148 | 1 | return AASRouteRoutingMethod(aaslookahead, cnotsynthtype); | ||
149 | } | |||
150 | ||||
151 | } // namespace tket | |||
152 |