• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zeFresk / ProPauli / 16890690472

11 Aug 2025 07:59PM UTC coverage: 5.48%. First build
16890690472

Pull #1

github

web-flow
Merge 8f8048806 into e05dafcd7
Pull Request #1: CI

8 of 230 branches covered (3.48%)

Branch coverage included in aggregate %.

0 of 3 new or added lines in 1 file covered. (0.0%)

65 of 1102 relevant lines covered (5.9%)

0.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/tests/pauli_term.cpp
1

2
#include "gtest/gtest.h"
3

4
#include <algorithm>
5
#include <cmath>
6
#include <cstdlib>
7
#include <sstream>
8
#include <string_view>
9
#include <utility>
10
#include <random>
11

12
#include "pauli.hpp"
13
#include "pauli_term.hpp"
14

15
static constexpr coeff_t pi = M_PI;
16
static constexpr auto seed = 42;
17

18
std::string random_pauli_string(unsigned length) {
×
19
        static constexpr std::string_view chars = "IXYZ";
×
20
        static std::mt19937 gen{ seed };
×
21
        std::uniform_int_distribution<> dis(0, chars.size() - 1);
×
22

23
        std::string ret;
×
24
        ret.reserve(length);
×
25
        for (unsigned i = 0; i < length; ++i) {
×
26
                ret += chars[dis(gen)];
×
27
        }
×
28
        return ret;
×
29
}
×
30

31
unsigned rand_in(unsigned max) {
×
32
        std::uniform_int_distribution<> dis(0, max);
×
33
        static std::mt19937 gen{ seed + 1 };
×
34
        return dis(gen);
×
35
}
×
36

37
TEST(PauliTerm, construct_from_string) {
×
38
        using enum Pauli_enum;
×
39
        PauliTerm pt{ "IXYZ", 0.5 };
×
40
        PauliTerm check_against{ { I, X, Y, Z }, 0.5 };
×
41
        EXPECT_EQ(pt, check_against);
×
42
}
×
43

44
TEST(PauliTerm, construct_from_paulis) {
×
45
        using enum Pauli_enum;
×
46
        PauliTerm pt{ { Z, Y, X, I }, 0.5 };
×
47
}
×
48

49
TEST(PauliTerm, construct_from_multiply) {
×
50
        using enum Pauli_enum;
×
51
        Pauli p{ I };
×
52
        PauliTerm pt1 = -1 * p;
×
53
        PauliTerm pt2 = p * -1;
×
54
        auto pt3 = 1 * I;
×
55
}
×
56

57
TEST(PauliTerm, equality) {
58
        using enum Pauli_enum;
59
        for (Pauli const p : { I, X, Y, Z }) {
60
                coeff_t c = 1;
61
                auto lhs = c * p;
62
                auto rhs = PauliTerm(p, c);
63
                EXPECT_EQ(lhs, rhs);
64
        }
65
}
66

67
TEST(PauliTerm, inequality) {
×
68
        std::array<PauliTerm<coeff_t>, 6> pt_list{
×
69
                { { "II", 1 }, { "I", 1 }, { "X", 1 }, { "Y", 1 }, { "XX", -1 }, { "XX", 1 } }
×
70
        };
×
71
        for (std::size_t i = 0; i < pt_list.size(); ++i) {
×
72
                for (std::size_t j = 0; j < pt_list.size(); ++j) {
×
73
                        if (i == j)
×
74
                                continue;
×
75
                        EXPECT_NE(pt_list[i], pt_list[j]);
×
76
                }
×
77
        }
×
78
}
×
79

80
TEST(PauliTerm, apply_pauli_single) {
81
        using enum Pauli_enum;
82
        std::array<std::tuple<Pauli, Pauli_enum, coeff_t>, 16> truth_table = { {
83
                { I, I, 1 },
84
                { I, X, 1 },
85
                { I, Y, 1 },
86
                { I, Z, 1 }, // I
87
                { X, I, 1 },
88
                { X, X, 1 },
89
                { X, Y, -1 },
90
                { X, Z, -1 }, // X
91
                { Y, I, 1 },
92
                { Y, X, -1 },
93
                { Y, Y, 1 },
94
                { Y, Z, -1 }, // Y
95
                { Z, I, 1 },
96
                { Z, X, -1 },
97
                { Z, Y, -1 },
98
                { Z, Z, 1 } // Z
99
        } };
100
        for (auto const [p, gate, out_coeff] : truth_table) {
101
                auto pt = 1 * p;
102
                auto g = static_cast<Pauli_gates>(std::to_underlying(gate));
103
                pt.apply_pauli(g, 0);
104
                auto expected_pt = out_coeff * p;
105
                EXPECT_EQ(pt, expected_pt);
106
        }
107
}
108

109
TEST(PauliTerm, apply_clifford_single) {
110
        using enum Pauli_enum;
111
        using Clifford_Gates_1Q::H;
112
        std::array<std::tuple<Pauli, Clifford_Gates_1Q, Pauli, coeff_t>, 4> truth_table = {
113
                { { I, H, I, 1 }, { X, H, Z, 1 }, { Y, H, Y, -1 }, { Z, H, X, 1 } }
114
        };
115
        for (auto const [p, gate, out_p, out_coeff] : truth_table) {
116
                auto pt_out = 1 * p;
117
                pt_out.apply_clifford(gate, 0);
118
                auto expected_pt = out_coeff * out_p;
119
                EXPECT_EQ(pt_out, expected_pt);
120
        }
121
}
122

123
TEST(PauliTerm, apply_cx_single) {
124
        // https://arxiv.org/pdf/2505.21606
125

126
        using enum Pauli_enum;
127
        std::array<std::tuple<PauliTerm<coeff_t>, PauliTerm<coeff_t>>, 16> truth_table = { {
128
                { { "II", 1 }, { "II", 1 } },
129
                { { "IX", 1 }, { "IX", 1 } },
130
                { { "IY", 1 }, { "ZY", 1 } },
131
                { { "IZ", 1 }, { "ZZ", 1 } }, // I
132
                { { "XI", 1 }, { "XX", 1 } },
133
                { { "XX", 1 }, { "XI", 1 } },
134
                { { "XY", 1 }, { "YZ", 1 } },
135
                { { "XZ", 1 }, { "YY", -1 } }, // X
136
                { { "YI", 1 }, { "YX", 1 } },
137
                { { "YX", 1 }, { "YI", 1 } },
138
                { { "YY", 1 }, { "XZ", -1 } },
139
                { { "YZ", 1 }, { "XY", 1 } }, // Y
140
                { { "ZI", 1 }, { "ZI", 1 } },
141
                { { "ZX", 1 }, { "ZX", 1 } },
142
                { { "ZY", 1 }, { "IY", 1 } },
143
                { { "ZZ", 1 }, { "IZ", 1 } } // Z
144
        } };
145
        for (auto const [pt_in, expected_pt] : truth_table) {
146
                auto pt = pt_in;
147
                pt.apply_cx(0, 1);
148
                EXPECT_EQ(pt, expected_pt);
149

150
                auto pt_reversed = -1 * pt_in;
151
                auto expected_reversed = -1 * expected_pt;
152
                pt_reversed.apply_cx(0, 1);
153
                EXPECT_EQ(pt_reversed, expected_reversed);
154
        }
155
}
156

157
TEST(PauliTerm, apply_rz_single) {
158
        using enum Pauli_enum;
159
        using PT = PauliTerm<coeff_t>;
160
        std::array<std::tuple<PT, std::pair<PT, PT>>, 2> truth_table = { { { 1 * X, { 1 * X, -1 * Y } },
161
                                                                           { 1 * Y, { 1 * Y, 1 * X } } } };
162
        std::array<coeff_t, 10> radians = { { 0, -0, pi, -pi, pi / 2.f, -pi / 2.f, pi / 4.f, -pi / 4.f, pi / 8.f,
163
                                              -pi / 8.f } };
164
        for (auto theta : radians) {
165
                auto cos_theta = std::cos(theta);
166
                auto sin_theta = std::sin(theta);
167

168
                for (auto const [pt_in, pts_out] : truth_table) {
169
                        auto pt_out_cos = cos_theta * pts_out.first;
170
                        auto pt_out_sin = sin_theta * pts_out.second;
171
                        auto pt = pt_in;
172
                        auto new_branch = pt.apply_rz(0, theta);
173
                        EXPECT_EQ(pt, pt_out_cos);
174
                        EXPECT_EQ(new_branch, pt_out_sin);
175
                }
176
        }
177
}
178

179
TEST(PauliTerm, apply_pauli_multiple) {
180
        using enum Pauli_enum;
181
        using PT = PauliTerm<coeff_t>;
182
        std::array<std::tuple<PT, Pauli_enum, unsigned, PT>, 16> truth_table = { {
183
                { { "IXIZZY", 1 }, I, 2, { "IXIZZY", 1 } },
184
                { { "IXIZZY", 1 }, X, 2, { "IXIZZY", 1 } },
185
                { { "IXIZZY", 1 }, Y, 0, { "IXIZZY", 1 } },
186
                { { "IXIZZY", 1 }, Z, 0, { "IXIZZY", 1 } }, // I
187
                { { "XZIYIIIX", 1 }, I, 7, { "XZIYIIIX", 1 } },
188
                { { "XZIYIIIX", 1 }, X, 7, { "XZIYIIIX", 1 } },
189
                { { "XZIYIIIX", 1 }, Y, 0, { "XZIYIIIX", -1 } },
190
                { { "XZIYIIIX", 1 }, Z, 0, { "XZIYIIIX", -1 } }, // X
191
                { { "IIZYXZYIIIYZ", 1 }, I, 3, { "IIZYXZYIIIYZ", 1 } },
192
                { { "IIZYXZYIIIYZ", 1 }, X, 6, { "IIZYXZYIIIYZ", -1 } },
193
                { { "IIZYXZYIIIYZ", 1 }, Y, 10, { "IIZYXZYIIIYZ", 1 } },
194
                { { "IIZYXZYIIIYZ", 1 }, Z, 10, { "IIZYXZYIIIYZ", -1 } }, // Y
195
                { { "ZZIIXXYZIYZZIIII", 1 }, I, 0, { "ZZIIXXYZIYZZIIII", 1 } },
196
                { { "ZZIIXXYZIYZZIIII", 1 }, X, 1, { "ZZIIXXYZIYZZIIII", -1 } },
197
                { { "ZZIIXXYZIYZZIIII", 1 }, Y, 7, { "ZZIIXXYZIYZZIIII", -1 } },
198
                { { "ZZIIXXYZIYZZIIII", 1 }, Z, 8, { "ZZIIXXYZIYZZIIII", 1 } }, // Z
199
        } };
200
        for (auto const [pt_in, gate, qubit, expected_pt] : truth_table) {
201
                auto pt = pt_in;
202
                auto g = static_cast<Pauli_gates>(std::to_underlying(gate));
203
                pt.apply_pauli(g, qubit);
204
                EXPECT_EQ(pt, expected_pt);
205
        }
206
}
207

208
TEST(PauliTerm, apply_clifford_multiple) {
209
        using enum Pauli_enum;
210
        using Clifford_Gates_1Q::H;
211
        using PT = PauliTerm<coeff_t>;
212
        std::array<std::tuple<PT, Clifford_Gates_1Q, unsigned, PT>, 4> truth_table = { {
213
                { { "ZZIIXXYZIYZZIIII", 1 }, H, 2, { "ZZIIXXYZIYZZIIII", 1 } },
214
                { { "ZZIIXXYZIYZZIIII", 1 }, H, 4, { "ZZIIZXYZIYZZIIII", 1 } },
215
                { { "ZZIIXXYZIYZZIIII", 1 }, H, 6, { "ZZIIXXYZIYZZIIII", -1 } },
216
                { { "ZZIIXXYZIYZZIIII", 1 }, H, 0, { "XZIIXXYZIYZZIIII", 1 } }, // Z
217
        } };
218
        for (auto const [pt_in, gate, qubit, expected_pt] : truth_table) {
219
                auto pt = pt_in;
220
                pt.apply_clifford(gate, qubit);
221
                EXPECT_EQ(pt, expected_pt);
222
        }
223
}
224

225
TEST(PauliTerm, apply_cx_multiple) {
226
        // https://arxiv.org/pdf/2505.21606
227

228
        using enum Pauli_enum;
229
        std::array<std::tuple<std::string_view, std::string_view, coeff_t>, 16> truth_table = { {
230
                { "II", "II", 1 },
231
                { "IX", "IX", 1 },
232
                { "IY", "ZY", 1 },
233
                { "IZ", "ZZ", 1 }, // I
234
                { "XI", "XX", 1 },
235
                { "XX", "XI", 1 },
236
                { "XY", "YZ", 1 },
237
                { "XZ", "YY", -1 }, // X
238
                { "YI", "YX", 1 },
239
                { "YX", "YI", 1 },
240
                { "YY", "XZ", -1 },
241
                { "YZ", "XY", 1 }, // Y
242
                { "ZI", "ZI", 1 },
243
                { "ZX", "ZX", 1 },
244
                { "ZY", "IY", 1 },
245
                { "ZZ", "IZ", 1 } // Z
246
        } };
247
        for (auto const [bs_in, expected_bs, expected_coeff] : truth_table) {
248
                auto rd_bs = random_pauli_string(16);
249
                auto expected_rd_bs = rd_bs;
250
                auto ctrl = rand_in(rd_bs.size() - 1);
251
                auto target = rand_in(rd_bs.size() - 1);
252
                while (target == ctrl)
253
                        target = rand_in(rd_bs.size() - 1);
254
                rd_bs[ctrl] = bs_in[0];
255
                rd_bs[target] = bs_in[1];
256
                expected_rd_bs[ctrl] = expected_bs[0];
257
                expected_rd_bs[target] = expected_bs[1];
258
                auto pt = PauliTerm<coeff_t>{ rd_bs, 1 };
259
                auto expected_pt = PauliTerm<coeff_t>{ expected_rd_bs, expected_coeff };
260

261
                pt.apply_cx(ctrl, target);
262
                EXPECT_EQ(pt, expected_pt);
263
        }
264
}
265

266
TEST(PauliTerm, apply_rz_multiple) {
267
        using enum Pauli_enum;
268
        std::array<std::tuple<std::string_view, coeff_t, std::string_view, coeff_t, std::string_view>, 2> truth_table = {
269
                { { "X", 1, "X", -1, "Y" }, { "Y", 1, "Y", 1, "X" } }
270
        };
271
        std::array<coeff_t, 10> radians = { { 0, -0, pi, -pi, pi / 2.f, -pi / 2.f, pi / 4.f, -pi / 4.f, pi / 8.f,
272
                                              -pi / 8.f } };
273
        for (auto theta : radians) {
274
                auto cos_theta = std::cos(theta);
275
                auto sin_theta = std::sin(theta);
276

277
                for (auto const [p_in, c_cos, p_cos, c_sin, p_sin] : truth_table) {
278
                        auto rd_bs = random_pauli_string(16);
279
                        auto expected_cos_bs = rd_bs;
280
                        auto expected_sin_bs = rd_bs;
281
                        auto q = rand_in(rd_bs.size() - 1);
282
                        rd_bs[q] = p_in[0];
283
                        expected_cos_bs[q] = p_cos[0];
284
                        expected_sin_bs[q] = p_sin[0];
285
                        auto pt = PauliTerm<coeff_t>{ rd_bs, 1 };
286
                        auto expected_cos = PauliTerm<coeff_t>{ expected_cos_bs, c_cos };
287
                        auto expected_sin = PauliTerm<coeff_t>{ expected_sin_bs, c_sin };
288

289
                        auto pt_out_cos = cos_theta * expected_cos;
290
                        auto pt_out_sin = sin_theta * expected_sin;
291
                        auto new_branch = pt.apply_rz(q, theta);
292
                        EXPECT_EQ(pt, pt_out_cos);
293
                        EXPECT_EQ(new_branch, pt_out_sin);
294
                }
295
        }
296
}
297

298
TEST(PauliTerm, expectation_value) {
299
        using PT = PauliTerm<coeff_t>;
300
        std::array<std::tuple<PT, coeff_t>, 6> truth_table = { {
301
                { { "ZI", 1 }, 1 },
302
                { { "IZ", -0.25 }, -0.25 },
303
                { { "ZZZZZZZZZZZZZZZZZZX", 0.5 }, 0 },
304
                { { "IIIIIIIIIIIIY", 1 }, 0 },
305
                { { "X", 1 }, 0 },
306
                { { "Y", 1 }, 0 },
307
        } };
308
        for (auto const [pt, expected] : truth_table) {
309
                EXPECT_EQ(pt.expectation_value(), expected);
310
        }
311
}
312

313
TEST(PauliTerm, serialize) {
314
        std::array<std::tuple<std::string_view, PauliTerm<coeff_t>>, 3> truth_table{
315
                { { "-1 X", { "X", -1 } }, { "+0.25 IY", { "IY", 0.25 } }, { "-0.125 IXYZ", { "IXYZ", -0.125 } } }
316
        };
317

318
        for (auto const [expected_str, pt] : truth_table) {
319
                std::stringstream ss;
320
                ss << pt;
321
                EXPECT_EQ(ss.str(), expected_str);
322
        }
323
}
324

325
TEST(PauliTerm, phash_simple) {
×
326
        using PT = PauliTerm<coeff_t>;
×
327
        PT pt1("IIIIXYZ"), pt2("IIIIYXZ");
×
328
        EXPECT_EQ(pt1.phash(), pt1.phash());
×
329
        EXPECT_NE(pt1.phash(), pt2.phash());
×
330

331
        auto pt3 = pt1;
×
332
        EXPECT_EQ(pt1.phash(), pt3.phash());
×
333
        EXPECT_NE(pt2.phash(), pt3.phash());
×
334
}
×
335

336
TEST(PauliTerm, phash_nocollision_q1024n1024) {
×
337
        static constexpr std::size_t nb_tests = 1024;
×
338
        auto lhs = PauliTerm<coeff_t>(random_pauli_string(1024));
×
339

340
        for (std::size_t i = 0; i < nb_tests; ++i) {
×
341
                auto rhs = PauliTerm<coeff_t>(random_pauli_string(1024));
×
342
                if (lhs != rhs) {
×
343
                        EXPECT_NE(lhs.phash(), rhs.phash());
×
344
                }
×
345
        }
×
346
}
×
347

348
TEST(PauliTerm, pauli_weight) {
349
        std::array<std::string_view, 8> truth_table{
350
                "I", "IIIIIIIIIII", "XXXYZZZZXXX", "IXYZIXYZ", "X", "Y", "Z", "ZZ"
351
        };
352
        for (auto ps : truth_table) {
353
                PauliTerm<coeff_t> pt(ps);
354
                auto nb_i = std::count_if(ps.cbegin(), ps.cend(), [](auto c) { return c != 'I'; });
×
355
                EXPECT_EQ(pt.pauli_weight(), nb_i);
356
        }
357
}
358

359
TEST(PauliTerm, depolarizing_noise) {
×
360
        using enum UnitalNoise;
×
361
        PauliTerm pt("IXYZXYZ");
×
362
        auto ph = pt.phash();
×
363
        constexpr coeff_t p = 0.01;
×
364

365
        // no effect on I
366
        pt.apply_unital_noise(Depolarizing, 0, p);
×
367
        EXPECT_EQ(pt.phash(), ph);
×
368
        EXPECT_FLOAT_EQ(pt.coefficient(), 1.);
×
369

370
        // effect compounds on all other
371
        for (unsigned i = 1; i < pt.size(); ++i) {
×
372
                pt.apply_unital_noise(Depolarizing, i, p);
×
373
                EXPECT_EQ(pt.phash(), ph);
×
374
                EXPECT_FLOAT_EQ(pt.coefficient(), std::pow(1 - p, i));
×
375
        }
×
376
}
×
377

378
TEST(PauliTerm, dephasing_noise) {
×
379
        using enum UnitalNoise;
×
380
        PauliTerm pt("IZXYXYXY");
×
381
        auto ph = pt.phash();
×
382
        constexpr coeff_t p = 0.01;
×
383

384
        // no effect on I
385
        pt.apply_unital_noise(Dephasing, 0, p);
×
386
        EXPECT_EQ(pt.phash(), ph);
×
387
        EXPECT_FLOAT_EQ(pt.coefficient(), 1.);
×
388

389
        // no effect on Z
390
        pt.apply_unital_noise(Dephasing, 1, p);
×
391
        EXPECT_EQ(pt.phash(), ph);
×
392
        EXPECT_FLOAT_EQ(pt.coefficient(), 1.);
×
393

394
        // effect compounds on all other
395
        for (unsigned i = 2; i < pt.size(); ++i) {
×
396
                pt.apply_unital_noise(Dephasing, i, p);
×
397
                EXPECT_EQ(pt.phash(), ph);
×
398
                EXPECT_FLOAT_EQ(pt.coefficient(), std::pow(1 - p, i - 1));
×
399
        }
×
400
}
×
401

402
TEST(PauliTerm, aplitude_damping_xy) {
×
403
        PauliTerm pt("XYXY");
×
404
        auto og_ph = pt.phash();
×
405
        static constexpr float p = 0.01;
×
406

407
        for (unsigned i = 0; i < pt.size(); ++i) {
×
408
                pt.apply_amplitude_damping_xy(i, p);
×
NEW
409
                EXPECT_FLOAT_EQ(pt.coefficient(), std::pow(std::sqrt(1 - p), i + 1));
×
410
                EXPECT_EQ(pt.phash(), og_ph);
×
411
        }
×
412
}
×
413

414
TEST(PauliTerm, aplitude_damping_z) {
×
415
        PauliTerm og_pt("ZZZZ");
×
416
        auto og_ph = og_pt.phash();
×
417
        static constexpr float p = 0.01;
×
418

419
        for (unsigned i = 0; i < og_pt.size(); ++i) {
×
420
                auto pt = og_pt;
×
421
                auto np = pt.apply_amplitude_damping_z(i, p);
×
422
                auto nc = np.coefficient();
×
423
                EXPECT_FLOAT_EQ(nc, p);
×
NEW
424
                EXPECT_FLOAT_EQ(pt.coefficient(), 1 - p);
×
425
                EXPECT_EQ(pt.phash(), og_ph);
×
NEW
426
                EXPECT_EQ(np.pauli_weight(), og_pt.pauli_weight() - 1);
×
427
        }
×
428
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc