22 #define ASSERT_NEAR(a, b, tol) \ 23 if (std::abs((a) - (b)) > (tol)) { \ 24 std::cerr << "FAILED: Expected " << (a) << " â " << (b) \ 25 << ", difference: " << std::abs((a) - (b)) << std::endl; \ 29 #define ASSERT_TRUE(cond) \ 31 std::cerr << "FAILED: Condition false: " #cond << std::endl; \ 40 std::cout <<
"Test 1: Construction..." <<
std::flush;
48 std::cout <<
" PASSED" << std::endl;
57 std::cout <<
"Test 2: Ground state initialization..." <<
std::flush;
65 for (
int i = 1; i < 4; i++) {
86 std::cout <<
" PASSED" << std::endl;
95 std::cout <<
"Test 3: State vector construction..." <<
std::flush;
99 double inv_sqrt2 = 1.0 / std::sqrt(2.0);
100 psi[0].real = inv_sqrt2;
102 psi[1].real = inv_sqrt2;
115 double pur = rho.
purity();
118 std::cout <<
" PASSED" << std::endl;
127 std::cout <<
"Test 4: Maximally mixed state..." <<
std::flush;
136 double pur = rho.
purity();
146 std::cout <<
" PASSED" << std::endl;
155 std::cout <<
"Test 5: Unitary evolution..." <<
std::flush;
166 double inv_sqrt2 = 1.0 / std::sqrt(2.0);
167 H_matrix[0] = {inv_sqrt2, 0.0};
168 H_matrix[1] = {inv_sqrt2, 0.0};
169 H_matrix[2] = {inv_sqrt2, 0.0};
170 H_matrix[3] = {-inv_sqrt2, 0.0};
181 double pur = rho.
purity();
184 std::cout <<
" PASSED" << std::endl;
193 std::cout <<
"Test 6: Single-qubit local kernel..." <<
std::flush;
201 double inv_sqrt2 = 1.0 / std::sqrt(2.0);
202 H_kernel[0] = {inv_sqrt2, 0.0};
203 H_kernel[1] = {inv_sqrt2, 0.0};
204 H_kernel[2] = {inv_sqrt2, 0.0};
205 H_kernel[3] = {-inv_sqrt2, 0.0};
221 std::cout <<
" PASSED" << std::endl;
230 std::cout <<
"Test 7: Two-qubit controlled gate..." <<
std::flush;
236 double inv_sqrt2 = 1.0 / std::sqrt(2.0);
237 H_kernel[0] = {inv_sqrt2, 0.0};
238 H_kernel[1] = {inv_sqrt2, 0.0};
239 H_kernel[2] = {inv_sqrt2, 0.0};
240 H_kernel[3] = {-inv_sqrt2, 0.0};
246 X_kernel[0] = {0.0, 0.0};
247 X_kernel[1] = {1.0, 0.0};
248 X_kernel[2] = {1.0, 0.0};
249 X_kernel[3] = {0.0, 0.0};
263 std::cout <<
" PASSED" << std::endl;
272 std::cout <<
"Test 8: GateOperation wrapper..." <<
std::flush;
277 Gate *h_gate =
new H(2, 0);
292 std::cout <<
" PASSED" << std::endl;
301 std::cout <<
"Test 9: Depolarizing noise (fixed)..." <<
std::flush;
305 double initial_purity = rho.
purity();
318 double final_purity = rho.
purity();
325 std::cout <<
" PASSED" << std::endl;
334 std::cout <<
"Test 10: Depolarizing noise (parametric)..." <<
std::flush;
348 double final_purity = rho.
purity();
355 std::cout <<
" PASSED" << std::endl;
364 std::cout <<
"Test 11: Amplitude damping..." <<
std::flush;
391 std::cout <<
" PASSED" << std::endl;
400 std::cout <<
"Test 12: Phase damping..." <<
std::flush;
404 double inv_sqrt2 = 1.0 / std::sqrt(2.0);
405 psi[0] = {inv_sqrt2, 0.0};
406 psi[1] = {inv_sqrt2, 0.0};
409 double initial_coherence = std::abs(rho(0, 1).
real);
421 double final_coherence = std::abs(rho(0, 1).
real);
432 std::cout <<
" PASSED" << std::endl;
441 std::cout <<
"Test 13: NoisyCircuit Bell state..." <<
std::flush;
463 std::cout <<
" PASSED" << std::endl;
472 std::cout <<
"Test 14: NoisyCircuit with fixed noise..." <<
std::flush;
489 std::cout <<
" PASSED" << std::endl;
498 std::cout <<
"Test 15: NoisyCircuit with parametric noise..." <<
std::flush;
509 double params[1] = {0.2};
516 std::cout <<
" PASSED" << std::endl;
525 std::cout <<
"Test 16: Mixed gates and noise..." <<
std::flush;
544 std::cout <<
" PASSED" << std::endl;
553 std::cout <<
"Test 17: Operation info..." <<
std::flush;
579 std::cout <<
" PASSED" << std::endl;
588 std::cout <<
"Test 18: Partial trace..." <<
std::flush;
596 circuit.
apply_to(
nullptr, 0, rho_full);
599 std::vector<int> trace_out = {1};
609 double pur = rho_reduced.
purity();
612 std::cout <<
" PASSED" << std::endl;
621 std::cout <<
"Test 19: Clone operations..." <<
std::flush;
624 Gate *h_gate =
new H(2, 0);
625 auto h_op = std::unique_ptr<GateOperation>(
new GateOperation(h_gate,
true));
626 auto h_clone = h_op->clone();
632 auto dep_op = std::unique_ptr<DepolarizingOp>(
new DepolarizingOp(2, 0.1));
633 auto dep_clone = dep_op->clone();
635 ASSERT_TRUE(dep_clone->get_name() ==
"Depolarizing");
640 auto amp_clone = amp_op->clone();
642 ASSERT_TRUE(amp_clone->get_name() ==
"AmplitudeDamping");
644 std::cout <<
" PASSED" << std::endl;
653 std::cout <<
"Test 20: Legacy NoiseChannel compatibility..." <<
std::flush;
665 std::cout <<
" PASSED" << std::endl;
674 std::cout <<
"\n========================================" << std::endl;
675 std::cout <<
" Density Matrix C++ Unit Tests" << std::endl;
676 std::cout <<
" Approach B: Interface Segregation" << std::endl;
677 std::cout <<
"========================================\n" << std::endl;
712 std::cout <<
"\n========================================" << std::endl;
713 std::cout <<
" All 20 tests PASSED â" << std::endl;
714 std::cout <<
"========================================\n" << std::endl;
716 std::cout <<
"\n========================================" << std::endl;
717 std::cout <<
" Some tests FAILED â" << std::endl;
718 std::cout <<
"========================================\n" << std::endl;
int test_amplitude_damping()
Header file for a class for the representation of general gate operations.
int test_mixed_gates_and_noise()
void apply(DensityMatrix &rho) override
Apply noise channel to density matrix.
void add_CNOT(int target, int control)
int get_parameter_num() const override
Get number of free parameters this operation requires.
int test_noisy_circuit_with_noise()
void add_phase_damping(int target)
Add parametric phase damping noise (1 parameter)
int test_unitary_evolution()
int test_depolarizing_parametric()
void apply_to(const double *params, int param_count, DensityMatrix &rho)
Apply entire circuit to density matrix.
std::vector< OperationInfo > get_operation_info() const
Get information about all operations.
bool is_unitary() const override
Check if this is a unitary operation (gate) or non-unitary (noise)
int test_gate_operation()
void apply_to_density(const double *params, int param_count, DensityMatrix &rho) override
Apply this operation to the density matrix.
int test_legacy_noise_channel()
bool is_valid(double tol=1e-10) const
Check if valid density matrix.
double entropy() const
von Neumann entropy: S(Ï) = -Tr(Ï logâ Ï)
double purity() const
Calculate purity: Tr(ϲ)
Depolarizing channel: Ï â (1-p)Ï + p·I/2^n.
DensityMatrix partial_trace(const std::vector< int > &trace_out) const
Compute partial trace over specified qubits.
int get_qbit_num() const
Get number of qubits.
Amplitude damping channel (T1 relaxation): |1â© â |0â© decay.
std::string get_name() const override
Get operation name for debugging/display.
int test_clone_operations()
void add_depolarizing(int qbit_num)
Add parametric depolarizing noise channel (1 parameter)
int test_two_qubit_controlled()
Header file of complex array storage array with automatic and thread safe reference counting...
Wraps an existing Gate for density matrix operations.
Quantum density matrix Ï for mixed-state representation.
Phase damping channel (T2 dephasing): loss of coherence.
QGD_Complex16 trace() const
Calculate trace: Tr(Ï)
void apply_unitary(const matrix_base< QGD_Complex16 > &U)
Apply unitary transformation: Ï â UÏUâ
Structure type representing complex numbers in the SQUANDER package.
int get_parameter_num() const
Get total number of parameters needed.
std::string get_name() const override
Get operation name for debugging/display.
int get_qbit_num() const
Get number of qubits.
std::string get_name() const override
Get operation name for debugging/display.
int get_parameter_num() const override
Get number of free parameters this operation requires.
Depolarizing noise channel: Ï â (1-p)Ï + p·I/2^n.
Double-precision complex matrix (float64).
void apply_to_density(const double *params, int param_count, DensityMatrix &rho) override
Apply gate to density matrix using optimized local kernel.
size_t get_operation_count() const
Get number of operations in the circuit.
#define ASSERT_TRUE(cond)
int test_operation_info()
int test_state_vector_construction()
void apply_to_density(const double *params, int param_count, DensityMatrix &rho) override
Apply this operation to the density matrix.
int get_dim() const
Get matrix dimension (2^qbit_num)
std::string get_name() const override
Get operation name for debugging/display.
int test_depolarizing_fixed()
bool is_parametric() const
double real
the real part of a complex number
int test_single_qubit_local()
bool is_unitary() const override
Check if this is a unitary operation (gate) or non-unitary (noise)
void apply_to_density(const double *params, int param_count, DensityMatrix &rho) override
Apply this operation to the density matrix.
Quantum circuit with noise for density matrix simulation.
int test_noisy_circuit_bell()
#define ASSERT_NEAR(a, b, tol)
void add_amplitude_damping(int target)
Add parametric amplitude damping noise (1 parameter)
int test_maximally_mixed()
void apply_single_qubit_unitary(const matrix_base< QGD_Complex16 > &u_2x2, int target_qbit)
Apply single-qubit unitary using local kernel (optimized)
void apply_two_qubit_unitary(const matrix_base< QGD_Complex16 > &u_2x2, int target_qbit, int control_qbit)
Apply two-qubit controlled unitary using local kernel (optimized)
double imag
the imaginary part of a complex number
static DensityMatrix maximally_mixed(int qbit_num)
Create maximally mixed state: Ï = I/2^n.
int test_noisy_circuit_parametric_noise()