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 "PauliStrings.hpp" | |||
16 | ||||
17 | #include <map> | |||
18 | #include <sstream> | |||
19 | #include <stdexcept> | |||
20 | #include <string> | |||
21 | #include <tkassert/Assert.hpp> | |||
22 | #include <utility> | |||
23 | #include <vector> | |||
24 | ||||
25 | #include "Utils/Constants.hpp" | |||
26 | #include "Utils/EigenConfig.hpp" | |||
27 | #include "Utils/Json.hpp" | |||
28 | ||||
29 | namespace tket { | |||
30 | ||||
31 | 4 | static const CmplxSpMat const_2x2_matrix( | ||
32 | Complex tl, Complex tr, Complex bl, Complex br) { | |||
33 | 4 | CmplxSpMat m(2, 2); | ||
34 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 2 times.
|
4 | if (tl != czero) { |
35 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m.insert(0, 0) = tl; | |
36 | } | |||
37 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 2 times.
|
4 | if (tr != czero) { |
38 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m.insert(0, 1) = tr; | |
39 | } | |||
40 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 2 times.
|
4 | if (bl != czero) { |
41 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m.insert(1, 0) = bl; | |
42 | } | |||
43 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 2 times.
|
4 | if (br != czero) { |
44 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m.insert(1, 1) = br; | |
45 | } | |||
46 | 4 | return m; | ||
47 | } | |||
48 | ||||
49 | 53 | static const CmplxSpMat &pauli_sparse_mat(Pauli p) { | ||
50 |
4/8✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
53 | static const CmplxSpMat I_mat = const_2x2_matrix(1, 0, 0, 1); | |
51 |
4/8✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
53 | static const CmplxSpMat X_mat = const_2x2_matrix(0, 1, 1, 0); | |
52 |
4/8✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
53 | static const CmplxSpMat Y_mat = const_2x2_matrix(0, -i_, i_, 0); | |
53 |
4/8✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
53 | static const CmplxSpMat Z_mat = const_2x2_matrix(1, 0, 0, -1); | |
54 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 9 times.
|
53 | switch (p) { | |
55 |
1/1✓ Decision 'true' taken 28 times.
|
28 | case Pauli::X: | |
56 | 28 | return X_mat; | ||
57 |
1/1✓ Decision 'true' taken 4 times.
|
4 | case Pauli::Y: | |
58 | 4 | return Y_mat; | ||
59 |
1/1✓ Decision 'true' taken 12 times.
|
12 | case Pauli::Z: | |
60 | 12 | return Z_mat; | ||
61 |
0/1✗ Decision 'true' not taken.
|
9 | default: | |
62 | TKET_ASSERT(p == Pauli::I); | |||
63 | 9 | return I_mat; | ||
64 | } | |||
65 | } | |||
66 | ||||
67 | class StateNotPowerTwo : public std::logic_error { | |||
68 | public: | |||
69 | ✗ | StateNotPowerTwo() | ||
70 | ✗ | : std::logic_error("Statevector size is not a power of two.") {} | ||
71 | }; | |||
72 | ||||
73 | 2 | unsigned get_n_qb_from_statevector(const Eigen::VectorXcd &state) { | ||
74 | // allowing room for big states | |||
75 | 2 | unsigned long long n = state.size(); | ||
76 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 2 times.
|
2 | if (!(n && (!(n & (n - 1))))) { |
77 | ✗ | throw StateNotPowerTwo(); | ||
78 | } | |||
79 | ||||
80 | 2 | unsigned count = 0; | ||
81 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
2/2✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 2 times.
|
8 | while (n) { |
82 | 6 | n >>= 1; | ||
83 | 6 | ++count; | ||
84 | } | |||
85 | 2 | return count - 1; | ||
86 | } | |||
87 | ||||
88 | ✗ | CmplxSpMat QubitPauliString::to_sparse_matrix() const { | ||
89 | ✗ | qubit_vector_t qubits(map.size()); | ||
90 | ✗ | unsigned i = 0; | ||
91 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | for (const std::pair<const Qubit, Pauli> &pair : map) { | |
92 | ✗ | qubits[i] = pair.first; | ||
93 | ✗ | ++i; | ||
94 | } | |||
95 | ✗ | return to_sparse_matrix(qubits); | ||
96 | } | |||
97 | ||||
98 | 27 | CmplxSpMat QubitPauliString::to_sparse_matrix(const unsigned n_qubits) const { | ||
99 |
1/2✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
|
27 | qubit_vector_t qubits(n_qubits); | |
100 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 27 times.
|
2/2✓ Decision 'true' taken 53 times.
✓ Decision 'false' taken 27 times.
|
80 | for (unsigned i = 0; i < n_qubits; ++i) { |
101 |
1/2✓ Branch 1 taken 53 times.
✗ Branch 2 not taken.
|
53 | qubits[i] = Qubit(i); | |
102 | } | |||
103 |
1/2✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
|
54 | return to_sparse_matrix(qubits); | |
104 | 27 | } | ||
105 | ||||
106 | 29 | CmplxSpMat QubitPauliString::to_sparse_matrix( | ||
107 | const qubit_vector_t &qubits) const { | |||
108 |
1/2✓ Branch 3 taken 29 times.
✗ Branch 4 not taken.
|
29 | std::vector<Pauli> paulis(qubits.size(), Pauli::I); | |
109 | 29 | std::map<Qubit, unsigned> index_map; | ||
110 | 29 | unsigned index = 0; | ||
111 |
2/2✓ Branch 4 taken 58 times.
✓ Branch 5 taken 29 times.
|
2/2✓ Decision 'true' taken 58 times.
✓ Decision 'false' taken 29 times.
|
87 | for (const Qubit &q : qubits) { |
112 |
1/2✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
|
58 | index_map.insert({q, index}); | |
113 | 58 | ++index; | ||
114 | } | |||
115 |
2/2✓ Branch 2 taken 1 times.
✓ Branch 3 taken 28 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 28 times.
|
29 | if (index_map.size() != qubits.size()) |
116 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | throw std::logic_error( | |
117 | 2 | "Qubit list given to to_sparse_matrix contains repeats"); | ||
118 |
2/2✓ Branch 4 taken 55 times.
✓ Branch 5 taken 27 times.
|
2/2✓ Decision 'true' taken 55 times.
✓ Decision 'false' taken 27 times.
|
82 | for (const std::pair<const Qubit, Pauli> &pair : map) { |
119 |
1/2✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
|
55 | std::map<Qubit, unsigned>::iterator found = index_map.find(pair.first); | |
120 |
2/2✓ Branch 2 taken 1 times.
✓ Branch 3 taken 54 times.
|
2/2✓ Decision 'true' taken 1 times.
✓ Decision 'false' taken 54 times.
|
55 | if (found == index_map.end()) |
121 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | throw std::logic_error( | |
122 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | "Qubit list given to to_sparse_matrix doesn't contain " + | |
123 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | pair.first.repr()); | |
124 |
1/2✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
|
54 | paulis.at(found->second) = pair.second; | |
125 | } | |||
126 |
1/2✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
|
27 | CmplxSpMat result(1, 1); | |
127 |
1/2✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
|
27 | result.insert(0, 0) = 1; | |
128 |
2/2✓ Branch 5 taken 53 times.
✓ Branch 6 taken 27 times.
|
2/2✓ Decision 'true' taken 53 times.
✓ Decision 'false' taken 27 times.
|
80 | for (Pauli p : paulis) { |
129 |
2/4✓ Branch 1 taken 53 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 53 times.
✗ Branch 5 not taken.
|
53 | const CmplxSpMat pauli_mat = pauli_sparse_mat(p); | |
130 |
3/6✓ Branch 1 taken 53 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 53 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 53 times.
✗ Branch 8 not taken.
|
53 | result = Eigen::KroneckerProductSparse(result, pauli_mat).eval(); | |
131 | 53 | } | ||
132 | 54 | return result; | ||
133 | 31 | } | ||
134 | ||||
135 | ✗ | CmplxSpMat operator_tensor( | ||
136 | const OperatorSum &total_operator, unsigned n_qubits) { | |||
137 | ✗ | qubit_vector_t qubits(n_qubits); | ||
138 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | for (unsigned i = 0; i < n_qubits; ++i) { | |
139 | ✗ | qubits[i] = Qubit(i); | ||
140 | } | |||
141 | ✗ | return operator_tensor(total_operator, qubits); | ||
142 | } | |||
143 | ||||
144 | ✗ | CmplxSpMat operator_tensor( | ||
145 | const OperatorSum &total_operator, const qubit_vector_t &qubits) { | |||
146 | ✗ | CmplxSpMat sum = total_operator[0].second * | ||
147 | ✗ | total_operator[0].first.to_sparse_matrix(qubits); | ||
148 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | for (unsigned j = 1; j < total_operator.size(); j++) { | |
149 | ✗ | sum += total_operator[j].second * | ||
150 | ✗ | total_operator[j].first.to_sparse_matrix(qubits); | ||
151 | } | |||
152 | ✗ | return sum; | ||
153 | } | |||
154 | ||||
155 | 2 | Eigen::VectorXcd QubitPauliString::dot_state( | ||
156 | const Eigen::VectorXcd &state) const { | |||
157 | 2 | const unsigned n_qubits = get_n_qb_from_statevector(state); | ||
158 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | return (to_sparse_matrix(n_qubits) * state); | |
159 | } | |||
160 | ||||
161 | ✗ | Eigen::VectorXcd QubitPauliString::dot_state( | ||
162 | const Eigen::VectorXcd &state, const qubit_vector_t &qubits) const { | |||
163 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | if (state.size() != 1 << qubits.size()) | |
164 | ✗ | throw std::logic_error( | ||
165 | "Size of statevector does not match number of qubits passed to " | |||
166 | ✗ | "dot_state"); | ||
167 | ✗ | return (to_sparse_matrix(qubits) * state); | ||
168 | } | |||
169 | ||||
170 | 1 | Complex QubitPauliString::state_expectation( | ||
171 | const Eigen::VectorXcd &state) const { | |||
172 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | return state.dot(dot_state(state)); | |
173 | } | |||
174 | ||||
175 | ✗ | Complex QubitPauliString::state_expectation( | ||
176 | const Eigen::VectorXcd &state, const qubit_vector_t &qubits) const { | |||
177 | ✗ | return state.dot(dot_state(state, qubits)); | ||
178 | } | |||
179 | ||||
180 | ✗ | Complex operator_expectation( | ||
181 | const OperatorSum &total_operator, const Eigen::VectorXcd &state) { | |||
182 | ✗ | Complex exp(0, 0); | ||
183 | ||||
184 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | for (unsigned j = 0; j < total_operator.size(); j++) { | |
185 | ✗ | exp += total_operator[j].second * | ||
186 | ✗ | total_operator[j].first.state_expectation(state); | ||
187 | } | |||
188 | ||||
189 | ✗ | return exp; | ||
190 | } | |||
191 | ||||
192 | ✗ | Complex operator_expectation( | ||
193 | const OperatorSum &total_operator, const Eigen::VectorXcd &state, | |||
194 | const qubit_vector_t &qubits) { | |||
195 | ✗ | Complex exp(0, 0); | ||
196 | ||||
197 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | for (unsigned j = 0; j < total_operator.size(); j++) { | |
198 | ✗ | exp += total_operator[j].second * | ||
199 | ✗ | total_operator[j].first.state_expectation(state, qubits); | ||
200 | } | |||
201 | ||||
202 | ✗ | return exp; | ||
203 | } | |||
204 | ||||
205 | 85 | QubitPauliString::QubitPauliString(const std::list<Pauli> &_paulis) { | ||
206 | 85 | unsigned qb_i = 0; | ||
207 |
2/2✓ Branch 4 taken 427 times.
✓ Branch 5 taken 85 times.
|
2/2✓ Decision 'true' taken 427 times.
✓ Decision 'false' taken 85 times.
|
512 | for (Pauli p : _paulis) { |
208 |
2/4✓ Branch 1 taken 427 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 427 times.
✗ Branch 5 not taken.
|
427 | map[Qubit(qb_i)] = p; | |
209 | 427 | ++qb_i; | ||
210 | } | |||
211 | 85 | } | ||
212 | ||||
213 | 76 | QubitPauliString::QubitPauliString( | ||
214 | 76 | const std::list<Qubit> &qubits, const std::list<Pauli> &paulis) { | ||
215 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 76 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 76 times.
|
76 | if (qubits.size() != paulis.size()) { |
216 | ✗ | throw std::logic_error( | ||
217 | "Mismatch of Qubits and Paulis upon QubitPauliString " | |||
218 | ✗ | "construction"); | ||
219 | } | |||
220 | 76 | std::list<Pauli>::const_iterator p_it = paulis.begin(); | ||
221 |
2/2✓ Branch 5 taken 228 times.
✓ Branch 6 taken 76 times.
|
2/2✓ Decision 'true' taken 228 times.
✓ Decision 'false' taken 76 times.
|
304 | for (const Qubit &qb : qubits) { |
222 | 228 | Pauli p = *p_it; | ||
223 |
2/4✓ Branch 2 taken 228 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 228 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 228 times.
|
228 | if (map.find(qb) != map.end()) { |
224 | ✗ | throw std::logic_error( | ||
225 | ✗ | "Non-unique Qubit inserted into QubitPauliString map"); | ||
226 | } | |||
227 |
1/2✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
|
228 | map[qb] = p; | |
228 | 228 | ++p_it; | ||
229 | } | |||
230 | 76 | } | ||
231 | ||||
232 | 1533 | bool QubitPauliString::operator==(const QubitPauliString &other) const { | ||
233 | 1533 | return compare(other) == 0; | ||
234 | } | |||
235 | ||||
236 | ✗ | bool QubitPauliString::operator!=(const QubitPauliString &other) const { | ||
237 | ✗ | return !(*this == other); | ||
238 | } | |||
239 | ||||
240 | 735 | bool QubitPauliString::operator<(const QubitPauliString &other) const { | ||
241 | 735 | return compare(other) < 0; | ||
242 | } | |||
243 | ||||
244 | 4316 | int QubitPauliString::compare(const QubitPauliString &other) const { | ||
245 | 4316 | QubitPauliMap::const_iterator p1_it = this->map.begin(); | ||
246 | 4316 | QubitPauliMap::const_iterator p2_it = other.map.begin(); | ||
247 |
2/2✓ Branch 2 taken 6286 times.
✓ Branch 3 taken 1095 times.
|
2/2✓ Decision 'true' taken 6286 times.
✓ Decision 'false' taken 1095 times.
|
7381 | while (p1_it != this->map.end()) { |
248 |
2/2✓ Branch 1 taken 66 times.
✓ Branch 2 taken 6220 times.
|
2/2✓ Decision 'true' taken 66 times.
✓ Decision 'false' taken 6220 times.
|
6286 | if (p1_it->second == Pauli::I) { |
249 | 66 | ++p1_it; | ||
250 | 66 | continue; | ||
251 | } | |||
252 |
6/6✓ Branch 2 taken 6044 times.
✓ Branch 3 taken 192 times.
✓ Branch 5 taken 16 times.
✓ Branch 6 taken 6028 times.
✓ Branch 7 taken 16 times.
✓ Branch 8 taken 6220 times.
|
0/1? Decision couldn't be analyzed.
|
6236 | while (p2_it != other.map.end() && p2_it->second == Pauli::I) { |
253 | 16 | ++p2_it; | ||
254 | } | |||
255 |
2/2✓ Branch 2 taken 192 times.
✓ Branch 3 taken 6028 times.
|
2/2✓ Decision 'true' taken 6028 times.
✓ Decision 'false' taken 192 times.
|
6220 | if (p2_it == other.map.end()) return 1; |
256 | // QubitPauliString order should reflect ILO | |||
257 | // i.e. IZ < ZI (Zq1 < Zq0) | |||
258 | // Hence we first order by reverse of leading qubit | |||
259 |
3/4✓ Branch 3 taken 6028 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 599 times.
✓ Branch 6 taken 5429 times.
|
2/2✓ Decision 'true' taken 5429 times.
✓ Decision 'false' taken 599 times.
|
6028 | if (p1_it->first < p2_it->first) return 1; |
260 |
3/4✓ Branch 3 taken 5429 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 948 times.
✓ Branch 6 taken 4481 times.
|
2/2✓ Decision 'true' taken 4481 times.
✓ Decision 'false' taken 948 times.
|
5429 | if (p2_it->first < p1_it->first) return -1; |
261 | // and then by increasing order of Pauli letter on the same qubit | |||
262 |
2/2✓ Branch 2 taken 1076 times.
✓ Branch 3 taken 3405 times.
|
2/2✓ Decision 'true' taken 3405 times.
✓ Decision 'false' taken 1076 times.
|
4481 | if (p1_it->second < p2_it->second) return -1; |
263 |
2/2✓ Branch 2 taken 406 times.
✓ Branch 3 taken 2999 times.
|
2/2✓ Decision 'true' taken 2999 times.
✓ Decision 'false' taken 406 times.
|
3405 | if (p1_it->second > p2_it->second) return 1; |
264 | 2999 | ++p1_it; | ||
265 | 2999 | ++p2_it; | ||
266 | } | |||
267 |
6/6✓ Branch 2 taken 435 times.
✓ Branch 3 taken 675 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 420 times.
✓ Branch 7 taken 15 times.
✓ Branch 8 taken 1095 times.
|
0/1? Decision couldn't be analyzed.
|
1110 | while (p2_it != other.map.end() && p2_it->second == Pauli::I) { |
268 | 15 | ++p2_it; | ||
269 | } | |||
270 |
2/2✓ Branch 2 taken 675 times.
✓ Branch 3 taken 420 times.
|
1095 | return (p2_it == other.map.end()) ? 0 : -1; | |
271 | } | |||
272 | ||||
273 | 136 | void QubitPauliString::compress() { | ||
274 | 136 | QubitPauliMap::iterator i = map.begin(); | ||
275 |
2/2✓ Branch 2 taken 336 times.
✓ Branch 3 taken 136 times.
|
2/2✓ Decision 'true' taken 336 times.
✓ Decision 'false' taken 136 times.
|
472 | while (i != map.end()) { |
276 |
2/2✓ Branch 1 taken 15 times.
✓ Branch 2 taken 321 times.
|
2/2✓ Decision 'true' taken 15 times.
✓ Decision 'false' taken 321 times.
|
336 | if (i->second == Pauli::I) { |
277 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | i = map.erase(i); | |
278 | } else { | |||
279 | 321 | ++i; | ||
280 | } | |||
281 | } | |||
282 | 136 | } | ||
283 | ||||
284 | 2022 | bool QubitPauliString::commutes_with(const QubitPauliString &other) const { | ||
285 | 2022 | return (conflicting_qubits(other).size() % 2) == 0; | ||
286 | } | |||
287 | ||||
288 | 68 | std::set<Qubit> QubitPauliString::common_qubits( | ||
289 | const QubitPauliString &other) const { | |||
290 | 68 | std::set<Qubit> common; | ||
291 |
2/2✓ Branch 5 taken 150 times.
✓ Branch 6 taken 68 times.
|
2/2✓ Decision 'true' taken 150 times.
✓ Decision 'false' taken 68 times.
|
218 | for (const std::pair<const Qubit, Pauli> &p : map) { |
292 |
1/2✓ Branch 1 taken 150 times.
✗ Branch 2 not taken.
|
150 | QubitPauliMap::const_iterator found = other.map.find(p.first); | |
293 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
|
1/2✓ Decision 'true' taken 150 times.
✗ Decision 'false' not taken.
|
150 | if (p.second == Pauli::I) continue; |
294 |
6/6✓ Branch 2 taken 132 times.
✓ Branch 3 taken 18 times.
✓ Branch 5 taken 69 times.
✓ Branch 6 taken 63 times.
✓ Branch 7 taken 69 times.
✓ Branch 8 taken 81 times.
|
2/2✓ Decision 'true' taken 69 times.
✓ Decision 'false' taken 81 times.
|
150 | if (found != other.map.end() && found->second == p.second) { |
295 |
1/2✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
|
69 | common.insert(p.first); | |
296 | } | |||
297 | } | |||
298 | 68 | return common; | ||
299 | } | |||
300 | ||||
301 | 136 | std::set<Qubit> QubitPauliString::own_qubits( | ||
302 | const QubitPauliString &other) const { | |||
303 | 136 | std::set<Qubit> own; | ||
304 |
2/2✓ Branch 5 taken 321 times.
✓ Branch 6 taken 136 times.
|
2/2✓ Decision 'true' taken 321 times.
✓ Decision 'false' taken 136 times.
|
457 | for (const std::pair<const Qubit, Pauli> &p : map) { |
305 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 321 times.
|
1/2✓ Decision 'true' taken 321 times.
✗ Decision 'false' not taken.
|
321 | if (p.second == Pauli::I) continue; |
306 |
1/2✓ Branch 1 taken 321 times.
✗ Branch 2 not taken.
|
321 | QubitPauliMap::const_iterator found = other.map.find(p.first); | |
307 |
5/6✓ Branch 2 taken 264 times.
✓ Branch 3 taken 57 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 264 times.
✓ Branch 7 taken 57 times.
✓ Branch 8 taken 264 times.
|
2/2✓ Decision 'true' taken 57 times.
✓ Decision 'false' taken 264 times.
|
321 | if (found == other.map.end() || found->second == Pauli::I) { |
308 |
1/2✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
|
57 | own.insert(p.first); | |
309 | } | |||
310 | } | |||
311 | 136 | return own; | ||
312 | } | |||
313 | ||||
314 | 2159 | std::set<Qubit> QubitPauliString::conflicting_qubits( | ||
315 | const QubitPauliString &other) const { | |||
316 | 2159 | std::set<Qubit> conflicts; | ||
317 |
2/2✓ Branch 5 taken 4636 times.
✓ Branch 6 taken 2159 times.
|
2/2✓ Decision 'true' taken 4636 times.
✓ Decision 'false' taken 2159 times.
|
6795 | for (const std::pair<const Qubit, Pauli> &p : map) { |
318 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 4600 times.
|
2/2✓ Decision 'true' taken 4600 times.
✓ Decision 'false' taken 36 times.
|
4636 | if (p.second == Pauli::I) continue; |
319 |
1/2✓ Branch 1 taken 4600 times.
✗ Branch 2 not taken.
|
4600 | QubitPauliMap::const_iterator found = other.map.find(p.first); | |
320 |
6/6✓ Branch 2 taken 2534 times.
✓ Branch 3 taken 2066 times.
✓ Branch 5 taken 2504 times.
✓ Branch 6 taken 30 times.
✓ Branch 7 taken 1513 times.
✓ Branch 8 taken 3087 times.
|
2/2✓ Decision 'true' taken 1513 times.
✓ Decision 'false' taken 5591 times.
|
7104 | if (found != other.map.end() && found->second != Pauli::I && |
321 |
2/2✓ Branch 1 taken 1513 times.
✓ Branch 2 taken 991 times.
|
2504 | found->second != p.second) { | |
322 |
1/2✓ Branch 1 taken 1513 times.
✗ Branch 2 not taken.
|
1513 | conflicts.insert(p.first); | |
323 | } | |||
324 | } | |||
325 | 2159 | return conflicts; | ||
326 | } | |||
327 | ||||
328 | 6 | std::string QubitPauliString::to_str() const { | ||
329 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | std::stringstream d; | |
330 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | d << "("; | |
331 | 6 | QubitPauliMap::const_iterator i = map.begin(); | ||
332 |
2/2✓ Branch 2 taken 7 times.
✓ Branch 3 taken 6 times.
|
2/2✓ Decision 'true' taken 7 times.
✓ Decision 'false' taken 6 times.
|
13 | while (i != map.end()) { |
333 |
3/5✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
7 | switch (i->second) { | |
334 |
0/1✗ Decision 'true' not taken.
|
✗ | case Pauli::I: { | |
335 | ✗ | d << "I"; | ||
336 | ✗ | break; | ||
337 | } | |||
338 |
1/1✓ Decision 'true' taken 1 times.
|
1 | case Pauli::X: { | |
339 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | d << "X"; | |
340 | 1 | break; | ||
341 | } | |||
342 |
1/1✓ Decision 'true' taken 3 times.
|
3 | case Pauli::Y: { | |
343 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | d << "Y"; | |
344 | 3 | break; | ||
345 | } | |||
346 |
1/1✓ Decision 'true' taken 3 times.
|
3 | case Pauli::Z: { | |
347 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | d << "Z"; | |
348 | 3 | break; | ||
349 | } | |||
350 | } | |||
351 |
2/4✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
|
7 | d << i->first.repr(); | |
352 | 7 | i++; | ||
353 |
3/4✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2/2✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 1 times.
|
7 | if (i != map.end()) d << ", "; |
354 | } | |||
355 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | d << ")"; | |
356 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
12 | return d.str(); | |
357 | 6 | } | ||
358 | ||||
359 | ✗ | Pauli QubitPauliString::get(const Qubit &q) const { | ||
360 | ✗ | QubitPauliMap::const_iterator i = map.find(q); | ||
361 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | if (i == map.end()) | |
362 | ✗ | return Pauli::I; | ||
363 | else | |||
364 | ✗ | return i->second; | ||
365 | } | |||
366 | ||||
367 | 12 | void QubitPauliString::set(const Qubit &q, Pauli p) { | ||
368 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | QubitPauliMap::iterator i = map.find(q); | |
369 |
1/2✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
1/2✓ Decision 'true' taken 12 times.
✗ Decision 'false' not taken.
|
12 | if (i == map.end()) { |
370 |
3/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 12 times.
|
12 | if (p != Pauli::I) map.insert({q, p}); |
371 | } else { | |||
372 |
0/2✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
✗ | if (p == Pauli::I) | |
373 | ✗ | map.erase(i); | ||
374 | else | |||
375 | ✗ | i->second = p; | ||
376 | } | |||
377 | 12 | } | ||
378 | ||||
379 | 189 | std::size_t hash_value(const QubitPauliString &qps) { | ||
380 | 189 | size_t seed = 0; | ||
381 |
2/2✓ Branch 5 taken 513 times.
✓ Branch 6 taken 189 times.
|
2/2✓ Decision 'true' taken 513 times.
✓ Decision 'false' taken 189 times.
|
702 | for (const std::pair<const Qubit, Pauli> &qb_p : qps.map) { |
382 |
2/2✓ Branch 0 taken 494 times.
✓ Branch 1 taken 19 times.
|
2/2✓ Decision 'true' taken 494 times.
✓ Decision 'false' taken 19 times.
|
513 | if (qb_p.second != Pauli::I) { |
383 |
1/2✓ Branch 1 taken 494 times.
✗ Branch 2 not taken.
|
494 | boost::hash_combine(seed, qb_p.first); | |
384 |
1/2✓ Branch 1 taken 494 times.
✗ Branch 2 not taken.
|
494 | boost::hash_combine(seed, qb_p.second); | |
385 | } | |||
386 | } | |||
387 | 189 | return seed; | ||
388 | } | |||
389 | ||||
390 | 19 | void to_json(nlohmann::json &j, const QubitPauliString &paulistr) { | ||
391 | 19 | j = nlohmann::json::array(); | ||
392 |
2/2✓ Branch 6 taken 27 times.
✓ Branch 7 taken 19 times.
|
2/2✓ Decision 'true' taken 27 times.
✓ Decision 'false' taken 19 times.
|
46 | for (const auto &[qb, pauli] : paulistr.map) { |
393 |
5/10✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 27 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 27 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 54 times.
✓ Branch 10 taken 27 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
81 | j.push_back({qb, pauli}); | |
394 | } | |||
395 | 19 | } | ||
396 | ||||
397 | 8 | void from_json(const nlohmann::json &j, QubitPauliString &paulistr) { | ||
398 |
4/6✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✓ Branch 9 taken 8 times.
|
0/1? Decision couldn't be analyzed.
|
20 | for (const auto &qb_pauli : j) { |
399 |
6/12✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 12 times.
✗ Branch 18 not taken.
|
12 | paulistr.set(qb_pauli[0].get<Qubit>(), qb_pauli[1].get<Pauli>()); | |
400 | } | |||
401 | 8 | } | ||
402 | ||||
403 | 585 | const QubitPauliTensor::Mult_Matrix &QubitPauliTensor::get_mult_matrix() { | ||
404 | static const Mult_Matrix mult_matrix{ | |||
405 | {{Pauli::I, Pauli::I}, {1., Pauli::I}}, | |||
406 | {{Pauli::I, Pauli::X}, {1., Pauli::X}}, | |||
407 | {{Pauli::I, Pauli::Y}, {1., Pauli::Y}}, | |||
408 | {{Pauli::I, Pauli::Z}, {1., Pauli::Z}}, | |||
409 | {{Pauli::X, Pauli::I}, {1., Pauli::X}}, | |||
410 | {{Pauli::X, Pauli::X}, {1., Pauli::I}}, | |||
411 | {{Pauli::X, Pauli::Y}, {i_, Pauli::Z}}, | |||
412 | {{Pauli::X, Pauli::Z}, {-i_, Pauli::Y}}, | |||
413 | {{Pauli::Y, Pauli::I}, {1., Pauli::Y}}, | |||
414 | {{Pauli::Y, Pauli::X}, {-i_, Pauli::Z}}, | |||
415 | {{Pauli::Y, Pauli::Y}, {1., Pauli::I}}, | |||
416 | {{Pauli::Y, Pauli::Z}, {i_, Pauli::X}}, | |||
417 | {{Pauli::Z, Pauli::I}, {1., Pauli::Z}}, | |||
418 | {{Pauli::Z, Pauli::X}, {i_, Pauli::Y}}, | |||
419 | {{Pauli::Z, Pauli::Y}, {-i_, Pauli::X}}, | |||
420 |
4/8✓ Branch 0 taken 1 times.
✓ Branch 1 taken 584 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
585 | {{Pauli::Z, Pauli::Z}, {1., Pauli::I}}}; | |
421 | 585 | return mult_matrix; | ||
422 | } | |||
423 | ||||
424 | 2567 | QubitPauliTensor QubitPauliTensor::operator*( | ||
425 | const QubitPauliTensor &other) const { | |||
426 | 2567 | QubitPauliTensor result(this->coeff * other.coeff); | ||
427 | 2567 | QubitPauliMap::const_iterator p1i = this->string.map.begin(); | ||
428 | 2567 | QubitPauliMap::const_iterator p2i = other.string.map.begin(); | ||
429 |
2/2✓ Branch 2 taken 2346 times.
✓ Branch 3 taken 2567 times.
|
2/2✓ Decision 'true' taken 2346 times.
✓ Decision 'false' taken 2567 times.
|
4913 | while (p1i != this->string.map.end()) { |
430 |
7/8✓ Branch 2 taken 2328 times.
✓ Branch 3 taken 148 times.
✓ Branch 7 taken 2328 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 130 times.
✓ Branch 10 taken 2198 times.
✓ Branch 11 taken 130 times.
✓ Branch 12 taken 2346 times.
|
0/1? Decision couldn't be analyzed.
|
2476 | while (p2i != other.string.map.end() && p2i->first < p1i->first) { |
431 |
1/2✓ Branch 2 taken 130 times.
✗ Branch 3 not taken.
|
130 | result.string.map.insert(*p2i); | |
432 | 130 | p2i++; | ||
433 | } | |||
434 |
7/8✓ Branch 2 taken 2198 times.
✓ Branch 3 taken 148 times.
✓ Branch 7 taken 2198 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 579 times.
✓ Branch 10 taken 1619 times.
✓ Branch 11 taken 579 times.
✓ Branch 12 taken 1767 times.
|
2/2✓ Decision 'true' taken 579 times.
✓ Decision 'false' taken 1767 times.
|
2346 | if (p2i != other.string.map.end() && p2i->first == p1i->first) { |
435 | // Pauli in the same position, so need to multiply | |||
436 | const std::pair<Complex, Pauli> &prod = | |||
437 |
2/4✓ Branch 1 taken 579 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 579 times.
✗ Branch 8 not taken.
|
579 | QubitPauliTensor::get_mult_matrix().at({p1i->second, p2i->second}); | |
438 | 579 | result.coeff *= prod.first; | ||
439 |
2/2✓ Branch 0 taken 421 times.
✓ Branch 1 taken 158 times.
|
2/2✓ Decision 'true' taken 421 times.
✓ Decision 'false' taken 158 times.
|
579 | if (prod.second != Pauli::I) { |
440 |
1/2✓ Branch 3 taken 421 times.
✗ Branch 4 not taken.
|
421 | result.string.map.insert({p1i->first, prod.second}); | |
441 | } | |||
442 | 579 | p2i++; | ||
443 | } else { | |||
444 |
1/2✓ Branch 2 taken 1767 times.
✗ Branch 3 not taken.
|
1767 | result.string.map.insert(*p1i); | |
445 | } | |||
446 | 2346 | p1i++; | ||
447 | } | |||
448 |
2/2✓ Branch 2 taken 2303 times.
✓ Branch 3 taken 2567 times.
|
2/2✓ Decision 'true' taken 2303 times.
✓ Decision 'false' taken 2567 times.
|
4870 | while (p2i != other.string.map.end()) { |
449 |
1/2✓ Branch 2 taken 2303 times.
✗ Branch 3 not taken.
|
2303 | result.string.map.insert(*p2i); | |
450 | 2303 | p2i++; | ||
451 | } | |||
452 | 5134 | return result; | ||
453 | } | |||
454 | ||||
455 | 221 | bool QubitPauliTensor::operator==(const QubitPauliTensor &other) const { | ||
456 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 217 times.
|
2/2✓ Decision 'true' taken 217 times.
✓ Decision 'false' taken 4 times.
|
221 | if (this->coeff != other.coeff) return false; |
457 | 217 | return (this->string == other.string); | ||
458 | } | |||
459 | ||||
460 | 163 | bool QubitPauliTensor::operator!=(const QubitPauliTensor &other) const { | ||
461 | 163 | return !(*this == other); | ||
462 | } | |||
463 | ||||
464 | 2048 | bool QubitPauliTensor::operator<(const QubitPauliTensor &other) const { | ||
465 | 2048 | int comp = this->string.compare(other.string); | ||
466 |
2/2✓ Branch 0 taken 1230 times.
✓ Branch 1 taken 818 times.
|
2/2✓ Decision 'true' taken 818 times.
✓ Decision 'false' taken 1230 times.
|
2048 | if (comp < 0) return true; |
467 |
2/2✓ Branch 0 taken 438 times.
✓ Branch 1 taken 380 times.
|
2/2✓ Decision 'true' taken 380 times.
✓ Decision 'false' taken 438 times.
|
818 | if (comp > 0) return false; |
468 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 380 times.
|
1/2✓ Decision 'true' taken 380 times.
✗ Decision 'false' not taken.
|
380 | if (this->coeff.real() < other.coeff.real()) return true; |
469 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 380 times.
|
1/2✓ Decision 'true' taken 380 times.
✗ Decision 'false' not taken.
|
380 | if (this->coeff.real() > other.coeff.real()) return false; |
470 | 380 | return (this->coeff.imag() < other.coeff.imag()); | ||
471 | } | |||
472 | ||||
473 | 136 | void QubitPauliTensor::compress() { string.compress(); } | ||
474 | ||||
475 | 1946 | bool QubitPauliTensor::commutes_with(const QubitPauliTensor &other) const { | ||
476 | 1946 | return (string.commutes_with(other.string)); | ||
477 | } | |||
478 | ||||
479 | 68 | std::set<Qubit> QubitPauliTensor::common_qubits( | ||
480 | const QubitPauliTensor &other) const { | |||
481 | 68 | return string.common_qubits(other.string); | ||
482 | } | |||
483 | ||||
484 | 136 | std::set<Qubit> QubitPauliTensor::own_qubits( | ||
485 | const QubitPauliTensor &other) const { | |||
486 | 136 | return string.own_qubits(other.string); | ||
487 | } | |||
488 | ||||
489 | 68 | std::set<Qubit> QubitPauliTensor::conflicting_qubits( | ||
490 | const QubitPauliTensor &other) const { | |||
491 | 68 | return (string.conflicting_qubits(other.string)); | ||
492 | } | |||
493 | ||||
494 | 6 | std::string QubitPauliTensor::to_str() const { | ||
495 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | std::stringstream d; | |
496 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 4 times.
|
6 | if (coeff == -1.) { |
497 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | d << "-"; | |
498 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 4 times.
|
4 | } else if (coeff != 1.) { |
499 | ✗ | d << coeff << "*"; | ||
500 | } | |||
501 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | d << string.to_str(); | |
502 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
12 | return d.str(); | |
503 | 6 | } | ||
504 | ||||
505 | 6 | std::size_t hash_value(const QubitPauliTensor &qpt) { | ||
506 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | size_t seed = hash_value(qpt.string); | |
507 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | boost::hash_combine(seed, qpt.coeff); | |
508 | 6 | return seed; | ||
509 | } | |||
510 | ||||
511 | 254 | QubitPauliTensor operator*(Complex a, const QubitPauliTensor &qpt) { | ||
512 | 254 | QubitPauliTensor result = qpt; | ||
513 | 254 | result.coeff *= a; | ||
514 | 254 | return result; | ||
515 | } | |||
516 | ||||
517 | 101 | PauliStabiliser::PauliStabiliser( | ||
518 | 101 | const std::vector<Pauli> string, const bool coeff) | ||
519 | 101 | : string(string), coeff(coeff) { | ||
520 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 101 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 101 times.
|
101 | if (string.size() == 0) { |
521 | ✗ | throw std::invalid_argument("Pauli stabiliser cannot be empty."); | ||
522 | } | |||
523 |
1/2✓ Branch 3 taken 101 times.
✗ Branch 4 not taken.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 99 times.
|
101 | if (std::adjacent_find(string.begin(), string.end(), std::not_equal_to<>()) == |
524 |
4/4✓ Branch 1 taken 16 times.
✓ Branch 2 taken 85 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 99 times.
|
218 | string.end() && | |
525 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 14 times.
|
16 | string[0] == Pauli::I) { | |
526 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | throw std::invalid_argument("Pauli stabiliser cannot be identity."); | |
527 | } | |||
528 | 101 | } | ||
529 | ||||
530 | 5 | bool PauliStabiliser::operator==(const PauliStabiliser &other) const { | ||
531 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
|
5 | return coeff == other.coeff && string == other.string; | |
532 | } | |||
533 | ||||
534 | ✗ | bool PauliStabiliser::operator!=(const PauliStabiliser &other) const { | ||
535 | ✗ | return coeff != other.coeff || string != other.string; | ||
536 | } | |||
537 | ||||
538 | 5 | void to_json(nlohmann::json &j, const PauliStabiliser &pauli_stabiliser) { | ||
539 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | j["string"] = pauli_stabiliser.string; | |
540 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | j["coeff"] = pauli_stabiliser.coeff; | |
541 | 5 | } | ||
542 | ||||
543 | 5 | void from_json(const nlohmann::json &j, PauliStabiliser &pauli_stabiliser) { | ||
544 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
10 | pauli_stabiliser = PauliStabiliser( | |
545 | 15 | j.at("string").get<std::vector<Pauli>>(), j.at("coeff").get<bool>()); | ||
546 | 5 | } | ||
547 | } // namespace tket | |||
548 |