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 <unsupported/Eigen/KroneckerProduct> | |||
16 | ||||
17 | #include "GateUnitaryMatrixImplementations.hpp" | |||
18 | #include "Utils/Constants.hpp" | |||
19 | ||||
20 | // This file is for gates with unitary matrices which serve as | |||
21 | // building blocks for others ("composite gates"). | |||
22 | // Of course, this choice is subjective and could change. | |||
23 | ||||
24 | namespace tket { | |||
25 | namespace internal { | |||
26 | ||||
27 | 25179 | Eigen::Matrix2cd GateUnitaryMatrixImplementations::Rx(double value) { | ||
28 | 25179 | const double angle = 0.5 * PI * value; | ||
29 | 25179 | const double cc = cos(angle); | ||
30 | 25179 | const double ss = sin(angle); | ||
31 |
1/2✓ Branch 1 taken 25179 times.
✗ Branch 2 not taken.
|
25179 | Eigen::Matrix2cd matr; | |
32 |
4/8✓ Branch 2 taken 25179 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 25179 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 25179 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 25179 times.
✗ Branch 17 not taken.
|
25179 | matr << cc, -i_ * ss, -i_ * ss, cc; | |
33 | 50358 | return matr; | ||
34 | } | |||
35 | ||||
36 | 23054 | Eigen::Matrix2cd GateUnitaryMatrixImplementations::Ry(double value) { | ||
37 | 23054 | const double angle = 0.5 * PI * value; | ||
38 | 23054 | const double cc = cos(angle); | ||
39 | 23054 | const double ss = sin(angle); | ||
40 | 23054 | Eigen::Matrix2cd matr; | ||
41 |
4/8✓ Branch 2 taken 23054 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 23054 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 23054 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 23054 times.
✗ Branch 15 not taken.
|
23054 | matr << cc, -ss, ss, cc; | |
42 | 23054 | return matr; | ||
43 | } | |||
44 | ||||
45 | 54541 | Eigen::Matrix2cd GateUnitaryMatrixImplementations::Rz(double value) { | ||
46 | 54541 | const double angle = 0.5 * PI * value; | ||
47 | 54541 | const double cc = cos(angle); | ||
48 | 54541 | const double ss = sin(angle); | ||
49 |
1/2✓ Branch 1 taken 54541 times.
✗ Branch 2 not taken.
|
54541 | Eigen::Matrix2cd matr; | |
50 |
5/10✓ Branch 2 taken 54541 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 54541 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 54541 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 54541 times.
✗ Branch 14 not taken.
✓ Branch 18 taken 54541 times.
✗ Branch 19 not taken.
|
54541 | matr << cc - i_ * ss, 0, 0, cc + i_ * ss; | |
51 | 109082 | return matr; | ||
52 | } | |||
53 | ||||
54 | 29630 | Eigen::Matrix2cd GateUnitaryMatrixImplementations::U1(double value) { | ||
55 | 29630 | Eigen::Matrix2cd matr; | ||
56 |
4/8✓ Branch 2 taken 29630 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 29630 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 29630 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 29630 times.
✗ Branch 15 not taken.
|
29630 | matr << 1, 0, 0, std::polar(1.0, PI * value); | |
57 | 29630 | return matr; | ||
58 | } | |||
59 | ||||
60 | 112 | Eigen::Matrix4cd GateUnitaryMatrixImplementations::ISWAP(double alpha) { | ||
61 |
1/2✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
|
112 | Eigen::Matrix4cd matr = Eigen::Matrix4cd::Identity(); | |
62 | 112 | const double angle = 0.5 * PI * alpha; | ||
63 | 112 | matr(1, 1) = matr(2, 2) = cos(angle); | ||
64 |
2/4✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 112 times.
✗ Branch 6 not taken.
|
112 | matr(2, 1) = matr(1, 2) = i_ * sin(angle); | |
65 | 112 | return matr; | ||
66 | } | |||
67 | ||||
68 | 5089 | Eigen::Matrix4cd GateUnitaryMatrixImplementations::XXPhase(double alpha) { | ||
69 | 5089 | const double angle = 0.5 * PI * alpha; | ||
70 |
2/4✓ Branch 2 taken 5089 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5089 times.
✗ Branch 6 not taken.
|
5089 | Eigen::Matrix4cd matr = cos(angle) * Eigen::Matrix4cd::Identity(); | |
71 |
4/8✓ Branch 2 taken 5089 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5089 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 5089 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 5089 times.
✗ Branch 12 not taken.
|
5089 | matr(3, 0) = matr(2, 1) = matr(1, 2) = matr(0, 3) = i_ * (-sin(angle)); | |
72 | 5089 | return matr; | ||
73 | } | |||
74 | ||||
75 | 2538 | Eigen::Matrix4cd GateUnitaryMatrixImplementations::YYPhase(double alpha) { | ||
76 | 2538 | auto matr = XXPhase(alpha); | ||
77 | 2538 | matr(3, 0) = matr(0, 3) = std::conj(matr(3, 0)); | ||
78 | 2538 | return matr; | ||
79 | } | |||
80 | ||||
81 | 2573 | Eigen::Matrix4cd GateUnitaryMatrixImplementations::ZZPhase(double alpha) { | ||
82 |
2/4✓ Branch 1 taken 2573 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2573 times.
✗ Branch 5 not taken.
|
2573 | Eigen::Matrix4cd matr = Eigen::Matrix4cd::Zero(); | |
83 | 2573 | const auto exp_entry = std::polar(1.0, 0.5 * PI * alpha); | ||
84 |
2/4✓ Branch 1 taken 2573 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2573 times.
✗ Branch 5 not taken.
|
2573 | matr(1, 1) = matr(2, 2) = exp_entry; | |
85 |
2/4✓ Branch 2 taken 2573 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2573 times.
✗ Branch 6 not taken.
|
2573 | matr(0, 0) = matr(3, 3) = std::conj(exp_entry); | |
86 | 5146 | return matr; | ||
87 | } | |||
88 | ||||
89 | 97 | Matrix8cd GateUnitaryMatrixImplementations::XXPhase3(double alpha) { | ||
90 |
2/4✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
|
97 | Eigen::Matrix2cd PauliI, PauliX; | |
91 |
2/4✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
|
97 | PauliI = Eigen::Matrix2cd::Identity(); | |
92 |
4/8✓ Branch 2 taken 97 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 97 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 97 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 97 times.
✗ Branch 15 not taken.
|
97 | PauliX << 0, 1, 1, 0; | |
93 | ||||
94 |
2/4✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
|
97 | Eigen::Matrix4cd XI = Eigen::kroneckerProduct(PauliX, PauliI); | |
95 |
2/4✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
|
97 | Eigen::Matrix4cd IX = Eigen::kroneckerProduct(PauliI, PauliX); | |
96 |
2/4✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
|
97 | Matrix8cd XXI = Eigen::kroneckerProduct(PauliX, XI); | |
97 |
2/4✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
|
97 | Matrix8cd IXX = Eigen::kroneckerProduct(IX, PauliX); | |
98 |
2/4✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
|
97 | Matrix8cd XIX = Eigen::kroneckerProduct(XI, PauliX); | |
99 | ||||
100 |
4/8✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 97 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 97 times.
✗ Branch 12 not taken.
|
97 | Matrix8cd exponent = -0.5 * alpha * PI * i_ * (XXI + IXX + XIX); | |
101 |
2/4✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
|
97 | Matrix8cd matr = exponent.exp(); | |
102 | ||||
103 | 194 | return matr; | ||
104 | } | |||
105 | ||||
106 | 83 | Eigen::Matrix4cd GateUnitaryMatrixImplementations::ESWAP(double alpha) { | ||
107 |
2/4✓ Branch 1 taken 83 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 83 times.
✗ Branch 5 not taken.
|
83 | Eigen::Matrix4cd matr = Eigen::Matrix4cd::Identity(); | |
108 | 83 | const double angle = 0.5 * PI * alpha; | ||
109 | 83 | const double cc = cos(angle); | ||
110 | 83 | const double ss = sin(angle); | ||
111 |
2/4✓ Branch 2 taken 83 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 83 times.
✗ Branch 6 not taken.
|
83 | matr(0, 0) = matr(3, 3) = std::complex(cc, -ss); | |
112 |
2/4✓ Branch 1 taken 83 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 83 times.
✗ Branch 6 not taken.
|
83 | matr(1, 1) = matr(2, 2) = cc; | |
113 |
2/4✓ Branch 3 taken 83 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 83 times.
✗ Branch 7 not taken.
|
83 | matr(1, 2) = matr(2, 1) = -i_ * ss; | |
114 | 166 | return matr; | ||
115 | } | |||
116 | ||||
117 | 89 | Eigen::Matrix4cd GateUnitaryMatrixImplementations::FSim( | ||
118 | double alpha, double beta) { | |||
119 |
1/2✓ Branch 2 taken 89 times.
✗ Branch 3 not taken.
|
89 | Eigen::Matrix4cd matr = Eigen::Matrix4cd::Identity(); | |
120 | 89 | const double angle = PI * alpha; | ||
121 | 89 | matr(1, 1) = matr(2, 2) = cos(angle); | ||
122 |
2/4✓ Branch 3 taken 89 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 89 times.
✗ Branch 7 not taken.
|
89 | matr(1, 2) = matr(2, 1) = -i_ * sin(angle); | |
123 |
1/2✓ Branch 2 taken 89 times.
✗ Branch 3 not taken.
|
89 | matr(3, 3) = std::polar(1.0, -PI * beta); | |
124 | 89 | return matr; | ||
125 | } | |||
126 | ||||
127 | 73 | Eigen::MatrixXcd GateUnitaryMatrixImplementations::PhaseGadget( | ||
128 | unsigned int number_of_qubits, double alpha) { | |||
129 | const auto diagonal_entries = | |||
130 |
1/2✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
|
73 | PhaseGadget_diagonal_entries(number_of_qubits, alpha); | |
131 |
2/4✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
|
146 | return diagonal_entries.asDiagonal(); | |
132 | 73 | } | ||
133 | ||||
134 | // Returns either 0 or 1. | |||
135 | 978 | static unsigned number_of_bits_mod_2_in_binary_expansion(unsigned ii) { | ||
136 | 978 | unsigned result = 0; | ||
137 |
2/2✓ Branch 0 taken 1744 times.
✓ Branch 1 taken 978 times.
|
2/2✓ Decision 'true' taken 1744 times.
✓ Decision 'false' taken 978 times.
|
2722 | while (ii > 0) { |
138 | // Standard trick: if the bits of i are abc...z10...0, | |||
139 | // then ~ii = ~(abc...z) 01...1 | |||
140 | 1744 | unsigned next_bit = (~ii + 1) & ii; | ||
141 | 1744 | result = 1 - result; | ||
142 | 1744 | ii &= ~next_bit; | ||
143 | } | |||
144 | 978 | return result; | ||
145 | } | |||
146 | ||||
147 | 120 | Eigen::VectorXcd GateUnitaryMatrixImplementations::PhaseGadget_diagonal_entries( | ||
148 | unsigned int number_of_qubits, double alpha) { | |||
149 | // We will count the bits in the binary expansion and reduce mod 2. | |||
150 |
1/2✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
|
120 | const unsigned size = get_matrix_size(number_of_qubits); | |
151 |
1/2✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
|
120 | Eigen::VectorXcd result(size); | |
152 | ||||
153 | 120 | std::array<std::complex<double>, 2> diagonal_terms; | ||
154 | 120 | diagonal_terms[1] = std::polar(1.0, 0.5 * PI * alpha); | ||
155 | 120 | diagonal_terms[0] = std::conj(diagonal_terms[1]); | ||
156 | ||||
157 |
2/2✓ Branch 0 taken 978 times.
✓ Branch 1 taken 120 times.
|
2/2✓ Decision 'true' taken 978 times.
✓ Decision 'false' taken 120 times.
|
1098 | for (unsigned ii = 0; ii < size; ++ii) { |
158 | // Could also do this iteratively/recursively, | |||
159 | // but maybe not much faster (surely no more than 20 bits, so the | |||
160 | // number_of_bits function is effectively constant time | |||
161 | // with a not too large constant) | |||
162 |
1/2✓ Branch 3 taken 978 times.
✗ Branch 4 not taken.
|
978 | result[ii] = diagonal_terms[number_of_bits_mod_2_in_binary_expansion(ii)]; | |
163 | } | |||
164 | 240 | return result; | ||
165 | } | |||
166 | ||||
167 | } // namespace internal | |||
168 | } // namespace tket | |||
169 |