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 "RzPhasedXSquash.hpp" | |||
16 | ||||
17 | #include <memory> | |||
18 | ||||
19 | #include "BasicOptimisation.hpp" | |||
20 | #include "Decomposition.hpp" | |||
21 | #include "PQPSquash.hpp" | |||
22 | #include "Transform.hpp" | |||
23 | #include "Utils/Expression.hpp" | |||
24 | ||||
25 | namespace tket { | |||
26 | ||||
27 | namespace Transforms { | |||
28 | ||||
29 | 11 | RzPhasedXSquasher::RzPhasedXSquasher(bool reversed) | ||
30 | 11 | : PQPSquasher(OpType::Rz, OpType::Rx, false, reversed) {} | ||
31 | ||||
32 | 61 | std::pair<Circuit, Gate_ptr> RzPhasedXSquasher::flush( | ||
33 | std::optional<Pauli> commutation_colour) const { | |||
34 | // For Quantinuum gate set, commutation_colour can only be Z or nullopt (e.g. | |||
35 | // Measure) | |||
36 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
61 | std::pair<Circuit, Gate_ptr> pair = PQPSquasher::flush(commutation_colour); | |
37 | ||||
38 | // Setting smart_squash to false should guarantee that only Rzs can commute | |||
39 | // through. | |||
40 | TKET_ASSERT(pair.second == nullptr || pair.second->get_type() == OpType::Rz); | |||
41 |
1/2✓ Branch 2 taken 61 times.
✗ Branch 3 not taken.
|
61 | Circuit replacement(1); | |
42 |
2/4✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 61 times.
✗ Branch 5 not taken.
|
61 | replacement.add_phase(pair.first.get_phase()); | |
43 | ||||
44 | // 1. Recover the angles of RzRxRz and the leftover Rz from PQPSquasher | |||
45 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
61 | std::vector<Command> coms = pair.first.get_commands(); | |
46 | // pqp | |||
47 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
61 | Expr rz1_angle = 0; | |
48 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
61 | Expr rx_angle = 0; | |
49 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
61 | Expr rz2_angle = 0; | |
50 | // left over Rz | |||
51 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
61 | Expr rz3_angle = 0; | |
52 |
2/2✓ Branch 1 taken 56 times.
✓ Branch 2 taken 5 times.
|
2/2✓ Decision 'true' taken 56 times.
✓ Decision 'false' taken 5 times.
|
61 | if (coms.size() > 0) { |
53 |
2/2✓ Branch 5 taken 41 times.
✓ Branch 6 taken 15 times.
|
2/2✓ Decision 'true' taken 41 times.
✓ Decision 'false' taken 15 times.
|
56 | if (coms[0].get_op_ptr()->get_type() == OpType::Rz) { |
54 |
2/4✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 41 times.
✗ Branch 9 not taken.
|
41 | rz1_angle = coms[0].get_op_ptr()->get_params()[0]; | |
55 | } else { | |||
56 |
2/4✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 15 times.
✗ Branch 9 not taken.
|
15 | rx_angle = coms[0].get_op_ptr()->get_params()[0]; | |
57 | } | |||
58 | } | |||
59 |
2/2✓ Branch 1 taken 14 times.
✓ Branch 2 taken 47 times.
|
2/2✓ Decision 'true' taken 14 times.
✓ Decision 'false' taken 47 times.
|
61 | if (coms.size() > 1) { |
60 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 12 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 12 times.
|
14 | if (coms[1].get_op_ptr()->get_type() == OpType::Rz) { |
61 |
2/4✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
|
2 | rz2_angle = coms[1].get_op_ptr()->get_params()[0]; | |
62 | } else { | |||
63 |
2/4✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
|
12 | rx_angle = coms[1].get_op_ptr()->get_params()[0]; | |
64 | } | |||
65 | } | |||
66 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 51 times.
|
2/2✓ Decision 'true' taken 10 times.
✓ Decision 'false' taken 51 times.
|
61 | if (coms.size() > 2) { |
67 |
2/4✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
|
10 | rz2_angle = coms[2].get_op_ptr()->get_params()[0]; | |
68 | } | |||
69 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 61 times.
|
61 | if (pair.second != nullptr) { |
70 | ✗ | rz3_angle = pair.second->get_params()[0]; | ||
71 | } | |||
72 | ||||
73 | // 2. Rebase (Rz Rx Rz | Rz) into (PhasedX Rz | Rz) | |||
74 |
5/6✓ Branch 1 taken 37 times.
✓ Branch 2 taken 24 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 37 times.
✓ Branch 6 taken 24 times.
✓ Branch 7 taken 37 times.
|
2/2✓ Decision 'true' taken 24 times.
✓ Decision 'false' taken 37 times.
|
61 | if (commutation_colour == Pauli::Z || commutation_colour == Pauli::I) { |
75 |
3/4✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 17 times.
|
2/2✓ Decision 'true' taken 21 times.
✓ Decision 'false' taken 3 times.
|
24 | if (!equiv_0(rx_angle, 4)) { |
76 |
7/14✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 7 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 7 times.
✗ Branch 17 not taken.
✓ Branch 20 taken 14 times.
✓ Branch 21 taken 7 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
21 | replacement.add_op<unsigned>( | |
77 | OpType::PhasedX, {rx_angle, -rz1_angle}, {0}); | |||
78 | } | |||
79 |
2/4✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
|
24 | rz3_angle += rz1_angle + rz2_angle; | |
80 | } else { | |||
81 |
3/4✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 17 times.
|
0/1? Decision couldn't be analyzed.
|
37 | if (!equiv_0(rx_angle, 4)) { |
82 |
7/14✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 20 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 20 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 20 times.
✗ Branch 17 not taken.
✓ Branch 20 taken 40 times.
✓ Branch 21 taken 20 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
60 | replacement.add_op<unsigned>( | |
83 | OpType::PhasedX, {rx_angle, -rz1_angle}, {0}); | |||
84 | } | |||
85 |
4/6✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 22 times.
✓ Branch 8 taken 15 times.
|
2/2✓ Decision 'true' taken 22 times.
✓ Decision 'false' taken 15 times.
|
37 | if (!equiv_0(rz1_angle + rz2_angle, 4)) { |
86 |
3/6✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 22 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 22 times.
✗ Branch 10 not taken.
|
22 | replacement.add_op<unsigned>(OpType::Rz, {rz1_angle + rz2_angle}, {0}); | |
87 | } | |||
88 | } | |||
89 | Gate_ptr rz3_gate = | |||
90 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
61 | equiv_0(rz3_angle, 4) | |
91 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 20 times.
|
122 | ? nullptr | |
92 |
9/18✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 20 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 20 times.
✓ Branch 12 taken 41 times.
✓ Branch 13 taken 20 times.
✓ Branch 14 taken 41 times.
✓ Branch 15 taken 20 times.
✓ Branch 16 taken 41 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
202 | : std::make_shared<Gate>(OpType::Rz, std::vector<Expr>{rz3_angle}, 1); | |
93 |
1/2✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
|
122 | return {replacement, rz3_gate}; | |
94 | 61 | } | ||
95 | ||||
96 | 7 | Transform squash_1qb_to_Rz_PhasedX() { | ||
97 | 9 | return Transform([](Circuit &circ) { | ||
98 | 9 | bool reverse = false; | ||
99 |
2/4✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
|
9 | bool success = decompose_ZX().apply(circ); | |
100 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | auto squasher = std::make_unique<RzPhasedXSquasher>(reverse); | |
101 |
3/12✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 11 taken 9 times.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
18 | return SingleQubitSquash(std::move(squasher), circ, reverse).squash() || | |
102 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
18 | success; | |
103 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
16 | }); | |
104 | } | |||
105 | ||||
106 | } // namespace Transforms | |||
107 | ||||
108 | } // namespace tket | |||
109 |