7using cplx = std::complex<real>;
8static constexpr real pi = 3.141592653589793238462643383279502884;
31 const real s = 1.0 / std::sqrt(
real(2));
39 const real c = std::cos(
pi / 4), s = std::sin(
pi / 4);
43 const real c = std::cos(
pi / 4), s = std::sin(
pi / 4);
48 const real c = std::cos(theta / 2), s = std::sin(theta / 2);
52 const real c = std::cos(theta / 2), s = std::sin(theta / 2);
56 const real c = std::cos(theta / 2), s = std::sin(theta / 2);
62 cplx{std::cos(lambda), std::sin(lambda)}};
66 const real ct = std::cos(theta / 2),
st = std::sin(theta / 2);
69 cplx{-std::cos(lambda) *
st, -std::sin(lambda) *
st},
109 const int N = 1 << n_qubits;
110 for (
int i = 0;
i < N;
i +=
stride << 1) {
114 sv[
i0] = G[0] *
a0 + G[1] *
a1;
115 sv[
i1] = G[2] *
a0 + G[3] *
a1;
123 const int N = 1 << n_qubits;
124 const int m0 = 1 << q0,
m1 = 1 << q1;
126 for (
int i = 0;
i < N; ++
i) {
128 if (
i &
m0 ||
i &
m1)
continue;
140 const int N = 1 << n_qubits;
142 for (
int i = 0;
i < N; ++
i) {
149 const int N = 1 << n_qubits;
151 for (
int i = 0;
i < N; ++
i) {
158 const int N = 1 << n_qubits;
159 const int m0 = 1 << q0,
m1 = 1 << q1;
160 for (
int i = 0;
i < N; ++
i) {
161 if ((
i &
m0) && !(
i &
m1))
162 std::swap(sv[
i], sv[(
i & ~
m0) |
m1]);
167 const int N = 1 << n_qubits;
169 for (
int i = 0;
i < N; ++
i) {
171 std::swap(sv[
i], sv[
i |
mt]);
183 for (
auto&
a : sv)
a /= n;
187 std::vector<real> p(sv.
size());
188 for (std::size_t
i = 0;
i < sv.
size(); ++
i) p[
i] = std::norm(sv[
i]);
197 for (std::size_t
i = 0;
i < sv.
size(); ++
i)
val += std::conj(sv[
i]) *
out[
i];
204 for (std::size_t
i = 0;
i < sv.
size(); ++
i) {
216 for (std::size_t
i = 0;
i < sv.
size(); ++
i)
val += std::conj(sv[
i]) *
tmp[
i];
224 for (std::size_t
i = 0;
i < sv.
size(); ++
i)
val += std::conj(sv[
i]) *
tmp[
i];
229 int n_qubits,
int qubit) {
234 const int N = 1 << n_qubits;
236 std::array<cplx, 4>
rho{};
237 for (
int i = 0;
i < N; ++
i) {
238 if (
i &
mask)
continue;
240 rho[0] += sv[
i] * std::conj(sv[
i]);
241 rho[1] += sv[
i] * std::conj(sv[
i1]);
242 rho[2] += sv[
i1] * std::conj(sv[
i]);
243 rho[3] += sv[
i1] * std::conj(sv[
i1]);
257 return (x > 1
e-15) ? -x * std::log2(x) :
real(0);
265 const int N = 1 << n_qubits;
267 for (
int i = 0;
i < N; ++
i) {
279 const int N = 1 << n_qubits;
281 const cplx phase{std::cos(lambda), std::sin(lambda)};
282 for (
int i = 0;
i < N; ++
i) {
290 const int N = 1 << n_qubits;
291 const int mc = 1 <<
ctrl,
m0 = 1 << q0,
m1 = 1 << q1;
292 for (
int i = 0;
i < N; ++
i) {
293 if ((
i & mc) && (
i &
m0) && !(
i &
m1))
294 std::swap(sv[
i], sv[(
i & ~
m0) |
m1]);
Dense vector with optional GPU storage, templated over scalar type T.
constexpr idx size() const noexcept
Gate gate_ry(real theta)
Rotation about Y: R_y(theta) = exp(-ithetaY/2)
void apply_cy(Statevector &sv, int n_qubits, int control, int target)
Controlled-Y.
std::array< cplx, 16 > Gate2Q
4x4 two-qubit gate stored row-major (16 entries)
Gate gate_rx(real theta)
Rotation about X: R_x(theta) = exp(-ithetaX/2)
real norm(const Statevector &sv)
L2 norm of the statevector (should be 1 for a valid quantum state)
std::complex< real > cplx
void apply_cp(Statevector &sv, int n_qubits, real lambda, int control, int target)
Controlled phase: applies phase e^{ilambda} when both control=1 and target=1.
Gate gate_x()
Pauli-X (NOT)
Gate gate_p(real lambda)
Phase gate: diag(1, e^{ilambda})
Gate gate_rz(real theta)
Rotation about Z: R_z(theta) = exp(-ithetaZ/2)
Gate2Q gate2q_cz()
Controlled-Z.
Gate gate_sdg()
S† = diag(1, -i)
void apply_2q(Statevector &sv, int n_qubits, const Gate2Q &G, int q0, int q1)
Apply a general 4x4 two-qubit gate to qubits q0, q1.
void apply_cnot(Statevector &sv, int n_qubits, int control, int target)
CNOT with explicit control and target qubits.
Gate2Q gate2q_cnot()
CNOT (qubit 0 = control, qubit 1 = target in subspace)
Gate gate_u(real theta, real phi, real lambda)
General SU(2) gate.
real expectation(const Statevector &sv, std::function< void(const Statevector &, Statevector &)> op)
Expectation value <psi|O|psi> for a Hermitian operator given as matrix-free matvec.
Gate gate_s()
Phase gate S = diag(1, i)
void apply_toffoli(Statevector &sv, int n_qubits, int c0, int c1, int target)
Toffoli (CCX) gate.
Statevector zero_state(int n_qubits)
Returns |0...0> computational basis state for n_qubits qubits.
void apply_cz(Statevector &sv, int n_qubits, int control, int target)
Controlled-Z.
Gate2Q gate2q_swap()
SWAP.
real expectation_x(const Statevector &sv, int n_qubits, int qubit)
<X_q> for qubit q
void apply_cswap(Statevector &sv, int n_qubits, int ctrl, int q0, int q1)
Fredkin (CSWAP): swaps q0 and q1 when ctrl=1.
void normalize(Statevector &sv)
Normalize statevector in-place.
std::array< std::complex< real >, 4 > reduced_density_matrix(const Statevector &sv, int n_qubits, int qubit)
Reduced density matrix for a single qubit (2x2, returned row-major)
std::vector< real > probabilities(const Statevector &sv)
Measurement probability for each basis state: p_i = |a_i|^2.
real expectation_z(const Statevector &sv, int qubit)
<Z_q> = P(q=0) - P(q=1) for qubit q
void apply_swap(Statevector &sv, int n_qubits, int q0, int q1)
SWAP two qubits.
real entanglement_entropy(const Statevector &sv, int n_qubits, int qubit)
Von Neumann entropy of a single qubit's reduced density matrix.
void apply_1q(Statevector &sv, int n_qubits, const Gate &G, int target)
Apply a 2x2 gate to a single qubit in-place.
std::array< cplx, 4 > Gate
2x2 single-qubit gate stored row-major: { G[0,0], G[0,1], G[1,0], G[1,1] }
real expectation_y(const Statevector &sv, int n_qubits, int qubit)
<Y_q> for qubit q
Statevector basis_state(int n_qubits, int k)
Returns the computational basis state |k> for an n_qubits system.
Gate gate_t()
T gate = diag(1, e^{ipi/4})
constexpr real phi
Golden ratio.
constexpr T ipow(T x) noexcept
Compute x^N at compile time via repeated squaring.
real norm(const Vector &x, Backend b=default_backend)
Euclidean norm.
Statevector-based quantum circuit simulator.