GCC Code Coverage Report


Directory: ./
File: Gate/GateUnitaryMatrixPrimitives.cpp
Date: 2022-10-15 05:10:18
Exec Total Coverage
Lines: 94 94 100.0%
Functions: 14 14 100.0%
Branches: 80 156 51.3%
Decisions: 4 4 100.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 #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