use kana::circuit::Circuit;
use kana::entanglement::{self, DensityMatrix};
use kana::operator::Operator;
use kana::state::StateVector;
#[test]
fn test_bell_state_via_circuit_components() {
let mut c = Circuit::new(1);
c.hadamard(0).unwrap();
let superposition = c.execute().unwrap();
let p0 = superposition.probability(0).unwrap();
let p1 = superposition.probability(1).unwrap();
assert!((p0 - 0.5).abs() < 1e-10);
assert!((p1 - 0.5).abs() < 1e-10);
}
#[test]
fn test_operator_preserves_norm() {
let h = Operator::hadamard();
let state = StateVector::zero(1);
let result = h.apply(&state).unwrap();
assert!((result.norm() - 1.0).abs() < 1e-10);
}
#[test]
fn test_entanglement_detection() {
let bell = entanglement::bell_phi_plus();
let c = entanglement::concurrence_pure(&bell);
assert!((c - 1.0).abs() < 1e-10);
let product = vec![(1.0, 0.0), (0.0, 0.0), (0.0, 0.0), (0.0, 0.0)];
let c2 = entanglement::concurrence_pure(&product);
assert!(c2.abs() < 1e-10);
}
#[test]
fn test_density_matrix_from_state_vector() {
let state = StateVector::plus();
let amps = vec![state.amplitude(0).unwrap(), state.amplitude(1).unwrap()];
let dm = DensityMatrix::from_pure_state(&s);
assert!((dm.purity() - 1.0).abs() < 1e-10);
}
#[test]
fn test_reduced_density_matrix_entropy() {
let bell = entanglement::bell_phi_plus();
let dm = DensityMatrix::from_pure_state(&bell);
let reduced = dm.partial_trace_b(2, 2).unwrap();
assert!((reduced.von_neumann_entropy() - 1.0).abs() < 1e-5);
}
#[test]
fn test_circuit_execution_matches_manual() {
let mut c = Circuit::new(1);
c.hadamard(0).unwrap();
let circuit_result = c.execute().unwrap();
let manual_result = StateVector::plus();
let (re, im) = circuit_result.inner_product(&manual_result).unwrap();
assert!((re - 1.0).abs() < 1e-10);
assert!(im.abs() < 1e-10);
}
#[test]
fn test_pauli_algebra() {
let x = Operator::pauli_x();
let y = Operator::pauli_y();
let xy = x.multiply(&y).unwrap();
let z = Operator::pauli_z();
for i in 0..2 {
for j in 0..2 {
let (xy_re, xy_im) = xy.element(i, j).unwrap();
let (z_re, z_im) = z.element(i, j).unwrap();
assert!((xy_re - (-z_im)).abs() < 1e-10);
assert!((xy_im - z_re).abs() < 1e-10);
}
}
}
#[test]
fn test_tensor_product_state_and_operator() {
let zero = StateVector::zero(1);
let one = StateVector::one();
let combined = zero.tensor_product(&one).unwrap();
let x = Operator::pauli_x();
let id = Operator::identity(2);
let x_on_first = x.tensor_product(&id);
let result = x_on_first.apply(&combined).unwrap();
assert!((result.probability(3).unwrap() - 1.0).abs() < 1e-10);
}
#[test]
fn test_bell_state_via_cnot_circuit() {
let mut c = Circuit::new(2);
c.hadamard(0).unwrap();
c.cnot(0, 1).unwrap();
let result = c.execute().unwrap();
let bell = entanglement::bell_phi_plus();
for (i, &(b_re, b_im)) in bell.iter().enumerate() {
let (r_re, r_im) = result.amplitude(i).unwrap();
assert!((r_re - b_re).abs() < 1e-10);
assert!((r_im - b_im).abs() < 1e-10);
}
let amps: Vec<(f64, f64)> = (0..4).map(|i| result.amplitude(i).unwrap()).collect();
let c_val = entanglement::concurrence_pure(&s);
assert!((c_val - 1.0).abs() < 1e-10);
}
#[test]
fn test_ghz_state_3q() {
let mut c = Circuit::new(3);
c.hadamard(0).unwrap();
c.cnot(0, 1).unwrap();
c.cnot(0, 2).unwrap();
let result = c.execute().unwrap();
let p000 = result.probability(0).unwrap(); let p111 = result.probability(7).unwrap(); assert!((p000 - 0.5).abs() < 1e-10);
assert!((p111 - 0.5).abs() < 1e-10);
for i in 1..7 {
assert!(result.probability(i).unwrap().abs() < 1e-10);
}
}
#[test]
fn test_swap_preserves_state() {
let mut c = Circuit::new(2);
c.pauli_x(1).unwrap(); c.swap(0, 1).unwrap();
c.swap(0, 1).unwrap();
let result = c.execute().unwrap();
assert!((result.probability(1).unwrap() - 1.0).abs() < 1e-10);
}
#[test]
fn test_cnot_non_adjacent_equals_manual() {
let mut amps = vec![(0.0, 0.0); 8];
amps[4] = (1.0, 0.0); let state = StateVector::new(amps).unwrap();
let mut c = Circuit::new(3);
c.cnot(0, 2).unwrap();
let result = c.execute_on(state).unwrap();
assert!((result.probability(5).unwrap() - 1.0).abs() < 1e-10);
}
#[test]
fn test_superdense_coding_all_messages() {
for (b0, b1) in [(false, false), (false, true), (true, false), (true, true)] {
let c = Circuit::superdense_coding(b0, b1);
let (_state, results) = c.execute_with_measurement(&[0.5, 0.5]).unwrap();
assert_eq!(results.len(), 2);
let decoded_b0 = results[0].1; let decoded_b1 = results[1].1; assert_eq!(decoded_b0, b0 as usize, "b0 mismatch for ({b0}, {b1})");
assert_eq!(decoded_b1, b1 as usize, "b1 mismatch for ({b0}, {b1})");
}
}
#[test]
fn test_teleportation_circuit_structure() {
let c = Circuit::teleportation();
assert_eq!(c.num_qubits(), 3);
assert_eq!(c.num_gates(), 6);
}
#[test]
fn test_teleportation_zero_state() {
let c = Circuit::teleportation();
let (_state, results) = c.execute_with_measurement(&[0.3, 0.3]).unwrap();
let (m0, m1) = (results[0].1, results[1].1);
let mut full = Circuit::teleportation();
full.teleportation_correction(m0, m1).unwrap();
let (final_state, _) = full.execute_with_measurement(&[0.3, 0.3]).unwrap();
let mut prob_q2_zero = 0.0;
for i in 0..8 {
if i & 1 == 0 {
prob_q2_zero += final_state.probability(i).unwrap();
}
}
assert!((prob_q2_zero - 1.0).abs() < 1e-10);
}
#[test]
fn test_bloch_roundtrip() {
let plus = StateVector::plus();
let (x, y, z) = plus.bloch_vector().unwrap();
assert!((x - 1.0).abs() < 1e-10);
assert!(y.abs() < 1e-10);
assert!(z.abs() < 1e-10);
let dm = entanglement::tomography_single_qubit(x, y, z);
assert!((dm.purity() - 1.0).abs() < 1e-10);
}
#[test]
fn test_deutsch_jozsa_constant_oracle() {
let c = Circuit::deutsch_jozsa(2, |_circuit, _inputs, _output| {});
let (_state, results) = c.execute_with_measurement(&[0.5, 0.5]).unwrap();
assert!(results.iter().all(|&(_, bit)| bit == 0));
}
#[test]
fn test_deutsch_jozsa_balanced_oracle() {
let c = Circuit::deutsch_jozsa(2, |circuit, inputs, output| {
circuit.cnot(inputs[0], output).unwrap();
});
let (_state, results) = c.execute_with_measurement(&[0.5, 0.5]).unwrap();
assert!(results.iter().any(|&(_, bit)| bit == 1));
}
#[test]
fn test_qft_inverse_qft_roundtrip() {
let qft = Circuit::qft(2);
let state = qft.execute().unwrap();
let iqft = Circuit::inverse_qft(2);
let result = iqft.execute_on(state).unwrap();
assert!((result.probability(0).unwrap() - 1.0).abs() < 1e-5);
}
#[test]
fn test_qft_3q_roundtrip() {
let qft = Circuit::qft(3);
let state = qft.execute().unwrap();
let iqft = Circuit::inverse_qft(3);
let result = iqft.execute_on(state).unwrap();
assert!((result.probability(0).unwrap() - 1.0).abs() < 1e-5);
}
#[test]
fn test_grover_2q_finds_target() {
let c = Circuit::grover(2, 1, |circuit, qubits| {
circuit.cz(qubits[0], qubits[1]).unwrap();
});
let (_state, results) = c.execute_with_measurement(&[0.5, 0.5]).unwrap();
assert_eq!(results[0].1, 1);
assert_eq!(results[1].1, 1);
}
#[test]
fn test_vqe_ansatz_executes() {
let params = vec![0.0; 4];
let c = Circuit::vqe_ansatz(2, 1, ¶ms).unwrap();
let result = c.execute().unwrap();
assert!((result.probability(0).unwrap() - 1.0).abs() < 1e-10);
}
#[test]
fn test_rotation_gates_unitarity() {
use std::f64::consts::PI;
let rx = Operator::rx(PI / 3.0);
let rxd = rx.dagger();
let product = rxd.multiply(&rx).unwrap();
let id = Operator::identity(2);
for i in 0..2 {
for j in 0..2 {
let (p_re, p_im) = product.element(i, j).unwrap();
let (i_re, i_im) = id.element(i, j).unwrap();
assert!((p_re - i_re).abs() < 1e-10);
assert!((p_im - i_im).abs() < 1e-10);
}
}
}
#[test]
fn test_noise_channel_on_circuit_output() {
let mut c = Circuit::new(1);
c.hadamard(0).unwrap();
let state = c.execute().unwrap();
let amps: Vec<(f64, f64)> = (0..2).map(|i| state.amplitude(i).unwrap()).collect();
let dm = entanglement::DensityMatrix::from_pure_state(&s);
let noisy = entanglement::NoiseChannel::depolarizing(0.5)
.unwrap()
.apply(&dm)
.unwrap();
assert!(noisy.purity() < dm.purity());
let (tr_re, tr_im) = noisy.trace();
assert!((tr_re - 1.0).abs() < 1e-10);
assert!(tr_im.abs() < 1e-10);
}