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

zeFresk / ProPauli / 18401797324

10 Oct 2025 09:02AM UTC coverage: 75.354% (-0.05%) from 75.403%
18401797324

Pull #19

github

web-flow
Merge 830573bbd into 29fb7d4f3
Pull Request #19: Parallel version

1009 of 1884 branches covered (53.56%)

Branch coverage included in aggregate %.

222 of 227 new or added lines in 8 files covered. (97.8%)

22 existing lines in 2 files now uncovered.

2241 of 2429 relevant lines covered (92.26%)

15962.84 hits per line

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

67.0
/include/quantum_op.hpp
1
#ifndef PP_QUANTUM_OP_HPP
2
#define PP_QUANTUM_OP_HPP
3

4
#include "observable.hpp"
5
#include "pauli.hpp"
6
#include "policy.hpp"
7
#include "symbolic/coefficient.hpp"
8
#include "operation_type.hpp"
9

10
#include <iterator>
11
#include <stdexcept>
12
#include <unordered_map>
13
#include <cassert>
14

15
/**
16
 * @var pg_map
17
 * @brief Maps single-qubit Pauli QGate enums to their library-internal Pauli_gates representation.
18
 */
19
static constexpr std::array<std::pair<QGate, Pauli_gates>, 4> pg_map = { {
20
        { QGate::I, Pauli_gates::I },
21
        { QGate::X, Pauli_gates::X },
22
        { QGate::Y, Pauli_gates::Y },
23
        { QGate::Z, Pauli_gates::Z },
24
} };
25

26
/**
27
 * @var clifford_map
28
 * @brief Maps single-qubit Clifford QGate enums to their library-internal Clifford_Gates_1Q representation.
29
 */
30
static constexpr std::array<std::pair<QGate, Clifford_Gates_1Q>, 1> clifford_map = { {
31
        { QGate::H, Clifford_Gates_1Q::H },
32
} };
33

34
/**
35
 * @var unoise_map
36
 * @brief Maps unital noise channel QGate enums to their library-internal UnitalNoise representation.
37
 */
38
static constexpr std::array<std::pair<QGate, UnitalNoise>, 2> unoise_map = { {
39
        { QGate::Depolarizing, UnitalNoise::Depolarizing },
40
        { QGate::Dephasing, UnitalNoise::Dephasing },
41
} };
42

43
/**
44
 * @brief A helper function to find a value in a map-like array of pairs.
45
 * @tparam T The type of the value to search for (the key).
46
 * @tparam Arr The type of the array-like container of pairs.
47
 * @param v The value to find in the `first` element of the pairs.
48
 * @param arr The container to search within.
49
 * @return An iterator to the first element in `arr` where `e.first == v`, or `std::cend(arr)` if not found.
50
 */
51
template <typename T, typename Arr>
52
inline bool in_array(T&& v, Arr const& arr) {
91✔
53
        return std::find_if(std::cbegin(arr), std::cend(arr), [&](auto&& e) { return e.first == v; }) != std::cend(arr);
173✔
54
}
91✔
55

56
/**
57
 * @struct QuantumOp
58
 * @brief Internal representation of a single quantum operation in a circuit.
59
 * @tparam F The callable type representing the gate's action on an observable.
60
 *
61
 * This struct bundles an operation's type, its gate identifier, and the
62
 * function that implements its transformation on an `Observable` object.
63
 */
64
template <typename T>
65
class QuantumOp {
66
    private:
67
        QGate gate; /**< The specific gate or noise channel identifier. */
68
        unsigned qubit0;
69
        unsigned qubit1;
70
        T parameter;
71

72
    public:
73
        using ObservableType = Observable<T>;
74

75
        QuantumOp(QGate qg, unsigned qubit) : gate(qg), qubit0(qubit) {
148✔
76
                if (qg != QGate::H && !in_array(qg, pg_map)) {
148!
77
                        throw std::invalid_argument("missing parameters for non-Pauli or H gate.");
1✔
78
                }
1✔
79
        }
148✔
80

81
        template <typename Real>
82
        QuantumOp(QGate qg, unsigned qubit, Real&& v)
83
                requires(std::is_floating_point_v<std::remove_cvref_t<Real>> || Symbolic<std::remove_cvref_t<Real>>)
84
                : gate(qg), qubit0(qubit), parameter(std::move(v)) {
178✔
85
                if (qg != QGate::Rz && !in_array(qg, unoise_map) && qg != QGate::AmplitudeDamping) {
178!
86
                        throw std::invalid_argument("bad parameters for non parametric gate.");
1✔
87
                }
1✔
88
        }
178✔
89

90
        template <typename Integer, std::enable_if_t<std::is_integral_v<Integer>, bool> = true>
91
        QuantumOp(QGate qg, unsigned control, Integer target) : gate(qg), qubit0(control), qubit1(target) {
86✔
92
                if (qg != QGate::Cx) {
86!
93
                        throw std::invalid_argument("bad parameters for cx");
2✔
94
                }
2✔
95
        }
86✔
96

97
        template <typename ExecutionPolicy = DefaultExecutionPolicy>
98
        [[gnu::always_inline]] inline void operator()(ObservableType& obs, ExecutionPolicy&& policy = ExecutionPolicy{}) const {
375✔
99
                switch (gate) {
375!
100
                case QGate::Rz:
76!
101
                        return obs.apply_rz(qubit0, parameter, policy);
76✔
102
                case QGate::Cx:
102!
103
                        return obs.apply_cx(qubit0, qubit1, policy);
102✔
104
                case QGate::AmplitudeDamping:
36!
105
                        return obs.apply_amplitude_damping(qubit0, parameter, policy);
36✔
106
                case QGate::Dephasing:
13!
107
                        return obs.apply_unital_noise(UnitalNoise::Dephasing, qubit0, parameter, policy);
13✔
108
                case QGate::Depolarizing:
24!
109
                        return obs.apply_unital_noise(UnitalNoise::Depolarizing, qubit0, parameter, policy);
24✔
110
                case QGate::H:
106!
111
                        return obs.apply_clifford(Clifford_Gates_1Q::H, qubit0);
106✔
112
                case QGate::I:
3!
113
                        return;
3✔
114
                case QGate::X:
1!
115
                        return obs.apply_pauli(Pauli_gates::X, qubit0);
1✔
116
                case QGate::Y:
1!
117
                        return obs.apply_pauli(Pauli_gates::X, qubit0);
1✔
118
                case QGate::Z:
13!
119
                        return obs.apply_pauli(Pauli_gates::X, qubit0);
13✔
NEW
120
                case QGate::Count:
×
NEW
121
                        return;
×
122
                }
375✔
123
        }
375✔
124

125
        void operator()(ObservableType& obs, RuntimePolicy const& runtime_policy) const {
126
                return std::visit([this, &obs](auto const& policy) { return (*this)(obs, policy); }, runtime_policy);
127
        }
128

129
        QGate get_gate() const { return gate; }
130

131
        [[gnu::always_inline]] inline OperationType operation_type() const {
784✔
132
                return (gate == QGate::Rz || gate == QGate::AmplitudeDamping) ? OperationType::SplittingGate : OperationType::BasicGate;
784!
133

134
                //static constexpr std::array<OperationType, 2> arr_map{OperationType::BasicGate, OperationType::SplittingGate};
135
                //return arr_map[gate == QGate::Rz || gate == QGate::AmplitudeDamping]; // branchless
136
        }
784✔
137
};
138

139
#endif
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