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 "GateUnitaryMatrixImplementations.hpp" | |||
16 | #include "GateUnitaryMatrixUtils.hpp" | |||
17 | #include "Utils/Constants.hpp" | |||
18 | ||||
19 | namespace tket { | |||
20 | namespace internal { | |||
21 | ||||
22 | namespace { | |||
23 | ||||
24 | struct FixedData { | |||
25 | Eigen::Matrix2cd X; | |||
26 | Eigen::Matrix2cd Y; | |||
27 | Eigen::Matrix2cd Z; | |||
28 | Eigen::Matrix2cd S; | |||
29 | Eigen::Matrix2cd Sdg; | |||
30 | Eigen::Matrix2cd T; | |||
31 | Eigen::Matrix2cd Tdg; | |||
32 | Eigen::Matrix2cd V; | |||
33 | Eigen::Matrix2cd Vdg; | |||
34 | Eigen::Matrix2cd H; | |||
35 | Eigen::Matrix2cd SX; | |||
36 | Eigen::Matrix2cd SXdg; | |||
37 | Eigen::Matrix4cd CSX; | |||
38 | Eigen::Matrix4cd CSXdg; | |||
39 | Eigen::Matrix4cd CX; | |||
40 | Eigen::Matrix4cd CY; | |||
41 | Eigen::Matrix4cd CZ; | |||
42 | Eigen::Matrix4cd CH; | |||
43 | Eigen::Matrix4cd CV; | |||
44 | Eigen::Matrix4cd CVdg; | |||
45 | Matrix8cd CCX; | |||
46 | Eigen::Matrix4cd SWAP; | |||
47 | Matrix8cd CSWAP; | |||
48 | Matrix8cd BRIDGE; | |||
49 | Eigen::Matrix2cd noop; | |||
50 | Eigen::Matrix4cd ECR; | |||
51 | Eigen::Matrix4cd ZZMax; | |||
52 | Eigen::Matrix4cd Sycamore; | |||
53 | Eigen::Matrix4cd ISWAPMax; | |||
54 | std::array<unsigned, 8> bridge_columns; | |||
55 | std::array<unsigned, 8> cswap_columns; | |||
56 | ||||
57 | 1 | FixedData() { | ||
58 |
4/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
|
1 | X << 0, 1, 1, 0; | |
59 |
4/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
|
1 | Y << 0, -i_, i_, 0; | |
60 |
4/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
|
1 | Z << 1, 0, 0, -1; | |
61 | ||||
62 |
4/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
|
1 | S << 1, 0, 0, i_; | |
63 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | Sdg = S.adjoint(); | |
64 | ||||
65 |
4/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
|
1 | T << 1, 0, 0, std::polar(1.0, 0.25 * PI); | |
66 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | Tdg = T.adjoint(); | |
67 | ||||
68 |
4/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
|
1 | V << 1, -i_, -i_, 1; | |
69 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | V *= std::sqrt(0.5); | |
70 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | Vdg = V.adjoint(); | |
71 | ||||
72 |
4/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
|
1 | H << 1, 1, 1, -1; | |
73 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | H *= std::sqrt(0.5); | |
74 | ||||
75 | 1 | const Complex one_plus_i = i_ + 1.0; | ||
76 | 1 | const Complex one_minus_i = -i_ + 1.0; | ||
77 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
1 | SX << one_plus_i, one_minus_i, one_minus_i, one_plus_i; | |
78 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | SX *= 0.5; | |
79 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | SXdg = SX.adjoint(); | |
80 | ||||
81 |
16/32✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 39 not taken.
✓ Branch 42 taken 1 times.
✗ Branch 43 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✓ Branch 50 taken 1 times.
✗ Branch 51 not taken.
✓ Branch 54 taken 1 times.
✗ Branch 55 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✓ Branch 62 taken 1 times.
✗ Branch 63 not taken.
|
1 | SWAP << 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1; | |
82 | ||||
83 | 1 | bridge_columns = {0, 1, 2, 3, 5, 4, 7, 6}; | ||
84 | 1 | cswap_columns = {0, 1, 2, 3, 4, 6, 5, 7}; | ||
85 | ||||
86 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | BRIDGE = Matrix8cd::Zero(); | |
87 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | CSWAP = BRIDGE; | |
88 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
|
2/2✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 1 times.
|
9 | for (unsigned ii = 0; ii < 8; ++ii) { |
89 |
1/2✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | BRIDGE(ii, bridge_columns[ii]) = 1.0; | |
90 |
1/2✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | CSWAP(ii, cswap_columns[ii]) = 1.0; | |
91 | } | |||
92 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | noop = Eigen::Matrix2cd::Identity(); | |
93 | ||||
94 |
16/32✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 36 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 44 taken 1 times.
✗ Branch 45 not taken.
✓ Branch 48 taken 1 times.
✗ Branch 49 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✓ Branch 56 taken 1 times.
✗ Branch 57 not taken.
✓ Branch 60 taken 1 times.
✗ Branch 61 not taken.
|
1 | ECR << 0, 0, 1, i_, 0, 0, i_, 1, 1, -i_, 0, 0, -i_, 1, 0, 0; | |
95 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | ECR *= std::sqrt(0.5); | |
96 | ||||
97 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | CX = GateUnitaryMatrixUtils::get_controlled_gate_unitary(X); | |
98 | ||||
99 | CCX = | |||
100 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | GateUnitaryMatrixUtils::get_multi_controlled_gate_dense_unitary(CX, 3); | |
101 | ||||
102 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | CY = GateUnitaryMatrixUtils::get_controlled_gate_unitary(Y); | |
103 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | CZ = GateUnitaryMatrixUtils::get_controlled_gate_unitary(Z); | |
104 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | CH = GateUnitaryMatrixUtils::get_controlled_gate_unitary(H); | |
105 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | CV = GateUnitaryMatrixUtils::get_controlled_gate_unitary(V); | |
106 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | CVdg = GateUnitaryMatrixUtils::get_controlled_gate_unitary(Vdg); | |
107 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | CSX = GateUnitaryMatrixUtils::get_controlled_gate_unitary(SX); | |
108 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | CSXdg = GateUnitaryMatrixUtils::get_controlled_gate_unitary(SXdg); | |
109 | ||||
110 | // Accuracy notes: std::sqrt is guaranteed by IEEE 754 | |||
111 | // but std::sin, std::cos are not (although C++ is not guaranteed | |||
112 | // to follow IEEE 754 anyway), so where there is a choice | |||
113 | // (e.g., cos(pi/4) vs. sqrt(2), cos(pi/6) vs. sqrt(3), etc.), | |||
114 | // std::sqrt might be very slightly more accurate, | |||
115 | // but it's not worth worrying about. | |||
116 | // However, note that cos(pi/2), sin(pi), etc. need NOT be exact | |||
117 | // so we should prefer exact values if it's easy to do. | |||
118 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ZZMax = GateUnitaryMatrixImplementations::ZZPhase(0.5); | |
119 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Sycamore = GateUnitaryMatrixImplementations::FSim(0.5, 1.0 / 6.0); | |
120 | ||||
121 | // Equals ISWAP(1) in theory, but ensure the exact result! | |||
122 |
16/32✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 29 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 33 taken 1 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 44 taken 1 times.
✗ Branch 45 not taken.
✓ Branch 48 taken 1 times.
✗ Branch 49 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✓ Branch 56 taken 1 times.
✗ Branch 57 not taken.
✓ Branch 60 taken 1 times.
✗ Branch 61 not taken.
|
1 | ISWAPMax << 1, 0, 0, 0, 0, 0, i_, 0, 0, i_, 0, 0, 0, 0, 0, 1; | |
123 | 1 | } | ||
124 | }; // struct FixedData | |||
125 | ||||
126 | 102831 | const FixedData& get_fixed_data() { | ||
127 | // Remember "Static Initialization Order Fiasco" | |||
128 |
4/8✓ Branch 0 taken 1 times.
✓ Branch 1 taken 102830 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
102831 | static const FixedData data; | |
129 | 102831 | return data; | ||
130 | } | |||
131 | ||||
132 | } // unnamed namespace | |||
133 | ||||
134 | #ifdef GATE_FUNCTION_1Q | |||
135 | #error "Macro already defined!" | |||
136 | #endif | |||
137 | #define GATE_FUNCTION_1Q(funcname) \ | |||
138 | const Eigen::Matrix2cd& GateUnitaryMatrixImplementations::funcname() { \ | |||
139 | return get_fixed_data().funcname; \ | |||
140 | } | |||
141 | 1393 | GATE_FUNCTION_1Q(X) | ||
142 | 520 | GATE_FUNCTION_1Q(Y) | ||
143 | 1196 | GATE_FUNCTION_1Q(Z) | ||
144 | 703 | GATE_FUNCTION_1Q(S) | ||
145 | 342 | GATE_FUNCTION_1Q(Sdg) | ||
146 | 888 | GATE_FUNCTION_1Q(T) | ||
147 | 646 | GATE_FUNCTION_1Q(Tdg) | ||
148 | 1095 | GATE_FUNCTION_1Q(V) | ||
149 | 809 | GATE_FUNCTION_1Q(Vdg) | ||
150 | 19927 | GATE_FUNCTION_1Q(H) | ||
151 | 106 | GATE_FUNCTION_1Q(SX) | ||
152 | 19 | GATE_FUNCTION_1Q(SXdg) | ||
153 | 13 | GATE_FUNCTION_1Q(noop) | ||
154 | #undef GATE_FUNCTION_1Q | |||
155 | ||||
156 | #ifdef GATE_FUNCTION_2Q | |||
157 | #error "Macro already defined!" | |||
158 | #endif | |||
159 | #define GATE_FUNCTION_2Q(funcname) \ | |||
160 | const Eigen::Matrix4cd& GateUnitaryMatrixImplementations::funcname() { \ | |||
161 | return get_fixed_data().funcname; \ | |||
162 | } | |||
163 | 49 | GATE_FUNCTION_2Q(SWAP) | ||
164 | 20 | GATE_FUNCTION_2Q(ECR) | ||
165 | 74444 | GATE_FUNCTION_2Q(CX) | ||
166 | 24 | GATE_FUNCTION_2Q(CY) | ||
167 | 384 | GATE_FUNCTION_2Q(CZ) | ||
168 | 22 | GATE_FUNCTION_2Q(CH) | ||
169 | 18 | GATE_FUNCTION_2Q(CV) | ||
170 | 16 | GATE_FUNCTION_2Q(CVdg) | ||
171 | 18 | GATE_FUNCTION_2Q(CSX) | ||
172 | 16 | GATE_FUNCTION_2Q(CSXdg) | ||
173 | 98 | GATE_FUNCTION_2Q(ZZMax) | ||
174 | 15 | GATE_FUNCTION_2Q(Sycamore) | ||
175 | 15 | GATE_FUNCTION_2Q(ISWAPMax) | ||
176 | #undef GATE_FUNCTION_2Q | |||
177 | ||||
178 | #ifdef GATE_FUNCTION_XQ | |||
179 | #error "Macro already defined!" | |||
180 | #endif | |||
181 | #define GATE_FUNCTION_3Q(funcname) \ | |||
182 | const Matrix8cd& GateUnitaryMatrixImplementations::funcname() { \ | |||
183 | return get_fixed_data().funcname; \ | |||
184 | } | |||
185 | 14 | GATE_FUNCTION_3Q(BRIDGE) | ||
186 | 9 | GATE_FUNCTION_3Q(CCX) | ||
187 | 10 | GATE_FUNCTION_3Q(CSWAP) | ||
188 | #undef GATE_FUNCTION_3Q | |||
189 | ||||
190 | const std::array<unsigned, 8>& | |||
191 | 1 | GateUnitaryMatrixImplementations::get_bridge_columns() { | ||
192 | 1 | return get_fixed_data().bridge_columns; | ||
193 | } | |||
194 | ||||
195 | const std::array<unsigned, 8>& | |||
196 | 1 | GateUnitaryMatrixImplementations::get_cswap_columns() { | ||
197 | 1 | return get_fixed_data().cswap_columns; | ||
198 | } | |||
199 | ||||
200 | } // namespace internal | |||
201 | } // namespace tket | |||
202 |