use crate::{
components::{
ChainableState,
operator::{
CNOT, Hadamard, Identity, Operator, Pauli, PhaseS, PhaseSdag, PhaseShift, PhaseT,
PhaseTdag, RotateX, RotateY, RotateZ, SWAP, Toffoli, Unitary2, Matchgate
},
state::State,
},
errors::Error,
};
use num_complex::Complex;
use std::f64::consts::PI;
#[test]
fn test_operator_hadamard_success() {
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
assert_eq!(zero_state.h(0).unwrap(), plus_state);
assert_eq!(one_state.h(0).unwrap(), minus_state);
assert_eq!(plus_state.h(0).unwrap(), zero_state);
assert_eq!(minus_state.h(0).unwrap(), one_state);
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.h_multi(&[0, 1]).unwrap();
let expected_state: State = State::new_plus(2).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_plus(1).unwrap().tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap();
let new_state: State = state.ch_multi(&[1], &[0]).unwrap();
let expected_state: State = State::new_basis_n(2, 1).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 0).unwrap().tensor_product(&State::new_plus(1).unwrap()).unwrap();
let new_state: State = state.ch_multi(&[0], &[1]).unwrap();
let expected_state: State = state.clone();
assert_eq!(new_state, expected_state);
let num_test_qubits_h_unc = 11;
let state_h_unc = State::new_zero(num_test_qubits_h_unc).unwrap();
let targets_h_unc: Vec<usize> = (0..num_test_qubits_h_unc).collect();
let new_state_h_unc = state_h_unc.h_multi(&targets_h_unc).unwrap();
let expected_state_h_unc = State::new_plus(num_test_qubits_h_unc).unwrap();
assert_eq!(new_state_h_unc, expected_state_h_unc, "Uncontrolled H parallel (multi-target) failed");
let num_test_qubits_ch = 11;
let control_q_ch = &[num_test_qubits_ch - 1]; let target_q_ch = &[0];
let initial_state_ch_c0 = State::new_zero(num_test_qubits_ch).unwrap();
let new_state_ch_c0 = initial_state_ch_c0.ch_multi(target_q_ch, control_q_ch).unwrap();
assert_eq!(new_state_ch_c0, initial_state_ch_c0, "Controlled H (c=0) parallel failed");
let mut initial_vec_ch_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_ch];
let idx_ch_c1_t0 = 1 << control_q_ch[0]; initial_vec_ch_c1[idx_ch_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_ch_c1 = State { state_vector: initial_vec_ch_c1, num_qubits: num_test_qubits_ch };
let new_state_ch_c1 = initial_state_ch_c1.ch_multi(target_q_ch, control_q_ch).unwrap();
let mut expected_vec_ch_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_ch];
let sqrt2_inv_h = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
expected_vec_ch_c1[idx_ch_c1_t0] = sqrt2_inv_h; expected_vec_ch_c1[idx_ch_c1_t0 | (1 << target_q_ch[0])] = sqrt2_inv_h; let expected_state_ch_c1 = State { state_vector: expected_vec_ch_c1, num_qubits: num_test_qubits_ch };
assert_eq!(new_state_ch_c1, expected_state_ch_c1, "Controlled H (c=1) parallel failed");
#[cfg(feature = "gpu")]
{
let num_test_qubits_h_unc = 15;
let state_h_unc = State::new_zero(num_test_qubits_h_unc).unwrap();
let targets_h_unc: Vec<usize> = (0..num_test_qubits_h_unc).collect();
let new_state_h_unc = state_h_unc.h_multi(&targets_h_unc).unwrap();
let expected_state_h_unc = State::new_plus(num_test_qubits_h_unc).unwrap();
assert_eq!(new_state_h_unc, expected_state_h_unc, "Uncontrolled H gpu (multi-target) failed");
let num_test_qubits_ch = 15;
let control_q_ch = &[num_test_qubits_ch - 1]; let target_q_ch = &[0];
let initial_state_ch_c0 = State::new_zero(num_test_qubits_ch).unwrap();
let new_state_ch_c0 = initial_state_ch_c0.ch_multi(target_q_ch, control_q_ch).unwrap();
assert_eq!(new_state_ch_c0, initial_state_ch_c0, "Controlled H (c=0) gpu failed");
let mut initial_vec_ch_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_ch];
let idx_ch_c1_t0 = 1 << control_q_ch[0]; initial_vec_ch_c1[idx_ch_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_ch_c1 = State { state_vector: initial_vec_ch_c1, num_qubits: num_test_qubits_ch };
let new_state_ch_c1 = initial_state_ch_c1.ch_multi(target_q_ch, control_q_ch).unwrap();
let mut expected_vec_ch_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_ch];
let sqrt2_inv_h = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
expected_vec_ch_c1[idx_ch_c1_t0] = sqrt2_inv_h; expected_vec_ch_c1[idx_ch_c1_t0 | (1 << target_q_ch[0])] = sqrt2_inv_h; let expected_state_ch_c1 = State { state_vector: expected_vec_ch_c1, num_qubits: num_test_qubits_ch };
assert_eq!(new_state_ch_c1, expected_state_ch_c1, "Controlled H (c=1) gpu failed");
}
assert_eq!(Hadamard {}.base_qubits(), 1);
}
#[test]
fn test_operator_pauli_x_success() {
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
assert_eq!(zero_state.x(0).unwrap(), one_state);
assert_eq!(one_state.x(0).unwrap(), zero_state);
assert_eq!(plus_state.x(0).unwrap(), plus_state);
assert_eq!(minus_state.x(0).unwrap(), minus_state * -1.0);
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.x_multi(&[0, 1]).unwrap();
let expected_state: State = State::new_basis_n(2, 3).unwrap(); assert_eq!(new_state, expected_state);
let new_state: State = zero_state.x(0).x(0).unwrap();
assert_eq!(new_state, zero_state);
let state: State = State::new_basis_n(2, 3).unwrap(); let new_state: State = state.cx_multi(&[1], &[0]).unwrap();
let expected_state: State = State::new_basis_n(2, 1).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(3, 3).unwrap(); let new_state: State = state.cx_multi(&[2], &[0, 1]).unwrap();
let expected_state: State = State::new_basis_n(3, 7).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 2).unwrap(); let new_state: State = state.cx_multi(&[1], &[0]).unwrap(); let expected_state: State = state.clone(); assert_eq!(new_state, expected_state);
assert_eq!(Pauli::X.base_qubits(), 1);
let num_test_qubits_x_unc = 11;
let initial_state_x_unc = State::new_zero(num_test_qubits_x_unc).unwrap();
let targets_x_unc: Vec<usize> = (0..num_test_qubits_x_unc).collect();
let new_state_x_unc = initial_state_x_unc.x_multi(&targets_x_unc).unwrap();
let expected_state_x_unc = State::new_basis_n(num_test_qubits_x_unc, (1 << num_test_qubits_x_unc) - 1).unwrap(); assert_eq!(new_state_x_unc, expected_state_x_unc, "Uncontrolled X parallel (multi-target) failed");
let num_test_qubits_cx = 11;
let control_q_cx = &[num_test_qubits_cx - 1]; let target_q_cx = &[0];
let initial_state_cx_c0 = State::new_zero(num_test_qubits_cx).unwrap();
let new_state_cx_c0 = initial_state_cx_c0.cx_multi(target_q_cx, control_q_cx).unwrap();
assert_eq!(new_state_cx_c0, initial_state_cx_c0, "Controlled X (c=0) parallel failed");
let mut initial_vec_cx_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cx];
let idx_cx_c1_t0 = 1 << control_q_cx[0]; initial_vec_cx_c1[idx_cx_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_cx_c1 = State { state_vector: initial_vec_cx_c1, num_qubits: num_test_qubits_cx };
let new_state_cx_c1 = initial_state_cx_c1.cx_multi(target_q_cx, control_q_cx).unwrap();
let mut expected_vec_cx_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cx];
expected_vec_cx_c1[idx_cx_c1_t0 | (1 << target_q_cx[0])] = Complex::new(1.0, 0.0); let expected_state_cx_c1 = State { state_vector: expected_vec_cx_c1, num_qubits: num_test_qubits_cx };
assert_eq!(new_state_cx_c1, expected_state_cx_c1, "Controlled X (c=1) parallel failed");
#[cfg(feature = "gpu")]
{
let num_test_qubits_x_gpu = 15;
let control_q_x_gpu = &[num_test_qubits_x_gpu - 1]; let target_q_x_gpu = &[0]; let i_complex_x_gpu = Complex::new(0.0, 1.0);
let sqrt2_inv_x_gpu = 1.0 / 2.0_f64.sqrt();
let initial_state_x_gpu_unc = State::new_zero(num_test_qubits_x_gpu).unwrap();
let targets_x_gpu_unc: Vec<usize> = (0..num_test_qubits_x_gpu).collect();
let new_state_x_gpu_unc = initial_state_x_gpu_unc.x_multi(&targets_x_gpu_unc).unwrap();
let expected_state_x_gpu_unc = State::new_basis_n(num_test_qubits_x_gpu, (1 << num_test_qubits_x_gpu) - 1).unwrap(); assert_eq!(new_state_x_gpu_unc, expected_state_x_gpu_unc, "Uncontrolled X GPU (multi-target) failed");
let initial_state_cx_gpu_c0 = State::new_zero(num_test_qubits_x_gpu).unwrap();
let new_state_cx_gpu_c0 = initial_state_cx_gpu_c0.cx_multi(target_q_x_gpu, control_q_x_gpu).unwrap();
assert_eq!(new_state_cx_gpu_c0, initial_state_cx_gpu_c0, "Controlled X GPU (c=0) failed");
let mut initial_vec_cx_gpu_c1_imag = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_x_gpu];
let idx_cx_gpu_c1_base = 1 << control_q_x_gpu[0]; initial_vec_cx_gpu_c1_imag[idx_cx_gpu_c1_base | (0 << target_q_x_gpu[0])] = i_complex_x_gpu * sqrt2_inv_x_gpu; initial_vec_cx_gpu_c1_imag[idx_cx_gpu_c1_base | (1 << target_q_x_gpu[0])] = Complex::new(1.0, 0.0) * sqrt2_inv_x_gpu; let initial_state_cx_gpu_c1_imag = State { state_vector: initial_vec_cx_gpu_c1_imag, num_qubits: num_test_qubits_x_gpu };
let new_state_cx_gpu_c1_imag = initial_state_cx_gpu_c1_imag.cx_multi(target_q_x_gpu, control_q_x_gpu).unwrap();
let mut expected_vec_cx_gpu_c1_imag = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_x_gpu];
expected_vec_cx_gpu_c1_imag[idx_cx_gpu_c1_base | (0 << target_q_x_gpu[0])] = Complex::new(1.0, 0.0) * sqrt2_inv_x_gpu; expected_vec_cx_gpu_c1_imag[idx_cx_gpu_c1_base | (1 << target_q_x_gpu[0])] = i_complex_x_gpu * sqrt2_inv_x_gpu; let expected_state_cx_gpu_c1_imag = State { state_vector: expected_vec_cx_gpu_c1_imag, num_qubits: num_test_qubits_x_gpu };
assert_eq!(new_state_cx_gpu_c1_imag, expected_state_cx_gpu_c1_imag, "Controlled X GPU (c=1, imag target) failed");
}
}
#[test]
fn test_operator_pauli_y_success() {
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
let i: Complex<f64> = Complex::new(0.0, 1.0);
let neg_i: Complex<f64> = Complex::new(0.0, -1.0);
let neg_one: Complex<f64> = Complex::new(-1.0, 0.0);
assert_eq!(zero_state.y(0).unwrap(), i * one_state.clone());
assert_eq!(one_state.y(0).unwrap(), neg_i * zero_state.clone());
assert_eq!(plus_state.y(0).unwrap(), neg_i * minus_state.clone());
assert_eq!(minus_state.y(0).unwrap(), i * plus_state.clone());
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.y_multi(&[0, 1]).unwrap();
let expected_state: State = State::new_basis_n(2, 3).unwrap() * neg_one;
assert_eq!(new_state, expected_state);
let new_state: State = zero_state.y(0).y(0).unwrap();
assert_eq!(new_state, zero_state);
let state: State = State::new_basis_n(2, 3).unwrap(); let new_state: State = state.cy_multi(&[1], &[0]).unwrap(); let expected_state: State = (State::new_zero(1).unwrap() * neg_i).tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 2).unwrap(); let new_state: State = state.cy_multi(&[1], &[0]).unwrap();
let expected_state: State = state.clone(); assert_eq!(new_state, expected_state);
assert_eq!(Pauli::Y.base_qubits(), 1);
let num_test_qubits_y_unc = 11;
let initial_state_y_unc = State::new_zero(num_test_qubits_y_unc).unwrap();
let targets_y_unc: Vec<usize> = (0..num_test_qubits_y_unc).collect();
let new_state_y_unc = initial_state_y_unc.y_multi(&targets_y_unc).unwrap();
let i_complex_y = Complex::new(0.0, 1.0);
let phase_factor_y = i_complex_y.powu(num_test_qubits_y_unc as u32);
let basis_one_state_y = State::new_basis_n(num_test_qubits_y_unc, (1 << num_test_qubits_y_unc) - 1).unwrap();
let expected_state_y_unc = basis_one_state_y * phase_factor_y;
assert_eq!(new_state_y_unc, expected_state_y_unc, "Uncontrolled Y parallel (multi-target) failed");
let num_test_qubits_cy = 11;
let control_q_cy = &[num_test_qubits_cy - 1]; let target_q_cy = &[0];
let initial_state_cy_c0 = State::new_zero(num_test_qubits_cy).unwrap();
let new_state_cy_c0 = initial_state_cy_c0.cy_multi(target_q_cy, control_q_cy).unwrap();
assert_eq!(new_state_cy_c0, initial_state_cy_c0, "Controlled Y (c=0) parallel failed");
let mut initial_vec_cy_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cy];
let idx_cy_c1_t0 = 1 << control_q_cy[0]; initial_vec_cy_c1[idx_cy_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_cy_c1 = State { state_vector: initial_vec_cy_c1, num_qubits: num_test_qubits_cy };
let new_state_cy_c1 = initial_state_cy_c1.cy_multi(target_q_cy, control_q_cy).unwrap();
let mut expected_vec_cy_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cy];
expected_vec_cy_c1[idx_cy_c1_t0 | (1 << target_q_cy[0])] = i_complex_y; let expected_state_cy_c1 = State { state_vector: expected_vec_cy_c1, num_qubits: num_test_qubits_cy };
assert_eq!(new_state_cy_c1, expected_state_cy_c1, "Controlled Y (c=1) parallel failed");
#[cfg(feature = "gpu")]
{
let num_test_qubits_y_gpu = 15;
let control_q_y_gpu = &[num_test_qubits_y_gpu - 1]; let target_q_y_gpu = &[0]; let i_complex_y_gpu = Complex::new(0.0, 1.0);
let initial_state_y_gpu_unc = State::new_zero(num_test_qubits_y_gpu).unwrap();
let targets_y_gpu_unc: Vec<usize> = (0..num_test_qubits_y_gpu).collect();
let new_state_y_gpu_unc = initial_state_y_gpu_unc.y_multi(&targets_y_gpu_unc).unwrap();
let phase_factor_y_gpu = i_complex_y_gpu.powu(num_test_qubits_y_gpu as u32);
let basis_one_state_y_gpu = State::new_basis_n(num_test_qubits_y_gpu, (1 << num_test_qubits_y_gpu) - 1).unwrap();
let expected_state_y_gpu_unc = basis_one_state_y_gpu * phase_factor_y_gpu;
assert_eq!(new_state_y_gpu_unc, expected_state_y_gpu_unc, "Uncontrolled Y GPU (multi-target) failed");
let initial_state_cy_gpu_c0 = State::new_zero(num_test_qubits_y_gpu).unwrap();
let new_state_cy_gpu_c0 = initial_state_cy_gpu_c0.cy_multi(target_q_y_gpu, control_q_y_gpu).unwrap();
assert_eq!(new_state_cy_gpu_c0, initial_state_cy_gpu_c0, "Controlled Y GPU (c=0) failed");
let mut initial_vec_cy_gpu_c1_imag = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_y_gpu];
let idx_cy_gpu_c1_base = 1 << control_q_y_gpu[0]; initial_vec_cy_gpu_c1_imag[idx_cy_gpu_c1_base | (0 << target_q_y_gpu[0])] = i_complex_y_gpu; let initial_state_cy_gpu_c1_imag = State { state_vector: initial_vec_cy_gpu_c1_imag, num_qubits: num_test_qubits_y_gpu };
let new_state_cy_gpu_c1_imag = initial_state_cy_gpu_c1_imag.cy_multi(target_q_y_gpu, control_q_y_gpu).unwrap();
let mut expected_vec_cy_gpu_c1_imag = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_y_gpu];
expected_vec_cy_gpu_c1_imag[idx_cy_gpu_c1_base | (1 << target_q_y_gpu[0])] = Complex::new(-1.0, 0.0); let expected_state_cy_gpu_c1_imag = State { state_vector: expected_vec_cy_gpu_c1_imag, num_qubits: num_test_qubits_y_gpu };
assert_eq!(new_state_cy_gpu_c1_imag, expected_state_cy_gpu_c1_imag, "Controlled Y GPU (c=1, imag target i|0>) failed");
}
}
#[test]
fn test_operator_pauli_z_success() {
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
assert_eq!(zero_state.z(0).unwrap(), zero_state.clone());
assert_eq!(one_state.z(0).unwrap(), one_state.clone() * -1.0);
assert_eq!(plus_state.z(0).unwrap(), minus_state.clone());
assert_eq!(minus_state.z(0).unwrap(), plus_state.clone());
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.z_multi(&[0, 1]).unwrap();
let expected_state: State = State::new_zero(2).unwrap();
assert_eq!(new_state, expected_state);
let new_state: State = plus_state.z(0).z(0).unwrap();
assert_eq!(new_state, plus_state);
let state: State = State::new_basis_n(2, 3).unwrap(); let new_state: State = state.cz_multi(&[1], &[0]).unwrap(); let expected_state: State = (State::new_basis_n(1, 1).unwrap() * -1.0).tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 2).unwrap(); let new_state: State = state.cz_multi(&[1], &[0]).unwrap(); let expected_state: State = state.clone(); assert_eq!(new_state, expected_state);
assert_eq!(Pauli::Z.base_qubits(), 1);
let num_test_qubits_z_unc = 11;
let initial_state_z_unc = State::new_zero(num_test_qubits_z_unc).unwrap();
let targets_z_unc: Vec<usize> = (0..num_test_qubits_z_unc).collect();
let new_state_z_unc = initial_state_z_unc.z_multi(&targets_z_unc).unwrap();
assert_eq!(new_state_z_unc, initial_state_z_unc, "Uncontrolled Z parallel (multi-target) failed on |0...0>");
let num_test_qubits_cz = 11;
let control_q_cz = &[num_test_qubits_cz - 1]; let target_q_cz = &[0];
let initial_state_cz_c0_t0 = State::new_zero(num_test_qubits_cz).unwrap(); let new_state_cz_c0_t0 = initial_state_cz_c0_t0.cz_multi(target_q_cz, control_q_cz).unwrap();
assert_eq!(new_state_cz_c0_t0, initial_state_cz_c0_t0, "Controlled Z (c=0, t=0) parallel failed");
let mut initial_vec_cz_c0_t1 = vec![Complex::new(0.0,0.0); 1 << num_test_qubits_cz];
initial_vec_cz_c0_t1[1 << target_q_cz[0]] = Complex::new(1.0,0.0); let initial_state_cz_c0_t1 = State { state_vector: initial_vec_cz_c0_t1, num_qubits: num_test_qubits_cz };
let new_state_cz_c0_t1 = initial_state_cz_c0_t1.cz_multi(target_q_cz, control_q_cz).unwrap();
assert_eq!(new_state_cz_c0_t1, initial_state_cz_c0_t1, "Controlled Z (c=0, t=1) parallel failed");
let mut initial_vec_cz_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cz];
let idx_cz_c1_t0 = 1 << control_q_cz[0]; initial_vec_cz_c1_t0[idx_cz_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_cz_c1_t0 = State { state_vector: initial_vec_cz_c1_t0, num_qubits: num_test_qubits_cz };
let new_state_cz_c1_t0 = initial_state_cz_c1_t0.cz_multi(target_q_cz, control_q_cz).unwrap();
assert_eq!(new_state_cz_c1_t0, initial_state_cz_c1_t0, "Controlled Z (c=1, t=0) parallel failed");
let mut initial_vec_cz_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cz];
let idx_cz_c1_t1 = (1 << control_q_cz[0]) | (1 << target_q_cz[0]); initial_vec_cz_c1_t1[idx_cz_c1_t1] = Complex::new(1.0, 0.0);
let initial_state_cz_c1_t1 = State { state_vector: initial_vec_cz_c1_t1, num_qubits: num_test_qubits_cz };
let new_state_cz_c1_t1 = initial_state_cz_c1_t1.cz_multi(target_q_cz, control_q_cz).unwrap();
let mut expected_vec_cz_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cz];
expected_vec_cz_c1_t1[idx_cz_c1_t1] = Complex::new(-1.0, 0.0); let expected_state_cz_c1_t1 = State { state_vector: expected_vec_cz_c1_t1, num_qubits: num_test_qubits_cz };
assert_eq!(new_state_cz_c1_t1, expected_state_cz_c1_t1, "Controlled Z (c=1, t=1) parallel failed");
#[cfg(feature = "gpu")]
{
let num_test_qubits_z_unc = 15;
let initial_state_z_unc = State::new_zero(num_test_qubits_z_unc).unwrap();
let targets_z_unc: Vec<usize> = (0..num_test_qubits_z_unc).collect();
let new_state_z_unc = initial_state_z_unc.z_multi(&targets_z_unc).unwrap();
assert_eq!(new_state_z_unc, initial_state_z_unc, "Uncontrolled Z gpu (multi-target) failed on |0...0>");
let initial_state_z_unc = State::new_basis_n(num_test_qubits_z_unc, 1).unwrap(); let new_state_z_unc = initial_state_z_unc.z(0).unwrap();
let expected_state_z_unc = -1.0 * initial_state_z_unc.clone(); assert_eq!(new_state_z_unc, expected_state_z_unc, "Uncontrolled Z gpu (single target) failed on |0..01>");
let num_test_qubits_cz = 15;
let control_q_cz = &[num_test_qubits_cz - 1]; let target_q_cz = &[0];
let initial_state_cz_c0_t0 = State::new_zero(num_test_qubits_cz).unwrap(); let new_state_cz_c0_t0 = initial_state_cz_c0_t0.cz_multi(target_q_cz, control_q_cz).unwrap();
assert_eq!(new_state_cz_c0_t0, initial_state_cz_c0_t0, "Controlled Z (c=0, t=0) gpu failed");
let mut initial_vec_cz_c0_t1 = vec![Complex::new(0.0,0.0); 1 << num_test_qubits_cz];
initial_vec_cz_c0_t1[1 << target_q_cz[0]] = Complex::new(1.0,0.0); let initial_state_cz_c0_t1 = State { state_vector: initial_vec_cz_c0_t1, num_qubits: num_test_qubits_cz };
let new_state_cz_c0_t1 = initial_state_cz_c0_t1.cz_multi(target_q_cz, control_q_cz).unwrap();
assert_eq!(new_state_cz_c0_t1, initial_state_cz_c0_t1, "Controlled Z (c=0, t=1) gpu failed");
let mut initial_vec_cz_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cz];
let idx_cz_c1_t0 = 1 << control_q_cz[0]; initial_vec_cz_c1_t0[idx_cz_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_cz_c1_t0 = State { state_vector: initial_vec_cz_c1_t0, num_qubits: num_test_qubits_cz };
let new_state_cz_c1_t0 = initial_state_cz_c1_t0.cz_multi(target_q_cz, control_q_cz).unwrap();
assert_eq!(new_state_cz_c1_t0, initial_state_cz_c1_t0, "Controlled Z (c=1, t=0) gpu failed");
}
}
#[test]
fn test_operator_pauli_to_pauli_string_success() {
let pauli_x = Pauli::X;
let pauli_y = Pauli::Y;
let pauli_z = Pauli::Z;
let pauli_string_x = pauli_x.to_pauli_string(0);
let pauli_string_y = pauli_y.to_pauli_string(0);
let pauli_string_z = pauli_z.to_pauli_string(0);
assert_eq!(pauli_string_x.len(), 1);
assert_eq!(pauli_string_y.len(), 1);
assert_eq!(pauli_string_z.len(), 1);
assert_eq!(pauli_string_x.get_targets(), vec![0]);
assert_eq!(pauli_string_y.get_targets(), vec![0]);
assert_eq!(pauli_string_z.get_targets(), vec![0]);
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
assert_eq!(zero_state.x(0).unwrap(), pauli_string_x.apply(&zero_state).unwrap());
assert_eq!(one_state.x(0).unwrap(), pauli_string_x.apply(&one_state).unwrap());
assert_eq!(plus_state.x(0).unwrap(), pauli_string_x.apply(&plus_state).unwrap());
assert_eq!(minus_state.x(0).unwrap(), pauli_string_x.apply(&minus_state).unwrap());
assert_eq!(zero_state.y(0).unwrap(), pauli_string_y.apply(&zero_state).unwrap());
assert_eq!(one_state.y(0).unwrap(), pauli_string_y.apply(&one_state).unwrap());
assert_eq!(plus_state.y(0).unwrap(), pauli_string_y.apply(&plus_state).unwrap());
assert_eq!(minus_state.y(0).unwrap(), pauli_string_y.apply(&minus_state).unwrap());
assert_eq!(zero_state.z(0).unwrap(), pauli_string_z.apply(&zero_state).unwrap());
assert_eq!(one_state.z(0).unwrap(), pauli_string_z.apply(&one_state).unwrap());
assert_eq!(plus_state.z(0).unwrap(), pauli_string_z.apply(&plus_state).unwrap());
assert_eq!(minus_state.z(0).unwrap(), pauli_string_z.apply(&minus_state).unwrap());
}
#[test]
fn test_operator_identity_success() {
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
assert_eq!(zero_state.i(0).unwrap(), zero_state.clone());
assert_eq!(one_state.i(0).unwrap(), one_state.clone());
assert_eq!(plus_state.i(0).unwrap(), plus_state.clone());
assert_eq!(minus_state.i(0).unwrap(), minus_state.clone());
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.i_multi(&[0, 1]).unwrap();
let expected_state: State = State::new_zero(2).unwrap();
assert_eq!(new_state, expected_state);
assert_eq!(Identity {}.base_qubits(), 1);
let num_test_qubits_i_unc = 11;
let initial_state_i_unc = State::new_zero(num_test_qubits_i_unc).unwrap();
let targets_i_unc: Vec<usize> = (0..num_test_qubits_i_unc).collect();
let new_state_i_unc = initial_state_i_unc.i_multi(&targets_i_unc).unwrap();
assert_eq!(new_state_i_unc, initial_state_i_unc, "Uncontrolled I parallel (multi-target) failed");
let num_test_qubits_ci = 11;
let control_q_ci = &[num_test_qubits_ci - 1];
let target_q_ci = &[0];
let initial_state_ci_c0 = State::new_zero(num_test_qubits_ci).unwrap();
let new_state_ci_c0 = initial_state_ci_c0.ci_multi(target_q_ci, control_q_ci).unwrap();
assert_eq!(new_state_ci_c0, initial_state_ci_c0, "Controlled I (c=0) parallel failed");
let mut initial_vec_ci_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_ci];
let idx_ci_c1_t0 = 1 << control_q_ci[0];
initial_vec_ci_c1[idx_ci_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_ci_c1 = State { state_vector: initial_vec_ci_c1, num_qubits: num_test_qubits_ci };
let new_state_ci_c1 = initial_state_ci_c1.ci_multi(target_q_ci, control_q_ci).unwrap();
assert_eq!(new_state_ci_c1, initial_state_ci_c1, "Controlled I (c=1) parallel failed");
}
#[test]
fn test_operator_phase_s_success() {
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
let i: Complex<f64> = Complex::new(0.0, 1.0);
let invrt2: Complex<f64> = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
let expected_plus: State = invrt2 * (zero_state.clone() + i * one_state.clone());
let expected_minus: State = invrt2 * (zero_state.clone() - i * one_state.clone());
assert_eq!(zero_state.s(0).unwrap(), zero_state.clone());
assert_eq!(one_state.s(0).unwrap(), i * one_state.clone());
assert_eq!(plus_state.s(0).unwrap(), expected_plus.clone());
assert_eq!(minus_state.s(0).unwrap(), expected_minus.clone());
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.s_multi(&[0, 1]).unwrap();
let expected_state: State = State::new_zero(2).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_plus(1).unwrap().tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap();
let new_state: State = state.cs_multi(&[1], &[0]).unwrap();
let invrt2: Complex<f64> = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
let expected_state: State = (invrt2 * (State::new_zero(1).unwrap() + i * State::new_basis_n(1, 1).unwrap())).tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 0).unwrap().tensor_product(&State::new_plus(1).unwrap()).unwrap();
let new_state: State = state.cs_multi(&[0], &[1]).unwrap();
let expected_state: State = state.clone(); assert_eq!(new_state, expected_state);
assert_eq!(PhaseS {}.base_qubits(), 1);
let num_test_qubits_s_unc = 11;
let initial_state_s_unc = State::new_zero(num_test_qubits_s_unc).unwrap();
let targets_s_unc: Vec<usize> = (0..num_test_qubits_s_unc).collect();
let new_state_s_unc = initial_state_s_unc.s_multi(&targets_s_unc).unwrap();
assert_eq!(new_state_s_unc, initial_state_s_unc, "Uncontrolled S parallel (multi-target) on |0...0> failed");
let num_test_qubits_cs = 11;
let control_q_cs = &[num_test_qubits_cs - 1]; let target_q_cs = &[0];
let initial_state_cs_c0_t0 = State::new_zero(num_test_qubits_cs).unwrap(); let new_state_cs_c0_t0 = initial_state_cs_c0_t0.cs_multi(target_q_cs, control_q_cs).unwrap();
assert_eq!(new_state_cs_c0_t0, initial_state_cs_c0_t0, "Controlled S (c=0, t=0) parallel failed");
let mut initial_vec_cs_c0_t1 = vec![Complex::new(0.0,0.0); 1 << num_test_qubits_cs];
initial_vec_cs_c0_t1[1 << target_q_cs[0]] = Complex::new(1.0,0.0); let initial_state_cs_c0_t1 = State { state_vector: initial_vec_cs_c0_t1, num_qubits: num_test_qubits_cs };
let new_state_cs_c0_t1 = initial_state_cs_c0_t1.cs_multi(target_q_cs, control_q_cs).unwrap();
assert_eq!(new_state_cs_c0_t1, initial_state_cs_c0_t1, "Controlled S (c=0, t=1) parallel failed");
let mut initial_vec_cs_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cs];
let idx_cs_c1_t0 = 1 << control_q_cs[0]; initial_vec_cs_c1_t0[idx_cs_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_cs_c1_t0 = State { state_vector: initial_vec_cs_c1_t0, num_qubits: num_test_qubits_cs };
let new_state_cs_c1_t0 = initial_state_cs_c1_t0.cs_multi(target_q_cs, control_q_cs).unwrap();
assert_eq!(new_state_cs_c1_t0, initial_state_cs_c1_t0, "Controlled S (c=1, t=0) parallel failed");
let mut initial_vec_cs_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cs];
let idx_cs_c1_t1 = (1 << control_q_cs[0]) | (1 << target_q_cs[0]); initial_vec_cs_c1_t1[idx_cs_c1_t1] = Complex::new(1.0, 0.0);
let initial_state_cs_c1_t1 = State { state_vector: initial_vec_cs_c1_t1, num_qubits: num_test_qubits_cs };
let new_state_cs_c1_t1 = initial_state_cs_c1_t1.cs_multi(target_q_cs, control_q_cs).unwrap();
let mut expected_vec_cs_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cs];
expected_vec_cs_c1_t1[idx_cs_c1_t1] = Complex::new(0.0, 1.0); let expected_state_cs_c1_t1 = State { state_vector: expected_vec_cs_c1_t1, num_qubits: num_test_qubits_cs };
assert_eq!(new_state_cs_c1_t1, expected_state_cs_c1_t1, "Controlled S (c=1, t=1) parallel failed");
#[cfg(feature = "gpu")]
{
let num_qubits_gpu = 15; let i_complex_gpu = Complex::new(0.0, 1.0);
let initial_state_s_gpu_unc_t1 = State::new_basis_n(num_qubits_gpu, 1).unwrap(); let new_state_s_gpu_unc_t1 = initial_state_s_gpu_unc_t1.s(0).unwrap();
let expected_state_s_gpu_unc_t1 = initial_state_s_gpu_unc_t1.clone() * i_complex_gpu;
assert_eq!(new_state_s_gpu_unc_t1, expected_state_s_gpu_unc_t1, "Uncontrolled S GPU on |...001> failed");
let initial_state_s_gpu_unc_t0 = State::new_zero(num_qubits_gpu).unwrap(); let new_state_s_gpu_unc_t0 = initial_state_s_gpu_unc_t0.s(0).unwrap();
assert_eq!(new_state_s_gpu_unc_t0, initial_state_s_gpu_unc_t0, "Uncontrolled S GPU on |...000> failed");
let control_q_gpu = &[num_qubits_gpu - 1]; let target_q_gpu = &[0];
let mut initial_vec_cs_gpu_c0_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
initial_vec_cs_gpu_c0_t1[1 << target_q_gpu[0]] = Complex::new(1.0, 0.0);
let initial_state_cs_gpu_c0_t1 = State { state_vector: initial_vec_cs_gpu_c0_t1, num_qubits: num_qubits_gpu };
let new_state_cs_gpu_c0_t1 = initial_state_cs_gpu_c0_t1.cs_multi(target_q_gpu, control_q_gpu).unwrap();
assert_eq!(new_state_cs_gpu_c0_t1, initial_state_cs_gpu_c0_t1, "Controlled S GPU (c=0, t=1) failed");
let mut initial_vec_cs_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_cs_gpu_c1_t1 = (1 << control_q_gpu[0]) | (1 << target_q_gpu[0]);
initial_vec_cs_gpu_c1_t1[idx_cs_gpu_c1_t1] = Complex::new(1.0, 0.0);
let initial_state_cs_gpu_c1_t1 = State { state_vector: initial_vec_cs_gpu_c1_t1, num_qubits: num_qubits_gpu };
let new_state_cs_gpu_c1_t1 = initial_state_cs_gpu_c1_t1.cs_multi(target_q_gpu, control_q_gpu).unwrap();
let mut expected_vec_cs_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_cs_gpu_c1_t1[idx_cs_gpu_c1_t1] = i_complex_gpu;
let expected_state_cs_gpu_c1_t1 = State { state_vector: expected_vec_cs_gpu_c1_t1, num_qubits: num_qubits_gpu };
assert_eq!(new_state_cs_gpu_c1_t1, expected_state_cs_gpu_c1_t1, "Controlled S GPU (c=1, t=1) failed");
let mut initial_vec_cs_gpu_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_cs_gpu_c1_t0 = 1 << control_q_gpu[0];
initial_vec_cs_gpu_c1_t0[idx_cs_gpu_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_cs_gpu_c1_t0 = State { state_vector: initial_vec_cs_gpu_c1_t0, num_qubits: num_qubits_gpu };
let new_state_cs_gpu_c1_t0 = initial_state_cs_gpu_c1_t0.cs_multi(target_q_gpu, control_q_gpu).unwrap();
assert_eq!(new_state_cs_gpu_c1_t0, initial_state_cs_gpu_c1_t0, "Controlled S GPU (c=1, t=0) failed");
}
}
#[test]
fn test_operator_phase_t_success() {
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
let eipi4: Complex<f64> = Complex::new(0.0, PI / 4.0).exp();
let invrt2: Complex<f64> = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
let expected_plus: State = invrt2 * (zero_state.clone() + eipi4 * one_state.clone());
let expected_minus: State = invrt2 * (zero_state.clone() - eipi4 * one_state.clone());
assert_eq!(zero_state.t(0).unwrap(), zero_state.clone());
assert_eq!(one_state.t(0).unwrap(), eipi4 * one_state.clone());
assert_eq!(plus_state.t(0).unwrap(), expected_plus.clone());
assert_eq!(minus_state.t(0).unwrap(), expected_minus.clone());
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.t_multi(&[0, 1]).unwrap();
let expected_state: State = State::new_zero(2).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_plus(1).unwrap().tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap();
let new_state: State = state.ct_multi(&[1], &[0]).unwrap();
let invrt2: Complex<f64> = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
let expected_state: State = (invrt2 * (State::new_zero(1).unwrap() + eipi4 * State::new_basis_n(1, 1).unwrap())).tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 0).unwrap().tensor_product(&State::new_plus(1).unwrap()).unwrap();
let new_state: State = state.ct_multi(&[0], &[1]).unwrap();
let expected_state: State = state.clone(); assert_eq!(new_state, expected_state);
assert_eq!(PhaseT {}.base_qubits(), 1);
let num_test_qubits_t_unc = 11;
let initial_state_t_unc = State::new_zero(num_test_qubits_t_unc).unwrap();
let targets_t_unc: Vec<usize> = (0..num_test_qubits_t_unc).collect();
let new_state_t_unc = initial_state_t_unc.t_multi(&targets_t_unc).unwrap();
assert_eq!(new_state_t_unc, initial_state_t_unc, "Uncontrolled T parallel (multi-target) on |0...0> failed");
let num_test_qubits_ct = 11;
let control_q_ct = &[num_test_qubits_ct - 1]; let target_q_ct = &[0];
let initial_state_ct_c0_t0 = State::new_zero(num_test_qubits_ct).unwrap(); let new_state_ct_c0_t0 = initial_state_ct_c0_t0.ct_multi(target_q_ct, control_q_ct).unwrap();
assert_eq!(new_state_ct_c0_t0, initial_state_ct_c0_t0, "Controlled T (c=0, t=0) parallel failed");
let mut initial_vec_ct_c0_t1 = vec![Complex::new(0.0,0.0); 1 << num_test_qubits_ct];
initial_vec_ct_c0_t1[1 << target_q_ct[0]] = Complex::new(1.0,0.0); let initial_state_ct_c0_t1 = State { state_vector: initial_vec_ct_c0_t1, num_qubits: num_test_qubits_ct };
let new_state_ct_c0_t1 = initial_state_ct_c0_t1.ct_multi(target_q_ct, control_q_ct).unwrap();
assert_eq!(new_state_ct_c0_t1, initial_state_ct_c0_t1, "Controlled T (c=0, t=1) parallel failed");
let mut initial_vec_ct_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_ct];
let idx_ct_c1_t0 = 1 << control_q_ct[0]; initial_vec_ct_c1_t0[idx_ct_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_ct_c1_t0 = State { state_vector: initial_vec_ct_c1_t0, num_qubits: num_test_qubits_ct };
let new_state_ct_c1_t0 = initial_state_ct_c1_t0.ct_multi(target_q_ct, control_q_ct).unwrap();
assert_eq!(new_state_ct_c1_t0, initial_state_ct_c1_t0, "Controlled T (c=1, t=0) parallel failed");
let mut initial_vec_ct_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_ct];
let idx_ct_c1_t1 = (1 << control_q_ct[0]) | (1 << target_q_ct[0]); initial_vec_ct_c1_t1[idx_ct_c1_t1] = Complex::new(1.0, 0.0);
let initial_state_ct_c1_t1 = State { state_vector: initial_vec_ct_c1_t1, num_qubits: num_test_qubits_ct };
let new_state_ct_c1_t1 = initial_state_ct_c1_t1.ct_multi(target_q_ct, control_q_ct).unwrap();
let mut expected_vec_ct_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_ct];
let eipi4_ct = Complex::new(0.0, PI / 4.0).exp();
expected_vec_ct_c1_t1[idx_ct_c1_t1] = eipi4_ct;
let expected_state_ct_c1_t1 = State { state_vector: expected_vec_ct_c1_t1, num_qubits: num_test_qubits_ct };
assert_eq!(new_state_ct_c1_t1, expected_state_ct_c1_t1, "Controlled T (c=1, t=1) parallel failed");
#[cfg(feature = "gpu")]
{
let num_qubits_gpu = 15; let eipi4_gpu = Complex::new(0.0, PI / 4.0).exp();
let initial_state_t_gpu_unc_t1 = State::new_basis_n(num_qubits_gpu, 1).unwrap(); let new_state_t_gpu_unc_t1 = initial_state_t_gpu_unc_t1.t(0).unwrap();
let expected_state_t_gpu_unc_t1 = initial_state_t_gpu_unc_t1.clone() * eipi4_gpu;
assert_eq!(new_state_t_gpu_unc_t1, expected_state_t_gpu_unc_t1, "Uncontrolled T GPU on |...001> failed");
let initial_state_t_gpu_unc_t0 = State::new_zero(num_qubits_gpu).unwrap(); let new_state_t_gpu_unc_t0 = initial_state_t_gpu_unc_t0.t(0).unwrap();
assert_eq!(new_state_t_gpu_unc_t0, initial_state_t_gpu_unc_t0, "Uncontrolled T GPU on |...000> failed");
let control_q_gpu = &[num_qubits_gpu - 1];
let target_q_gpu = &[0];
let mut initial_vec_ct_gpu_c0_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
initial_vec_ct_gpu_c0_t1[1 << target_q_gpu[0]] = Complex::new(1.0, 0.0);
let initial_state_ct_gpu_c0_t1 = State { state_vector: initial_vec_ct_gpu_c0_t1, num_qubits: num_qubits_gpu };
let new_state_ct_gpu_c0_t1 = initial_state_ct_gpu_c0_t1.ct_multi(target_q_gpu, control_q_gpu).unwrap();
assert_eq!(new_state_ct_gpu_c0_t1, initial_state_ct_gpu_c0_t1, "Controlled T GPU (c=0, t=1) failed");
let mut initial_vec_ct_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_ct_gpu_c1_t1 = (1 << control_q_gpu[0]) | (1 << target_q_gpu[0]);
initial_vec_ct_gpu_c1_t1[idx_ct_gpu_c1_t1] = Complex::new(1.0, 0.0);
let initial_state_ct_gpu_c1_t1 = State { state_vector: initial_vec_ct_gpu_c1_t1, num_qubits: num_qubits_gpu };
let new_state_ct_gpu_c1_t1 = initial_state_ct_gpu_c1_t1.ct_multi(target_q_gpu, control_q_gpu).unwrap();
let mut expected_vec_ct_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_ct_gpu_c1_t1[idx_ct_gpu_c1_t1] = eipi4_gpu;
let expected_state_ct_gpu_c1_t1 = State { state_vector: expected_vec_ct_gpu_c1_t1, num_qubits: num_qubits_gpu };
assert_eq!(new_state_ct_gpu_c1_t1, expected_state_ct_gpu_c1_t1, "Controlled T GPU (c=1, t=1) failed");
let mut initial_vec_ct_gpu_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_ct_gpu_c1_t0 = 1 << control_q_gpu[0];
initial_vec_ct_gpu_c1_t0[idx_ct_gpu_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_ct_gpu_c1_t0 = State { state_vector: initial_vec_ct_gpu_c1_t0, num_qubits: num_qubits_gpu };
let new_state_ct_gpu_c1_t0 = initial_state_ct_gpu_c1_t0.ct_multi(target_q_gpu, control_q_gpu).unwrap();
assert_eq!(new_state_ct_gpu_c1_t0, initial_state_ct_gpu_c1_t0, "Controlled T GPU (c=1, t=0) failed");
}
}
#[test]
fn test_operator_s_dag_success() {
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
let i: Complex<f64> = Complex::new(0.0, 1.0);
let neg_i: Complex<f64> = Complex::new(0.0, -1.0);
let invrt2: Complex<f64> = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
let expected_one: State = neg_i * one_state.clone();
let expected_plus: State = invrt2 * (zero_state.clone() - i * one_state.clone());
let expected_minus: State = invrt2 * (zero_state.clone() + i * one_state.clone());
assert_eq!(zero_state.s_dag(0).unwrap(), zero_state.clone());
assert_eq!(one_state.s_dag(0).unwrap(), expected_one.clone());
assert_eq!(plus_state.s_dag(0).unwrap(), expected_plus.clone());
assert_eq!(minus_state.s_dag(0).unwrap(), expected_minus.clone());
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.s_dag_multi(&[0, 1]).unwrap();
let expected_state: State = State::new_zero(2).unwrap();
assert_eq!(new_state, expected_state);
let new_state: State = plus_state.s(0).s_dag(0).unwrap();
assert_eq!(new_state, plus_state);
let state: State = State::new_plus(1).unwrap().tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap();
let new_state: State = state.cs_dag_multi(&[1], &[0]).unwrap();
let invrt2: Complex<f64> = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
let expected_state: State = (invrt2 * (State::new_zero(1).unwrap() - i * State::new_basis_n(1, 1).unwrap())).tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 0).unwrap().tensor_product(&State::new_plus(1).unwrap()).unwrap();
let new_state: State = state.cs_dag_multi(&[0], &[1]).unwrap();
let expected_state: State = state.clone(); assert_eq!(new_state, expected_state);
assert_eq!(PhaseSdag {}.base_qubits(), 1);
let num_test_qubits_sdag_unc = 11;
let initial_state_sdag_unc = State::new_zero(num_test_qubits_sdag_unc).unwrap();
let targets_sdag_unc: Vec<usize> = (0..num_test_qubits_sdag_unc).collect();
let new_state_sdag_unc = initial_state_sdag_unc.s_dag_multi(&targets_sdag_unc).unwrap();
assert_eq!(new_state_sdag_unc, initial_state_sdag_unc, "Uncontrolled Sdag parallel (multi-target) on |0...0> failed");
let num_test_qubits_csdag = 11;
let control_q_csdag = &[num_test_qubits_csdag - 1];
let target_q_csdag = &[0];
let initial_state_csdag_c0_t0 = State::new_zero(num_test_qubits_csdag).unwrap();
let new_state_csdag_c0_t0 = initial_state_csdag_c0_t0.cs_dag_multi(target_q_csdag, control_q_csdag).unwrap();
assert_eq!(new_state_csdag_c0_t0, initial_state_csdag_c0_t0, "Controlled Sdag (c=0, t=0) parallel failed");
let mut initial_vec_csdag_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_csdag];
let idx_csdag_c1_t1 = (1 << control_q_csdag[0]) | (1 << target_q_csdag[0]);
initial_vec_csdag_c1_t1[idx_csdag_c1_t1] = Complex::new(1.0, 0.0);
let initial_state_csdag_c1_t1 = State { state_vector: initial_vec_csdag_c1_t1, num_qubits: num_test_qubits_csdag };
let new_state_csdag_c1_t1 = initial_state_csdag_c1_t1.cs_dag_multi(target_q_csdag, control_q_csdag).unwrap();
let mut expected_vec_csdag_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_csdag];
expected_vec_csdag_c1_t1[idx_csdag_c1_t1] = Complex::new(0.0, -1.0); let expected_state_csdag_c1_t1 = State { state_vector: expected_vec_csdag_c1_t1, num_qubits: num_test_qubits_csdag };
assert_eq!(new_state_csdag_c1_t1, expected_state_csdag_c1_t1, "Controlled Sdag (c=1, t=1) parallel failed");
#[cfg(feature = "gpu")]
{
let num_qubits_gpu = 15; let neg_i_complex_gpu = Complex::new(0.0, -1.0);
let initial_state_sdag_gpu_unc_t1 = State::new_basis_n(num_qubits_gpu, 1).unwrap(); let new_state_sdag_gpu_unc_t1 = initial_state_sdag_gpu_unc_t1.s_dag(0).unwrap();
let expected_state_sdag_gpu_unc_t1 = initial_state_sdag_gpu_unc_t1.clone() * neg_i_complex_gpu;
assert_eq!(new_state_sdag_gpu_unc_t1, expected_state_sdag_gpu_unc_t1, "Uncontrolled Sdag GPU on |...001> failed");
let initial_state_sdag_gpu_unc_t0 = State::new_zero(num_qubits_gpu).unwrap(); let new_state_sdag_gpu_unc_t0 = initial_state_sdag_gpu_unc_t0.s_dag(0).unwrap();
assert_eq!(new_state_sdag_gpu_unc_t0, initial_state_sdag_gpu_unc_t0, "Uncontrolled Sdag GPU on |...000> failed");
let control_q_gpu = &[num_qubits_gpu - 1];
let target_q_gpu = &[0];
let mut initial_vec_csdag_gpu_c0_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
initial_vec_csdag_gpu_c0_t1[1 << target_q_gpu[0]] = Complex::new(1.0, 0.0);
let initial_state_csdag_gpu_c0_t1 = State { state_vector: initial_vec_csdag_gpu_c0_t1, num_qubits: num_qubits_gpu };
let new_state_csdag_gpu_c0_t1 = initial_state_csdag_gpu_c0_t1.cs_dag_multi(target_q_gpu, control_q_gpu).unwrap();
assert_eq!(new_state_csdag_gpu_c0_t1, initial_state_csdag_gpu_c0_t1, "Controlled Sdag GPU (c=0, t=1) failed");
let mut initial_vec_csdag_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_csdag_gpu_c1_t1 = (1 << control_q_gpu[0]) | (1 << target_q_gpu[0]);
initial_vec_csdag_gpu_c1_t1[idx_csdag_gpu_c1_t1] = Complex::new(1.0, 0.0);
let initial_state_csdag_gpu_c1_t1 = State { state_vector: initial_vec_csdag_gpu_c1_t1, num_qubits: num_qubits_gpu };
let new_state_csdag_gpu_c1_t1 = initial_state_csdag_gpu_c1_t1.cs_dag_multi(target_q_gpu, control_q_gpu).unwrap();
let mut expected_vec_csdag_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_csdag_gpu_c1_t1[idx_csdag_gpu_c1_t1] = neg_i_complex_gpu;
let expected_state_csdag_gpu_c1_t1 = State { state_vector: expected_vec_csdag_gpu_c1_t1, num_qubits: num_qubits_gpu };
assert_eq!(new_state_csdag_gpu_c1_t1, expected_state_csdag_gpu_c1_t1, "Controlled Sdag GPU (c=1, t=1) failed");
let mut initial_vec_csdag_gpu_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_csdag_gpu_c1_t0 = 1 << control_q_gpu[0];
initial_vec_csdag_gpu_c1_t0[idx_csdag_gpu_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_csdag_gpu_c1_t0 = State { state_vector: initial_vec_csdag_gpu_c1_t0, num_qubits: num_qubits_gpu };
let new_state_csdag_gpu_c1_t0 = initial_state_csdag_gpu_c1_t0.cs_dag_multi(target_q_gpu, control_q_gpu).unwrap();
assert_eq!(new_state_csdag_gpu_c1_t0, initial_state_csdag_gpu_c1_t0, "Controlled Sdag GPU (c=1, t=0) failed");
}
}
#[test]
fn test_operator_t_dag_success() {
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
let enegipi4: Complex<f64> = Complex::new(0.0, -PI / 4.0).exp();
let invrt2: Complex<f64> = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
let expected_one: State = enegipi4 * one_state.clone();
let expected_plus: State = invrt2 * (zero_state.clone() + enegipi4 * one_state.clone());
let expected_minus: State = invrt2 * (zero_state.clone() - enegipi4 * one_state.clone());
assert_eq!(zero_state.t_dag(0).unwrap(), zero_state.clone());
assert_eq!(one_state.t_dag(0).unwrap(), expected_one.clone());
assert_eq!(plus_state.t_dag(0).unwrap(), expected_plus.clone());
assert_eq!(minus_state.t_dag(0).unwrap(), expected_minus.clone());
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.t_dag_multi(&[0, 1]).unwrap();
let expected_state: State = State::new_zero(2).unwrap();
assert_eq!(new_state, expected_state);
let new_state: State = plus_state.t(0).t_dag(0).unwrap();
assert_eq!(new_state, plus_state);
let state: State = State::new_plus(1).unwrap().tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap();
let new_state: State = state.ct_dag_multi(&[1], &[0]).unwrap();
let invrt2: Complex<f64> = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
let expected_state: State = (invrt2 * (State::new_zero(1).unwrap() + enegipi4 * State::new_basis_n(1, 1).unwrap())).tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap(); assert_eq!(new_state, expected_state);
assert_eq!(PhaseTdag {}.base_qubits(), 1);
let num_test_qubits_tdag_unc = 11;
let initial_state_tdag_unc = State::new_zero(num_test_qubits_tdag_unc).unwrap();
let targets_tdag_unc: Vec<usize> = (0..num_test_qubits_tdag_unc).collect();
let new_state_tdag_unc = initial_state_tdag_unc.t_dag_multi(&targets_tdag_unc).unwrap();
assert_eq!(new_state_tdag_unc, initial_state_tdag_unc, "Uncontrolled Tdag parallel (multi-target) on |0...0> failed");
let num_test_qubits_ctdag = 11;
let control_q_ctdag = &[num_test_qubits_ctdag - 1];
let target_q_ctdag = &[0];
let initial_state_ctdag_c0_t0 = State::new_zero(num_test_qubits_ctdag).unwrap();
let new_state_ctdag_c0_t0 = initial_state_ctdag_c0_t0.ct_dag_multi(target_q_ctdag, control_q_ctdag).unwrap();
assert_eq!(new_state_ctdag_c0_t0, initial_state_ctdag_c0_t0, "Controlled Tdag (c=0, t=0) parallel failed");
let mut initial_vec_ctdag_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_ctdag];
let idx_ctdag_c1_t1 = (1 << control_q_ctdag[0]) | (1 << target_q_ctdag[0]);
initial_vec_ctdag_c1_t1[idx_ctdag_c1_t1] = Complex::new(1.0, 0.0);
let initial_state_ctdag_c1_t1 = State { state_vector: initial_vec_ctdag_c1_t1, num_qubits: num_test_qubits_ctdag };
let new_state_ctdag_c1_t1 = initial_state_ctdag_c1_t1.ct_dag_multi(target_q_ctdag, control_q_ctdag).unwrap();
let mut expected_vec_ctdag_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_ctdag];
let enegipi4_ctdag = Complex::new(0.0, -PI / 4.0).exp();
expected_vec_ctdag_c1_t1[idx_ctdag_c1_t1] = enegipi4_ctdag;
let expected_state_ctdag_c1_t1 = State { state_vector: expected_vec_ctdag_c1_t1, num_qubits: num_test_qubits_ctdag };
assert_eq!(new_state_ctdag_c1_t1, expected_state_ctdag_c1_t1, "Controlled Tdag (c=1, t=1) parallel failed");
#[cfg(feature = "gpu")]
{
let num_qubits_gpu = 15; let enegipi4_gpu = Complex::new(0.0, -PI / 4.0).exp();
let initial_state_tdag_gpu_unc_t1 = State::new_basis_n(num_qubits_gpu, 1).unwrap(); let new_state_tdag_gpu_unc_t1 = initial_state_tdag_gpu_unc_t1.t_dag(0).unwrap();
let expected_state_tdag_gpu_unc_t1 = initial_state_tdag_gpu_unc_t1.clone() * enegipi4_gpu;
assert_eq!(new_state_tdag_gpu_unc_t1, expected_state_tdag_gpu_unc_t1, "Uncontrolled Tdag GPU on |...001> failed");
let initial_state_tdag_gpu_unc_t0 = State::new_zero(num_qubits_gpu).unwrap(); let new_state_tdag_gpu_unc_t0 = initial_state_tdag_gpu_unc_t0.t_dag(0).unwrap();
assert_eq!(new_state_tdag_gpu_unc_t0, initial_state_tdag_gpu_unc_t0, "Uncontrolled Tdag GPU on |...000> failed");
let control_q_gpu = &[num_qubits_gpu - 1];
let target_q_gpu = &[0];
let mut initial_vec_ctdag_gpu_c0_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
initial_vec_ctdag_gpu_c0_t1[1 << target_q_gpu[0]] = Complex::new(1.0, 0.0);
let initial_state_ctdag_gpu_c0_t1 = State { state_vector: initial_vec_ctdag_gpu_c0_t1, num_qubits: num_qubits_gpu };
let new_state_ctdag_gpu_c0_t1 = initial_state_ctdag_gpu_c0_t1.ct_dag_multi(target_q_gpu, control_q_gpu).unwrap();
assert_eq!(new_state_ctdag_gpu_c0_t1, initial_state_ctdag_gpu_c0_t1, "Controlled Tdag GPU (c=0, t=1) failed");
let mut initial_vec_ctdag_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_ctdag_gpu_c1_t1 = (1 << control_q_gpu[0]) | (1 << target_q_gpu[0]);
initial_vec_ctdag_gpu_c1_t1[idx_ctdag_gpu_c1_t1] = Complex::new(1.0, 0.0);
let initial_state_ctdag_gpu_c1_t1 = State { state_vector: initial_vec_ctdag_gpu_c1_t1, num_qubits: num_qubits_gpu };
let new_state_ctdag_gpu_c1_t1 = initial_state_ctdag_gpu_c1_t1.ct_dag_multi(target_q_gpu, control_q_gpu).unwrap();
let mut expected_vec_ctdag_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_ctdag_gpu_c1_t1[idx_ctdag_gpu_c1_t1] = enegipi4_gpu;
let expected_state_ctdag_gpu_c1_t1 = State { state_vector: expected_vec_ctdag_gpu_c1_t1, num_qubits: num_qubits_gpu };
assert_eq!(new_state_ctdag_gpu_c1_t1, expected_state_ctdag_gpu_c1_t1, "Controlled Tdag GPU (c=1, t=1) failed");
let mut initial_vec_ctdag_gpu_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_ctdag_gpu_c1_t0 = 1 << control_q_gpu[0];
initial_vec_ctdag_gpu_c1_t0[idx_ctdag_gpu_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_ctdag_gpu_c1_t0 = State { state_vector: initial_vec_ctdag_gpu_c1_t0, num_qubits: num_qubits_gpu };
let new_state_ctdag_gpu_c1_t0 = initial_state_ctdag_gpu_c1_t0.ct_dag_multi(target_q_gpu, control_q_gpu).unwrap();
assert_eq!(new_state_ctdag_gpu_c1_t0, initial_state_ctdag_gpu_c1_t0, "Controlled Tdag GPU (c=1, t=0) failed");
}
}
#[test]
fn test_operator_phase_shift_success() {
let theta: f64 = PI / 2.5;
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
let eitheta: Complex<f64> = Complex::new(0.0, theta).exp();
let invrt2: Complex<f64> = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
let expected_one: State = eitheta * one_state.clone();
let expected_plus: State = invrt2 * (zero_state.clone() + eitheta * one_state.clone());
let expected_minus: State = invrt2 * (zero_state.clone() - eitheta * one_state.clone());
assert_eq!(zero_state.p(0, theta).unwrap(), zero_state.clone());
assert_eq!(one_state.p(0, theta).unwrap(), expected_one.clone());
assert_eq!(plus_state.p(0, theta).unwrap(), expected_plus.clone());
assert_eq!(minus_state.p(0, theta).unwrap(), expected_minus.clone());
let new_state: State = plus_state.p(0, -PI / 2.0).unwrap();
assert_eq!(new_state, plus_state.s_dag(0).unwrap());
let new_state: State = plus_state.p(0, PI / 2.0).unwrap();
assert_eq!(new_state, plus_state.s(0).unwrap());
let new_state: State = plus_state.p(0, -PI / 4.0).unwrap();
assert_eq!(new_state, plus_state.t_dag(0).unwrap());
let new_state: State = plus_state.p(0, PI / 4.0).unwrap();
assert_eq!(new_state, plus_state.t(0).unwrap());
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.p_multi(&[0, 1], theta).unwrap();
let expected_state: State = State::new_zero(2).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_plus(1).unwrap().tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap();
let new_state: State = state.cp_multi(&[1], &[0], PI / 2.0).unwrap();
let invrt2: Complex<f64> = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
let expected_state: State = (invrt2 * (State::new_zero(1).unwrap() + Complex::new(0.0, PI / 2.0).exp() * State::new_basis_n(1, 1).unwrap())).tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 0).unwrap().tensor_product(&State::new_plus(1).unwrap()).unwrap();
let new_state: State = state.cp_multi(&[0], &[1], -PI / 2.0).unwrap();
let expected_state: State = state.clone(); assert_eq!(new_state, expected_state);
assert_eq!(PhaseShift::new(theta).base_qubits(), 1);
let num_test_qubits_p_unc = 11;
let angle_p_unc = PI / 3.0;
let initial_state_p_unc = State::new_zero(num_test_qubits_p_unc).unwrap();
let targets_p_unc: Vec<usize> = (0..num_test_qubits_p_unc).collect();
let new_state_p_unc = initial_state_p_unc.p_multi(&targets_p_unc, angle_p_unc).unwrap();
assert_eq!(new_state_p_unc, initial_state_p_unc, "Uncontrolled PhaseShift parallel (multi-target) on |0...0> failed");
let num_test_qubits_cp = 11;
let angle_cp = PI / 5.0;
let control_q_cp = &[num_test_qubits_cp - 1];
let target_q_cp = &[0];
let initial_state_cp_c0_t0 = State::new_zero(num_test_qubits_cp).unwrap();
let new_state_cp_c0_t0 = initial_state_cp_c0_t0.cp_multi(target_q_cp, control_q_cp, angle_cp).unwrap();
assert_eq!(new_state_cp_c0_t0, initial_state_cp_c0_t0, "Controlled PhaseShift (c=0, t=0) parallel failed");
let mut initial_vec_cp_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cp];
let idx_cp_c1_t1 = (1 << control_q_cp[0]) | (1 << target_q_cp[0]);
initial_vec_cp_c1_t1[idx_cp_c1_t1] = Complex::new(1.0, 0.0);
let initial_state_cp_c1_t1 = State { state_vector: initial_vec_cp_c1_t1, num_qubits: num_test_qubits_cp };
let new_state_cp_c1_t1 = initial_state_cp_c1_t1.cp_multi(target_q_cp, control_q_cp, angle_cp).unwrap();
let mut expected_vec_cp_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cp];
let eitheta_cp = Complex::new(0.0, angle_cp).exp();
expected_vec_cp_c1_t1[idx_cp_c1_t1] = eitheta_cp;
let expected_state_cp_c1_t1 = State { state_vector: expected_vec_cp_c1_t1, num_qubits: num_test_qubits_cp };
assert_eq!(new_state_cp_c1_t1, expected_state_cp_c1_t1, "Controlled PhaseShift (c=1, t=1) parallel failed");
#[cfg(feature = "gpu")]
{
let num_qubits_gpu = 15; let angle_gpu = PI / 3.7; let eitheta_gpu = Complex::new(0.0, angle_gpu).exp();
let initial_state_p_gpu_unc_t1 = State::new_basis_n(num_qubits_gpu, 1).unwrap(); let new_state_p_gpu_unc_t1 = initial_state_p_gpu_unc_t1.p(0, angle_gpu).unwrap();
let expected_state_p_gpu_unc_t1 = initial_state_p_gpu_unc_t1.clone() * eitheta_gpu;
assert_eq!(new_state_p_gpu_unc_t1, expected_state_p_gpu_unc_t1, "Uncontrolled PhaseShift GPU on |...001> failed");
let initial_state_p_gpu_unc_t0 = State::new_zero(num_qubits_gpu).unwrap(); let new_state_p_gpu_unc_t0 = initial_state_p_gpu_unc_t0.p(0, angle_gpu).unwrap();
assert_eq!(new_state_p_gpu_unc_t0, initial_state_p_gpu_unc_t0, "Uncontrolled PhaseShift GPU on |...000> failed");
let control_q_gpu = &[num_qubits_gpu - 1];
let target_q_gpu = &[0];
let mut initial_vec_cp_gpu_c0_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
initial_vec_cp_gpu_c0_t1[1 << target_q_gpu[0]] = Complex::new(1.0, 0.0);
let initial_state_cp_gpu_c0_t1 = State { state_vector: initial_vec_cp_gpu_c0_t1, num_qubits: num_qubits_gpu };
let new_state_cp_gpu_c0_t1 = initial_state_cp_gpu_c0_t1.cp_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
assert_eq!(new_state_cp_gpu_c0_t1, initial_state_cp_gpu_c0_t1, "Controlled PhaseShift GPU (c=0, t=1) failed");
let mut initial_vec_cp_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_cp_gpu_c1_t1 = (1 << control_q_gpu[0]) | (1 << target_q_gpu[0]);
initial_vec_cp_gpu_c1_t1[idx_cp_gpu_c1_t1] = Complex::new(1.0, 0.0);
let initial_state_cp_gpu_c1_t1 = State { state_vector: initial_vec_cp_gpu_c1_t1, num_qubits: num_qubits_gpu };
let new_state_cp_gpu_c1_t1 = initial_state_cp_gpu_c1_t1.cp_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
let mut expected_vec_cp_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_cp_gpu_c1_t1[idx_cp_gpu_c1_t1] = eitheta_gpu;
let expected_state_cp_gpu_c1_t1 = State { state_vector: expected_vec_cp_gpu_c1_t1, num_qubits: num_qubits_gpu };
assert_eq!(new_state_cp_gpu_c1_t1, expected_state_cp_gpu_c1_t1, "Controlled PhaseShift GPU (c=1, t=1) failed");
let mut initial_vec_cp_gpu_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_cp_gpu_c1_t0 = 1 << control_q_gpu[0];
initial_vec_cp_gpu_c1_t0[idx_cp_gpu_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_cp_gpu_c1_t0 = State { state_vector: initial_vec_cp_gpu_c1_t0, num_qubits: num_qubits_gpu };
let new_state_cp_gpu_c1_t0 = initial_state_cp_gpu_c1_t0.cp_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
assert_eq!(new_state_cp_gpu_c1_t0, initial_state_cp_gpu_c1_t0, "Controlled PhaseShift GPU (c=1, t=0) failed");
}
}
#[test]
fn test_operator_rotate_x_success() {
let theta: f64 = PI / 2.5;
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
let cos_half_theta: f64 = (theta / 2.0).cos();
let sin_half_theta: f64 = (theta / 2.0).sin();
let eimhalf_theta: Complex<f64> = Complex::new(0.0, -theta / 2.0).exp();
let eimhalf_theta_conj: Complex<f64> = Complex::new(0.0, theta / 2.0).exp();
let i: Complex<f64> = Complex::new(0.0, 1.0);
let expected_zero: State =
cos_half_theta * zero_state.clone() + i * -sin_half_theta * one_state.clone();
let expected_one: State =
-i * sin_half_theta * zero_state.clone() + cos_half_theta * one_state.clone();
let expected_plus: State = eimhalf_theta * plus_state.clone();
let expected_minus: State = eimhalf_theta_conj * minus_state.clone();
assert_eq!(zero_state.rx(0, theta).unwrap(), expected_zero.clone());
assert_eq!(one_state.rx(0, theta).unwrap(), expected_one.clone());
assert_eq!(plus_state.rx(0, theta).unwrap(), expected_plus.clone());
assert_eq!(minus_state.rx(0, theta).unwrap(), expected_minus.clone());
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.rx_multi(&[0, 1], theta).unwrap();
let expected_state: State = State::new_zero(2).unwrap() * cos_half_theta * cos_half_theta
+ State::new_basis_n(2, 1).unwrap() * -i * cos_half_theta * sin_half_theta
+ State::new_basis_n(2, 2).unwrap() * -i * cos_half_theta * sin_half_theta
+ State::new_basis_n(2, 3).unwrap() * -sin_half_theta * sin_half_theta;
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 3).unwrap(); let new_state: State = state.crx_multi(&[1], &[0], PI).unwrap(); let expected_state: State = (State::new_zero(1).unwrap() * -i).tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 0).unwrap().tensor_product(&State::new_plus(1).unwrap()).unwrap();
let new_state: State = state.crx_multi(&[0], &[1], -PI).unwrap(); let expected_state: State = state.clone(); assert_eq!(new_state, expected_state);
assert_eq!(RotateX::new(theta).base_qubits(), 1);
let num_test_qubits_rx_unc = 11;
let angle_rx_unc = PI / 1.5;
let initial_state_rx_unc = State::new_zero(num_test_qubits_rx_unc).unwrap();
let targets_rx_unc: Vec<usize> = (0..num_test_qubits_rx_unc).collect();
let new_state_rx_unc = initial_state_rx_unc.rx_multi(&targets_rx_unc, angle_rx_unc).unwrap();
let rx_on_zero_one_q = State::new_zero(1).unwrap().rx(0, angle_rx_unc).unwrap();
let mut expected_state_rx_unc = rx_on_zero_one_q.clone();
if num_test_qubits_rx_unc > 0 { for _ in 1..num_test_qubits_rx_unc {
expected_state_rx_unc = expected_state_rx_unc.tensor_product_unchecked(&rx_on_zero_one_q);
}
} else {
panic!("num_test_qubits_rx_unc is 0, which is not expected for this test");
}
assert_eq!(new_state_rx_unc, expected_state_rx_unc, "Uncontrolled Rx parallel (multi-target) failed");
let num_test_qubits_crx = 11;
let angle_crx = PI / 2.2;
let control_q_crx = &[num_test_qubits_crx - 1];
let target_q_crx = &[0];
let initial_state_crx_c0 = State::new_zero(num_test_qubits_crx).unwrap();
let new_state_crx_c0 = initial_state_crx_c0.crx_multi(target_q_crx, control_q_crx, angle_crx).unwrap();
assert_eq!(new_state_crx_c0, initial_state_crx_c0, "Controlled Rx (c=0) parallel failed");
let mut initial_vec_crx_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_crx];
let idx_crx_c1_t0 = 1 << control_q_crx[0];
initial_vec_crx_c1[idx_crx_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_crx_c1 = State { state_vector: initial_vec_crx_c1, num_qubits: num_test_qubits_crx };
let new_state_crx_c1 = initial_state_crx_c1.crx_multi(target_q_crx, control_q_crx, angle_crx).unwrap();
let rx_on_zero_for_crx = State::new_zero(1).unwrap().rx(0, angle_crx).unwrap();
let mut expected_vec_crx_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_crx];
if rx_on_zero_for_crx.state_vector[0].norm_sqr() > 1e-9 {
expected_vec_crx_c1[idx_crx_c1_t0] = rx_on_zero_for_crx.state_vector[0];
}
if rx_on_zero_for_crx.state_vector[1].norm_sqr() > 1e-9 {
expected_vec_crx_c1[idx_crx_c1_t0 | (1 << target_q_crx[0])] = rx_on_zero_for_crx.state_vector[1];
}
let expected_state_crx_c1 = State { state_vector: expected_vec_crx_c1, num_qubits: num_test_qubits_crx };
assert_eq!(new_state_crx_c1, expected_state_crx_c1, "Controlled Rx (c=1) parallel failed");
#[cfg(feature = "gpu")]
{
let num_qubits_gpu = 15; let angle_gpu = PI / 3.7; let cos_half_theta_gpu = (angle_gpu / 2.0).cos();
let sin_half_theta_gpu = (angle_gpu / 2.0).sin();
let i_gpu = Complex::new(0.0, 1.0);
let initial_state_rx_gpu_unc_t0 = State::new_zero(num_qubits_gpu).unwrap();
let new_state_rx_gpu_unc_t0 = initial_state_rx_gpu_unc_t0.rx(0, angle_gpu).unwrap();
let mut expected_vec_rx_gpu_unc_t0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_rx_gpu_unc_t0[0] = Complex::new(cos_half_theta_gpu, 0.0);
expected_vec_rx_gpu_unc_t0[1] = -i_gpu * sin_half_theta_gpu;
let expected_state_rx_gpu_unc_t0 = State { state_vector: expected_vec_rx_gpu_unc_t0, num_qubits: num_qubits_gpu };
assert_eq!(new_state_rx_gpu_unc_t0, expected_state_rx_gpu_unc_t0, "Uncontrolled RotateX GPU on |...000> failed");
let initial_state_rx_gpu_unc_t1 = State::new_basis_n(num_qubits_gpu, 1).unwrap(); let new_state_rx_gpu_unc_t1 = initial_state_rx_gpu_unc_t1.rx(0, angle_gpu).unwrap();
let mut expected_vec_rx_gpu_unc_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_rx_gpu_unc_t1[0] = -i_gpu * sin_half_theta_gpu;
expected_vec_rx_gpu_unc_t1[1] = Complex::new(cos_half_theta_gpu, 0.0);
let expected_state_rx_gpu_unc_t1 = State { state_vector: expected_vec_rx_gpu_unc_t1, num_qubits: num_qubits_gpu };
assert_eq!(new_state_rx_gpu_unc_t1, expected_state_rx_gpu_unc_t1, "Uncontrolled RotateX GPU on |...001> failed");
let control_q_gpu = &[num_qubits_gpu - 1];
let target_q_gpu = &[0];
let initial_state_crx_gpu_c0_t0 = State::new_zero(num_qubits_gpu).unwrap();
let new_state_crx_gpu_c0_t0 = initial_state_crx_gpu_c0_t0.crx_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
assert_eq!(new_state_crx_gpu_c0_t0, initial_state_crx_gpu_c0_t0, "Controlled RotateX GPU (c=0, t=0) failed");
let mut initial_vec_crx_gpu_c0_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
initial_vec_crx_gpu_c0_t1[1 << target_q_gpu[0]] = Complex::new(1.0, 0.0); let initial_state_crx_gpu_c0_t1 = State { state_vector: initial_vec_crx_gpu_c0_t1, num_qubits: num_qubits_gpu };
let new_state_crx_gpu_c0_t1 = initial_state_crx_gpu_c0_t1.crx_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
assert_eq!(new_state_crx_gpu_c0_t1, initial_state_crx_gpu_c0_t1, "Controlled RotateX GPU (c=0, t=1) failed");
let mut initial_vec_crx_gpu_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_crx_gpu_c1_t0_control = 1 << control_q_gpu[0]; initial_vec_crx_gpu_c1_t0[idx_crx_gpu_c1_t0_control] = Complex::new(1.0, 0.0); let initial_state_crx_gpu_c1_t0 = State { state_vector: initial_vec_crx_gpu_c1_t0, num_qubits: num_qubits_gpu };
let new_state_crx_gpu_c1_t0 = initial_state_crx_gpu_c1_t0.crx_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
let mut expected_vec_crx_gpu_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_crx_gpu_c1_t0[idx_crx_gpu_c1_t0_control] = Complex::new(cos_half_theta_gpu, 0.0); expected_vec_crx_gpu_c1_t0[idx_crx_gpu_c1_t0_control | (1 << target_q_gpu[0])] = -i_gpu * sin_half_theta_gpu; let expected_state_crx_gpu_c1_t0 = State { state_vector: expected_vec_crx_gpu_c1_t0, num_qubits: num_qubits_gpu };
assert_eq!(new_state_crx_gpu_c1_t0, expected_state_crx_gpu_c1_t0, "Controlled RotateX GPU (c=1, t=0) failed");
let mut initial_vec_crx_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_crx_gpu_c1_t1_control_target = (1 << control_q_gpu[0]) | (1 << target_q_gpu[0]); initial_vec_crx_gpu_c1_t1[idx_crx_gpu_c1_t1_control_target] = Complex::new(1.0, 0.0); let initial_state_crx_gpu_c1_t1 = State { state_vector: initial_vec_crx_gpu_c1_t1, num_qubits: num_qubits_gpu };
let new_state_crx_gpu_c1_t1 = initial_state_crx_gpu_c1_t1.crx_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
let mut expected_vec_crx_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_crx_gpu_c1_t1[idx_crx_gpu_c1_t1_control_target & !(1 << target_q_gpu[0])] = -i_gpu * sin_half_theta_gpu; expected_vec_crx_gpu_c1_t1[idx_crx_gpu_c1_t1_control_target] = Complex::new(cos_half_theta_gpu, 0.0); let expected_state_crx_gpu_c1_t1 = State { state_vector: expected_vec_crx_gpu_c1_t1, num_qubits: num_qubits_gpu };
assert_eq!(new_state_crx_gpu_c1_t1, expected_state_crx_gpu_c1_t1, "Controlled RotateX GPU (c=1, t=1) failed");
}
}
#[test]
fn test_operator_rotate_y_success() {
let theta: f64 = PI / 2.5;
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
let cos_half_theta: f64 = (theta / 2.0).cos();
let sin_half_theta: f64 = (theta / 2.0).sin();
let invrt2: Complex<f64> = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
let expected_zero: State =
cos_half_theta * zero_state.clone() + sin_half_theta * one_state.clone();
let expected_one: State =
-sin_half_theta * zero_state.clone() + cos_half_theta * one_state.clone();
let expected_plus: State = invrt2
* ((cos_half_theta - sin_half_theta) * zero_state.clone()
+ (cos_half_theta + sin_half_theta) * one_state.clone());
let expected_minus: State = invrt2
* ((cos_half_theta + sin_half_theta) * zero_state.clone()
- (cos_half_theta - sin_half_theta) * one_state.clone());
assert_eq!(zero_state.ry(0, theta).unwrap(), expected_zero.clone());
assert_eq!(one_state.ry(0, theta).unwrap(), expected_one.clone());
assert_eq!(plus_state.ry(0, theta).unwrap(), expected_plus.clone());
assert_eq!(minus_state.ry(0, theta).unwrap(), expected_minus.clone());
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.ry_multi(&[0, 1], theta).unwrap();
let expected_state: State = State::new_zero(2).unwrap() * cos_half_theta * cos_half_theta
+ State::new_basis_n(2, 1).unwrap() * sin_half_theta * cos_half_theta
+ State::new_basis_n(2, 2).unwrap() * sin_half_theta * cos_half_theta
+ State::new_basis_n(2, 3).unwrap() * sin_half_theta * sin_half_theta;
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 3).unwrap(); let new_state: State = state.cry_multi(&[1], &[0], PI).unwrap(); let expected_state: State = (State::new_zero(1).unwrap() * -1.0).tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 0).unwrap().tensor_product(&State::new_plus(1).unwrap()).unwrap();
let new_state: State = state.cry_multi(&[0], &[1], -PI).unwrap();
let expected_state: State = state.clone(); assert_eq!(new_state, expected_state);
assert_eq!(RotateY::new(theta).base_qubits(), 1);
let num_test_qubits_ry_unc = 11;
let angle_ry_unc = PI / 1.8;
let initial_state_ry_unc = State::new_zero(num_test_qubits_ry_unc).unwrap();
let targets_ry_unc: Vec<usize> = (0..num_test_qubits_ry_unc).collect();
let new_state_ry_unc = initial_state_ry_unc.ry_multi(&targets_ry_unc, angle_ry_unc).unwrap();
let ry_on_zero_one_q = State::new_zero(1).unwrap().ry(0, angle_ry_unc).unwrap();
let mut expected_state_ry_unc = ry_on_zero_one_q.clone();
if num_test_qubits_ry_unc > 0 { for _ in 1..num_test_qubits_ry_unc {
expected_state_ry_unc = expected_state_ry_unc.tensor_product_unchecked(&ry_on_zero_one_q);
}
} else {
panic!("num_test_qubits_ry_unc is 0, which is not expected for this test");
}
assert_eq!(new_state_ry_unc, expected_state_ry_unc, "Uncontrolled Ry parallel (multi-target) failed");
let num_test_qubits_cry = 11;
let angle_cry = PI / 2.8;
let control_q_cry = &[num_test_qubits_cry - 1];
let target_q_cry = &[0];
let initial_state_cry_c0 = State::new_zero(num_test_qubits_cry).unwrap();
let new_state_cry_c0 = initial_state_cry_c0.cry_multi(target_q_cry, control_q_cry, angle_cry).unwrap();
assert_eq!(new_state_cry_c0, initial_state_cry_c0, "Controlled Ry (c=0) parallel failed");
let mut initial_vec_cry_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cry];
let idx_cry_c1_t0 = 1 << control_q_cry[0];
initial_vec_cry_c1[idx_cry_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_cry_c1 = State { state_vector: initial_vec_cry_c1, num_qubits: num_test_qubits_cry };
let new_state_cry_c1 = initial_state_cry_c1.cry_multi(target_q_cry, control_q_cry, angle_cry).unwrap();
let ry_on_zero_for_cry = State::new_zero(1).unwrap().ry(0, angle_cry).unwrap();
let mut expected_vec_cry_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cry];
if ry_on_zero_for_cry.state_vector[0].norm_sqr() > 1e-9 {
expected_vec_cry_c1[idx_cry_c1_t0] = ry_on_zero_for_cry.state_vector[0];
}
if ry_on_zero_for_cry.state_vector[1].norm_sqr() > 1e-9 {
expected_vec_cry_c1[idx_cry_c1_t0 | (1 << target_q_cry[0])] = ry_on_zero_for_cry.state_vector[1];
}
let expected_state_cry_c1 = State { state_vector: expected_vec_cry_c1, num_qubits: num_test_qubits_cry };
assert_eq!(new_state_cry_c1, expected_state_cry_c1, "Controlled Ry (c=1) parallel failed");
#[cfg(feature = "gpu")]
{
let num_qubits_gpu = 15; let angle_gpu = PI / 3.7; let cos_half_theta_gpu = (angle_gpu / 2.0).cos();
let sin_half_theta_gpu = (angle_gpu / 2.0).sin();
let initial_state_ry_gpu_unc_t0 = State::new_zero(num_qubits_gpu).unwrap();
let new_state_ry_gpu_unc_t0 = initial_state_ry_gpu_unc_t0.ry(0, angle_gpu).unwrap();
let mut expected_vec_ry_gpu_unc_t0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_ry_gpu_unc_t0[0] = Complex::new(cos_half_theta_gpu, 0.0);
expected_vec_ry_gpu_unc_t0[1] = Complex::new(sin_half_theta_gpu, 0.0);
let expected_state_ry_gpu_unc_t0 = State { state_vector: expected_vec_ry_gpu_unc_t0, num_qubits: num_qubits_gpu };
assert_eq!(new_state_ry_gpu_unc_t0, expected_state_ry_gpu_unc_t0, "Uncontrolled RotateY GPU on |...000> failed");
let initial_state_ry_gpu_unc_t1 = State::new_basis_n(num_qubits_gpu, 1).unwrap(); let new_state_ry_gpu_unc_t1 = initial_state_ry_gpu_unc_t1.ry(0, angle_gpu).unwrap();
let mut expected_vec_ry_gpu_unc_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_ry_gpu_unc_t1[0] = Complex::new(-sin_half_theta_gpu, 0.0);
expected_vec_ry_gpu_unc_t1[1] = Complex::new(cos_half_theta_gpu, 0.0);
let expected_state_ry_gpu_unc_t1 = State { state_vector: expected_vec_ry_gpu_unc_t1, num_qubits: num_qubits_gpu };
assert_eq!(new_state_ry_gpu_unc_t1, expected_state_ry_gpu_unc_t1, "Uncontrolled RotateY GPU on |...001> failed");
let control_q_gpu = &[num_qubits_gpu - 1];
let target_q_gpu = &[0];
let initial_state_cry_gpu_c0_t0 = State::new_zero(num_qubits_gpu).unwrap();
let new_state_cry_gpu_c0_t0 = initial_state_cry_gpu_c0_t0.cry_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
assert_eq!(new_state_cry_gpu_c0_t0, initial_state_cry_gpu_c0_t0, "Controlled RotateY GPU (c=0, t=0) failed");
let mut initial_vec_cry_gpu_c0_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
initial_vec_cry_gpu_c0_t1[1 << target_q_gpu[0]] = Complex::new(1.0, 0.0);
let initial_state_cry_gpu_c0_t1 = State { state_vector: initial_vec_cry_gpu_c0_t1, num_qubits: num_qubits_gpu };
let new_state_cry_gpu_c0_t1 = initial_state_cry_gpu_c0_t1.cry_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
assert_eq!(new_state_cry_gpu_c0_t1, initial_state_cry_gpu_c0_t1, "Controlled RotateY GPU (c=0, t=1) failed");
let mut initial_vec_cry_gpu_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_cry_gpu_c1_t0_control = 1 << control_q_gpu[0];
initial_vec_cry_gpu_c1_t0[idx_cry_gpu_c1_t0_control] = Complex::new(1.0, 0.0);
let initial_state_cry_gpu_c1_t0 = State { state_vector: initial_vec_cry_gpu_c1_t0, num_qubits: num_qubits_gpu };
let new_state_cry_gpu_c1_t0 = initial_state_cry_gpu_c1_t0.cry_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
let mut expected_vec_cry_gpu_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_cry_gpu_c1_t0[idx_cry_gpu_c1_t0_control] = Complex::new(cos_half_theta_gpu, 0.0);
expected_vec_cry_gpu_c1_t0[idx_cry_gpu_c1_t0_control | (1 << target_q_gpu[0])] = Complex::new(sin_half_theta_gpu, 0.0);
let expected_state_cry_gpu_c1_t0 = State { state_vector: expected_vec_cry_gpu_c1_t0, num_qubits: num_qubits_gpu };
assert_eq!(new_state_cry_gpu_c1_t0, expected_state_cry_gpu_c1_t0, "Controlled RotateY GPU (c=1, t=0) failed");
let mut initial_vec_cry_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_cry_gpu_c1_t1_control_target = (1 << control_q_gpu[0]) | (1 << target_q_gpu[0]);
initial_vec_cry_gpu_c1_t1[idx_cry_gpu_c1_t1_control_target] = Complex::new(1.0, 0.0);
let initial_state_cry_gpu_c1_t1 = State { state_vector: initial_vec_cry_gpu_c1_t1, num_qubits: num_qubits_gpu };
let new_state_cry_gpu_c1_t1 = initial_state_cry_gpu_c1_t1.cry_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
let mut expected_vec_cry_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
expected_vec_cry_gpu_c1_t1[idx_cry_gpu_c1_t1_control_target & !(1 << target_q_gpu[0])] = Complex::new(-sin_half_theta_gpu, 0.0);
expected_vec_cry_gpu_c1_t1[idx_cry_gpu_c1_t1_control_target] = Complex::new(cos_half_theta_gpu, 0.0);
let expected_state_cry_gpu_c1_t1 = State { state_vector: expected_vec_cry_gpu_c1_t1, num_qubits: num_qubits_gpu };
assert_eq!(new_state_cry_gpu_c1_t1, expected_state_cry_gpu_c1_t1, "Controlled RotateY GPU (c=1, t=1) failed");
}
}
#[test]
fn test_operator_rotate_z_success() {
let theta: f64 = PI / 2.5;
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
let eimhalf_theta: Complex<f64> = Complex::new(0.0, -theta / 2.0).exp();
let eimhalf_theta_conj: Complex<f64> = Complex::new(0.0, theta / 2.0).exp();
let invrt2: Complex<f64> = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0);
let expected_zero: State = eimhalf_theta * zero_state.clone();
let expected_one: State = eimhalf_theta_conj * one_state.clone();
let expected_plus: State =
invrt2 * (eimhalf_theta * zero_state.clone() + eimhalf_theta_conj * one_state.clone());
let expected_minus: State =
invrt2 * (eimhalf_theta * zero_state.clone() - eimhalf_theta_conj * one_state.clone());
assert_eq!(zero_state.rz(0, theta).unwrap(), expected_zero.clone());
assert_eq!(one_state.rz(0, theta).unwrap(), expected_one.clone());
assert_eq!(plus_state.rz(0, theta).unwrap(), expected_plus.clone());
assert_eq!(minus_state.rz(0, theta).unwrap(), expected_minus.clone());
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.rz_multi(&[0, 1], theta).unwrap();
let expected_state: State = State::new_zero(2).unwrap() * eimhalf_theta * eimhalf_theta;
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 3).unwrap(); let new_state: State = state.crz_multi(&[1], &[0], PI).unwrap(); let i: Complex<f64> = Complex::new(0.0, 1.0);
let expected_state: State = (State::new_basis_n(1, 1).unwrap() * i).tensor_product(&State::new_basis_n(1, 1).unwrap()).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 0).unwrap().tensor_product(&State::new_plus(1).unwrap()).unwrap();
let new_state: State = state.crz_multi(&[0], &[1], -PI).unwrap(); let expected_state: State = state.clone(); assert_eq!(new_state, expected_state);
assert_eq!(RotateZ::new(theta).base_qubits(), 1);
let num_test_qubits_rz_unc = 11;
let angle_rz_unc = PI / 1.2;
let initial_state_rz_unc = State::new_zero(num_test_qubits_rz_unc).unwrap();
let targets_rz_unc: Vec<usize> = (0..num_test_qubits_rz_unc).collect();
let new_state_rz_unc = initial_state_rz_unc.rz_multi(&targets_rz_unc, angle_rz_unc).unwrap();
let rz_on_zero_one_q = State::new_zero(1).unwrap().rz(0, angle_rz_unc).unwrap();
let mut expected_state_rz_unc = rz_on_zero_one_q.clone();
if num_test_qubits_rz_unc > 0 { for _ in 1..num_test_qubits_rz_unc {
expected_state_rz_unc = expected_state_rz_unc.tensor_product_unchecked(&rz_on_zero_one_q);
}
} else {
panic!("num_test_qubits_rz_unc is 0, which is not expected for this test");
}
assert_eq!(new_state_rz_unc, expected_state_rz_unc, "Uncontrolled Rz parallel (multi-target) failed");
let num_test_qubits_crz = 11;
let angle_crz = PI / 3.3;
let control_q_crz = &[num_test_qubits_crz - 1];
let target_q_crz = &[0];
let initial_state_crz_c0 = State::new_zero(num_test_qubits_crz).unwrap();
let new_state_crz_c0 = initial_state_crz_c0.crz_multi(target_q_crz, control_q_crz, angle_crz).unwrap();
assert_eq!(new_state_crz_c0, initial_state_crz_c0, "Controlled Rz (c=0) parallel failed");
let mut initial_vec_crz_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_crz];
let idx_crz_c1_t0 = 1 << control_q_crz[0];
initial_vec_crz_c1_t0[idx_crz_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_crz_c1_t0 = State { state_vector: initial_vec_crz_c1_t0, num_qubits: num_test_qubits_crz };
let new_state_crz_c1_t0 = initial_state_crz_c1_t0.crz_multi(target_q_crz, control_q_crz, angle_crz).unwrap();
let rz_on_zero_for_crz = State::new_zero(1).unwrap().rz(0, angle_crz).unwrap(); let mut expected_vec_crz_c1_t0_calc = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_crz];
expected_vec_crz_c1_t0_calc[idx_crz_c1_t0] = rz_on_zero_for_crz.state_vector[0];
let expected_state_crz_c1_t0 = State { state_vector: expected_vec_crz_c1_t0_calc, num_qubits: num_test_qubits_crz };
assert_eq!(new_state_crz_c1_t0, expected_state_crz_c1_t0, "Controlled Rz (c=1, t=0) parallel failed");
#[cfg(feature = "gpu")]
{
let num_qubits_gpu = 15; let angle_gpu = PI / 3.7; let e_neg_i_half_theta_gpu = Complex::new(0.0, -angle_gpu / 2.0).exp();
let e_pos_i_half_theta_gpu = Complex::new(0.0, angle_gpu / 2.0).exp();
let initial_state_rz_gpu_unc_t0 = State::new_zero(num_qubits_gpu).unwrap();
let new_state_rz_gpu_unc_t0 = initial_state_rz_gpu_unc_t0.rz(0, angle_gpu).unwrap();
let expected_state_rz_gpu_unc_t0 = initial_state_rz_gpu_unc_t0.clone() * e_neg_i_half_theta_gpu;
assert_eq!(new_state_rz_gpu_unc_t0, expected_state_rz_gpu_unc_t0, "Uncontrolled RotateZ GPU on |...000> failed");
let initial_state_rz_gpu_unc_t1 = State::new_basis_n(num_qubits_gpu, 1).unwrap(); let new_state_rz_gpu_unc_t1 = initial_state_rz_gpu_unc_t1.rz(0, angle_gpu).unwrap();
let expected_state_rz_gpu_unc_t1 = initial_state_rz_gpu_unc_t1.clone() * e_pos_i_half_theta_gpu;
assert_eq!(new_state_rz_gpu_unc_t1, expected_state_rz_gpu_unc_t1, "Uncontrolled RotateZ GPU on |...001> failed");
let control_q_gpu = &[num_qubits_gpu - 1];
let target_q_gpu = &[0];
let initial_state_crz_gpu_c0_t0 = State::new_zero(num_qubits_gpu).unwrap();
let new_state_crz_gpu_c0_t0 = initial_state_crz_gpu_c0_t0.crz_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
assert_eq!(new_state_crz_gpu_c0_t0, initial_state_crz_gpu_c0_t0, "Controlled RotateZ GPU (c=0, t=0) failed");
let mut initial_vec_crz_gpu_c0_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
initial_vec_crz_gpu_c0_t1[1 << target_q_gpu[0]] = Complex::new(1.0, 0.0);
let initial_state_crz_gpu_c0_t1 = State { state_vector: initial_vec_crz_gpu_c0_t1, num_qubits: num_qubits_gpu };
let new_state_crz_gpu_c0_t1 = initial_state_crz_gpu_c0_t1.crz_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
assert_eq!(new_state_crz_gpu_c0_t1, initial_state_crz_gpu_c0_t1, "Controlled RotateZ GPU (c=0, t=1) failed");
let mut initial_vec_crz_gpu_c1_t0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_crz_gpu_c1_t0_control = 1 << control_q_gpu[0];
initial_vec_crz_gpu_c1_t0[idx_crz_gpu_c1_t0_control] = Complex::new(1.0, 0.0);
let initial_state_crz_gpu_c1_t0 = State { state_vector: initial_vec_crz_gpu_c1_t0, num_qubits: num_qubits_gpu };
let new_state_crz_gpu_c1_t0 = initial_state_crz_gpu_c1_t0.crz_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
let expected_state_crz_gpu_c1_t0 = initial_state_crz_gpu_c1_t0.clone() * e_neg_i_half_theta_gpu;
assert_eq!(new_state_crz_gpu_c1_t0, expected_state_crz_gpu_c1_t0, "Controlled RotateZ GPU (c=1, t=0) failed");
let mut initial_vec_crz_gpu_c1_t1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_crz_gpu_c1_t1_control_target = (1 << control_q_gpu[0]) | (1 << target_q_gpu[0]);
initial_vec_crz_gpu_c1_t1[idx_crz_gpu_c1_t1_control_target] = Complex::new(1.0, 0.0);
let initial_state_crz_gpu_c1_t1 = State { state_vector: initial_vec_crz_gpu_c1_t1, num_qubits: num_qubits_gpu };
let new_state_crz_gpu_c1_t1 = initial_state_crz_gpu_c1_t1.crz_multi(target_q_gpu, control_q_gpu, angle_gpu).unwrap();
let expected_state_crz_gpu_c1_t1 = initial_state_crz_gpu_c1_t1.clone() * e_pos_i_half_theta_gpu;
assert_eq!(new_state_crz_gpu_c1_t1, expected_state_crz_gpu_c1_t1, "Controlled RotateZ GPU (c=1, t=1) failed");
}
}
#[test]
fn test_operator_unitary2_success() {
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
let u: [[Complex<f64>; 2]; 2] = [
[Complex::new(0.0, 0.0), Complex::new(1.0, 0.0)],
[Complex::new(1.0, 0.0), Complex::new(0.0, 0.0)],
];
let expected_zero: State = one_state.clone();
let expected_one: State = zero_state.clone();
let expected_plus: State = plus_state.clone();
let expected_minus: State = minus_state.clone() * -1.0;
assert_eq!(zero_state.unitary(0, u).unwrap(), expected_zero.clone());
assert_eq!(one_state.unitary(0, u).unwrap(), expected_one.clone());
assert_eq!(plus_state.unitary(0, u).unwrap(), expected_plus.clone());
assert_eq!(minus_state.unitary(0, u).unwrap(), expected_minus.clone());
let two_qubit_state: State = State::new_zero(2).unwrap();
let new_state: State = two_qubit_state.unitary_multi(&[0, 1], u).unwrap();
let expected_state: State = State::new_basis_n(2, 3).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 3).unwrap(); let new_state: State = state.cunitary_multi(&[1], &[0], u).unwrap(); let expected_state: State = State::new_basis_n(2, 1).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 0).unwrap().tensor_product(&State::new_plus(1).unwrap()).unwrap();
let new_state: State = state.cunitary_multi(&[0], &[1], u).unwrap(); let expected_state: State = state.clone(); assert_eq!(new_state, expected_state);
assert_eq!(Unitary2::new(u).unwrap().base_qubits(), 1);
let invalid_u: [[Complex<f64>; 2]; 2] = [
[Complex::new(0.0, 0.0), Complex::new(1.0, 0.0)],
[Complex::new(1.0, 0.0), Complex::new(1.0, 0.0)],
];
let invalid_unitary = Unitary2::new(invalid_u);
assert!(invalid_unitary.is_err(), "Invalid unitary matrix should return an error.");
let num_test_qubits_u_unc = 11;
let u_matrix_unc = u; let initial_state_u_unc = State::new_zero(num_test_qubits_u_unc).unwrap();
let targets_u_unc: Vec<usize> = (0..num_test_qubits_u_unc).collect();
let new_state_u_unc = initial_state_u_unc.unitary_multi(&targets_u_unc, u_matrix_unc).unwrap();
let expected_state_u_unc = State::new_basis_n(num_test_qubits_u_unc, (1 << num_test_qubits_u_unc) - 1).unwrap(); assert_eq!(new_state_u_unc, expected_state_u_unc, "Uncontrolled Unitary2 (X) parallel (multi-target) failed");
let num_test_qubits_cu = 11;
let u_matrix_cu = u; let control_q_cu = &[num_test_qubits_cu - 1];
let target_q_cu = &[0];
let initial_state_cu_c0 = State::new_zero(num_test_qubits_cu).unwrap();
let new_state_cu_c0 = initial_state_cu_c0.cunitary_multi(target_q_cu, control_q_cu, u_matrix_cu).unwrap();
assert_eq!(new_state_cu_c0, initial_state_cu_c0, "Controlled Unitary2 (X) (c=0) parallel failed");
let mut initial_vec_cu_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cu];
let idx_cu_c1_t0 = 1 << control_q_cu[0];
initial_vec_cu_c1[idx_cu_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_cu_c1 = State { state_vector: initial_vec_cu_c1, num_qubits: num_test_qubits_cu };
let new_state_cu_c1 = initial_state_cu_c1.cunitary_multi(target_q_cu, control_q_cu, u_matrix_cu).unwrap();
let u_on_zero_for_cu = State::new_zero(1).unwrap().unitary(0, u_matrix_cu).unwrap(); let mut expected_vec_cu_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cu];
if u_on_zero_for_cu.state_vector[0].norm_sqr() > 1e-9 {
expected_vec_cu_c1[idx_cu_c1_t0] = u_on_zero_for_cu.state_vector[0];
}
if u_on_zero_for_cu.state_vector[1].norm_sqr() > 1e-9 {
expected_vec_cu_c1[idx_cu_c1_t0 | (1 << target_q_cu[0])] = u_on_zero_for_cu.state_vector[1];
}
let expected_state_cu_c1 = State { state_vector: expected_vec_cu_c1, num_qubits: num_test_qubits_cu };
assert_eq!(new_state_cu_c1, expected_state_cu_c1, "Controlled Unitary2 (X) (c=1) parallel failed");
}
#[test]
fn test_operator_ry_phase_success() {
let theta: f64 = PI / 2.5; let phi: f64 = PI / 4.0;
let zero_state: State = State::new_zero(1).unwrap();
let one_state: State = State::new_basis_n(1, 1).unwrap();
let plus_state: State = State::new_plus(1).unwrap();
let minus_state: State = State::new_minus(1).unwrap();
let new_zero_state = zero_state.ry_phase(0, theta, phi).unwrap();
let expected_zero_state = zero_state.p(0, phi).ry(0, theta).unwrap();
let new_one_state = one_state.ry_phase(0, theta, phi).unwrap();
let expected_one_state = one_state.p(0, phi).ry(0, theta).unwrap();
let new_plus_state = plus_state.ry_phase(0, theta, phi).unwrap();
let expected_plus_state = plus_state.p(0, phi).ry(0, theta).unwrap();
let new_minus_state = minus_state.ry_phase(0, theta, phi).unwrap();
let expected_minus_state = minus_state.p(0, phi).ry(0, theta).unwrap();
assert_eq!(new_zero_state, expected_zero_state);
assert_eq!(new_one_state, expected_one_state);
assert_eq!(new_plus_state, expected_plus_state);
assert_eq!(new_minus_state, expected_minus_state);
let zero_state_3q: State = State::new_zero(3).unwrap();
let new_zero_state_3q = zero_state_3q.ry_phase(0, theta, 0.0).unwrap();
let expected_zero_state_3q = zero_state_3q.ry(0, theta).unwrap();
let one_state_3q: State = State::new_basis_n(3, 1).unwrap();
let new_one_state_3q = one_state_3q.ry_phase(0, theta, 0.0).unwrap();
let expected_one_state_3q = one_state_3q.ry(0, theta).unwrap();
let plus_state_3q: State = State::new_plus(3).unwrap();
let new_plus_state_3q = plus_state_3q.ry_phase(0, theta, 0.0).unwrap();
let expected_plus_state_3q = plus_state_3q.ry(0, theta).unwrap();
let minus_state_3q: State = State::new_minus(3).unwrap();
let new_minus_state_3q = minus_state_3q.ry_phase(0, theta, 0.0).unwrap();
let expected_minus_state_3q = minus_state_3q.ry(0, theta).unwrap();
assert_eq!(new_zero_state_3q, expected_zero_state_3q);
assert_eq!(new_one_state_3q, expected_one_state_3q);
assert_eq!(new_plus_state_3q, expected_plus_state_3q);
assert_eq!(new_minus_state_3q, expected_minus_state_3q);
let zero_state_3q_p: State = State::new_zero(3).unwrap();
let new_zero_state_3q_p = zero_state_3q_p.ry_phase(0, 0.0, phi).unwrap();
let expected_zero_state_3q_p = zero_state_3q_p.p(0, phi).unwrap();
let one_state_3q_p: State = State::new_basis_n(3, 1).unwrap();
let new_one_state_3q_p = one_state_3q_p.ry_phase(0, 0.0, phi).unwrap();
let expected_one_state_3q_p = one_state_3q_p.p(0, phi).unwrap();
let plus_state_3q_p: State = State::new_plus(3).unwrap();
let new_plus_state_3q_p = plus_state_3q_p.ry_phase(0, 0.0, phi).unwrap();
let expected_plus_state_3q_p = plus_state_3q_p.p(0, phi).unwrap();
let minus_state_3q_p: State = State::new_minus(3).unwrap();
let new_minus_state_3q_p = minus_state_3q_p.ry_phase(0, 0.0, phi).unwrap();
let expected_minus_state_3q_p = minus_state_3q_p.p(0, phi).unwrap();
assert_eq!(new_zero_state_3q_p, expected_zero_state_3q_p);
assert_eq!(new_one_state_3q_p, expected_one_state_3q_p);
assert_eq!(new_plus_state_3q_p, expected_plus_state_3q_p);
assert_eq!(new_minus_state_3q_p, expected_minus_state_3q_p);
let theta_pi2: f64 = PI / 2.0;
let phi_pi: f64 = PI;
let zero_state_3q_h: State = State::new_zero(3).unwrap();
let new_zero_state_3q_h = zero_state_3q_h.ry_phase(0, theta_pi2, phi_pi).unwrap();
let expected_zero_state_3q_h = zero_state_3q_h.h(0).unwrap();
let one_state_3q_h: State = State::new_basis_n(3, 1).unwrap();
let new_one_state_3q_h = one_state_3q_h.ry_phase(0, theta_pi2, phi_pi).unwrap();
let expected_one_state_3q_h = one_state_3q_h.h(0).unwrap();
let plus_state_3q_h: State = State::new_plus(3).unwrap();
let new_plus_state_3q_h = plus_state_3q_h.ry_phase(0, theta_pi2, phi_pi).unwrap();
let expected_plus_state_3q_h = plus_state_3q_h.h(0).unwrap();
let minus_state_3q_h: State = State::new_minus(3).unwrap();
let new_minus_state_3q_h = minus_state_3q_h.ry_phase(0, theta_pi2, phi_pi).unwrap();
let expected_minus_state_3q_h = minus_state_3q_h.h(0).unwrap();
assert_eq!(new_zero_state_3q_h, expected_zero_state_3q_h);
assert_eq!(new_one_state_3q_h, expected_one_state_3q_h);
assert_eq!(new_plus_state_3q_h, expected_plus_state_3q_h);
assert_eq!(new_minus_state_3q_h, expected_minus_state_3q_h);
let theta_pi: f64 = PI;
let phi_pi: f64 = PI;
let zero_state_3q_x: State = State::new_zero(3).unwrap();
let new_zero_state_3q_x = zero_state_3q_x.ry_phase(0, theta_pi, phi_pi).unwrap();
let expected_zero_state_3q_x = zero_state_3q_x.x(0).unwrap();
let one_state_3q_x: State = State::new_basis_n(3, 1).unwrap();
let new_one_state_3q_x = one_state_3q_x.ry_phase(0, theta_pi, phi_pi).unwrap();
let expected_one_state_3q_x = one_state_3q_x.x(0).unwrap();
let plus_state_3q_x: State = State::new_plus(3).unwrap();
let new_plus_state_3q_x = plus_state_3q_x.ry_phase(0, theta_pi, phi_pi).unwrap();
let expected_plus_state_3q_x = plus_state_3q_x.x(0).unwrap();
let minus_state_3q_x: State = State::new_minus(3).unwrap();
let new_minus_state_3q_x = minus_state_3q_x.ry_phase(0, theta_pi, phi_pi).unwrap();
let expected_minus_state_3q_x = minus_state_3q_x.x(0).unwrap();
assert_eq!(new_zero_state_3q_x, expected_zero_state_3q_x);
assert_eq!(new_one_state_3q_x, expected_one_state_3q_x);
assert_eq!(new_plus_state_3q_x, expected_plus_state_3q_x);
assert_eq!(new_minus_state_3q_x, expected_minus_state_3q_x);
}
#[test]
fn test_operator_ry_phase_dag_success() {
let theta = PI / 1.5; let phi = PI / 3.25;
let zero_state = State::new_zero(3).unwrap();
let new_zero_state = zero_state.ry_phase(0, theta, phi).ry_phase_dag(0, theta, phi).unwrap();
assert_eq!(new_zero_state, zero_state);
let one_state = State::new_basis_n(3, 1).unwrap();
let new_one_state = one_state.ry_phase(0, theta, phi).ry_phase_dag(0, theta, phi).unwrap();
assert_eq!(new_one_state, one_state);
let plus_state = State::new_plus(3).unwrap();
let new_plus_state = plus_state.ry_phase(0, theta, phi).ry_phase_dag(0, theta, phi).unwrap();
assert_eq!(new_plus_state, plus_state);
let minus_state = State::new_minus(3).unwrap();
let new_minus_state = minus_state.ry_phase(0, theta, phi).ry_phase_dag(0, theta, phi).unwrap();
assert_eq!(new_minus_state, minus_state);
}
#[test]
fn test_operator_cnot_success() {
let state: State = State::new_zero(2).unwrap();
let new_state: State = state.cnot(0, 1).unwrap();
let expected_state: State = State::new_zero(2).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 2).unwrap();
let new_state: State = state.cnot(0, 1).unwrap();
let expected_state: State = State::new_basis_n(2, 2).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 1).unwrap();
let new_state: State = state.cnot(0, 1).unwrap();
let expected_state: State = State::new_basis_n(2, 3).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 3).unwrap();
let new_state: State = state.cnot(0, 1).unwrap();
let expected_state: State = State::new_basis_n(2, 1).unwrap();
assert_eq!(new_state, expected_state);
let state: State =
1.0 / 2.0_f64.sqrt() * (State::new_zero(2).unwrap() + State::new_basis_n(2, 1).unwrap());
let new_state: State = state.cnot(0, 1).unwrap();
let expected_state: State = Complex::new(1.0 / 2.0_f64.sqrt(), 0.0)
* (State::new_basis_n(2, 0).unwrap() + State::new_basis_n(2, 3).unwrap());
assert_eq!(new_state, expected_state);
assert_eq!(CNOT.base_qubits(), 2);
let num_test_qubits_cnot_par = 11;
let control_cnot_par = num_test_qubits_cnot_par - 1; let target_cnot_par = 0;
let initial_state_cnot_par_c0 = State::new_zero(num_test_qubits_cnot_par).unwrap();
let new_state_cnot_par_c0 = initial_state_cnot_par_c0.cnot(control_cnot_par, target_cnot_par).unwrap();
assert_eq!(new_state_cnot_par_c0, initial_state_cnot_par_c0, "CNOT parallel (control=0) failed");
let mut initial_vec_cnot_par_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cnot_par];
let idx_cnot_par_c1_t0 = 1 << control_cnot_par; initial_vec_cnot_par_c1[idx_cnot_par_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_cnot_par_c1 = State { state_vector: initial_vec_cnot_par_c1, num_qubits: num_test_qubits_cnot_par };
let new_state_cnot_par_c1 = initial_state_cnot_par_c1.cnot(control_cnot_par, target_cnot_par).unwrap();
let mut expected_vec_cnot_par_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cnot_par];
expected_vec_cnot_par_c1[idx_cnot_par_c1_t0 | (1 << target_cnot_par)] = Complex::new(1.0, 0.0); let expected_state_cnot_par_c1 = State { state_vector: expected_vec_cnot_par_c1, num_qubits: num_test_qubits_cnot_par };
assert_eq!(new_state_cnot_par_c1, expected_state_cnot_par_c1, "CNOT parallel (control=1) failed");
let num_test_qubits_ccnot_par = 11;
let c1_ccnot_par = num_test_qubits_ccnot_par - 1; let c2_ccnot_par = num_test_qubits_ccnot_par - 2; let t_ccnot_par = 0;
let initial_state_ccnot_par_c00 = State::new_zero(num_test_qubits_ccnot_par).unwrap();
let new_state_ccnot_par_c00 = initial_state_ccnot_par_c00.toffoli(c1_ccnot_par, c2_ccnot_par, t_ccnot_par).unwrap();
assert_eq!(new_state_ccnot_par_c00, initial_state_ccnot_par_c00, "Toffoli (as controlled CNOT) parallel (controls 00) failed");
let mut initial_vec_ccnot_par_c11 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_ccnot_par];
let idx_ccnot_par_c11_t0 = (1 << c1_ccnot_par) | (1 << c2_ccnot_par); initial_vec_ccnot_par_c11[idx_ccnot_par_c11_t0] = Complex::new(1.0, 0.0);
let initial_state_ccnot_par_c11 = State { state_vector: initial_vec_ccnot_par_c11, num_qubits: num_test_qubits_ccnot_par };
let new_state_ccnot_par_c11 = initial_state_ccnot_par_c11.toffoli(c1_ccnot_par, c2_ccnot_par, t_ccnot_par).unwrap();
let mut expected_vec_ccnot_par_c11 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_ccnot_par];
expected_vec_ccnot_par_c11[idx_ccnot_par_c11_t0 | (1 << t_ccnot_par)] = Complex::new(1.0, 0.0); let expected_state_ccnot_par_c11 = State { state_vector: expected_vec_ccnot_par_c11, num_qubits: num_test_qubits_ccnot_par };
assert_eq!(new_state_ccnot_par_c11, expected_state_ccnot_par_c11, "Toffoli (as controlled CNOT) parallel (controls 11) failed");
}
#[test]
fn test_operator_swap_success() {
let state: State = State::new_zero(2).unwrap();
let new_state: State = state.swap(0, 1).unwrap();
let expected_state: State = State::new_zero(2).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 2).unwrap();
let new_state: State = state.swap(0, 1).unwrap();
let expected_state: State = State::new_basis_n(2, 1).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 1).unwrap();
let new_state: State = state.swap(0, 1).unwrap();
let expected_state: State = State::new_basis_n(2, 2).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(2, 3).unwrap();
let new_state: State = state.swap(0, 1).unwrap();
let expected_state: State = State::new_basis_n(2, 3).unwrap();
assert_eq!(new_state, expected_state);
let state: State = 1.0 / 2.0
* (State::new_zero(2).unwrap() - State::new_basis_n(2, 1).unwrap()
+ State::new_basis_n(2, 2).unwrap()
- State::new_basis_n(2, 3).unwrap());
let new_state: State = state.swap(0, 1).unwrap();
let expected_state: State = 1.0 / 2.0
* (State::new_zero(2).unwrap() + State::new_basis_n(2, 1).unwrap()
- State::new_basis_n(2, 2).unwrap()
- State::new_basis_n(2, 3).unwrap());
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(3, 3).unwrap(); let new_state: State = state.cswap(1, 2, &[0]).unwrap(); let expected_state: State = State::new_basis_n(3, 5).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(3, 4).unwrap(); let new_state: State = state.cswap(1, 2, &[0]).unwrap(); let expected_state: State = State::new_basis_n(3, 4).unwrap(); assert_eq!(new_state, expected_state);
assert_eq!(SWAP.base_qubits(), 2);
let num_test_qubits_swap_par = 11;
let t1_swap_par = 0; let t2_swap_par = 1;
let mut initial_vec_swap_par = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_swap_par];
initial_vec_swap_par[1 << t1_swap_par] = Complex::new(1.0, 0.0); let initial_state_swap_par = State { state_vector: initial_vec_swap_par, num_qubits: num_test_qubits_swap_par };
let new_state_swap_par = initial_state_swap_par.swap(t1_swap_par, t2_swap_par).unwrap();
let mut expected_vec_swap_par = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_swap_par];
expected_vec_swap_par[1 << t2_swap_par] = Complex::new(1.0, 0.0); let expected_state_swap_par = State { state_vector: expected_vec_swap_par, num_qubits: num_test_qubits_swap_par };
assert_eq!(new_state_swap_par, expected_state_swap_par, "SWAP parallel failed");
let num_test_qubits_cswap_par = 11;
let control_cswap_par = &[num_test_qubits_cswap_par - 1]; let t1_cswap_par = 0; let t2_cswap_par = 1;
let mut initial_vec_cswap_par_c0 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cswap_par];
initial_vec_cswap_par_c0[1 << t1_cswap_par] = Complex::new(1.0, 0.0); let initial_state_cswap_par_c0 = State { state_vector: initial_vec_cswap_par_c0, num_qubits: num_test_qubits_cswap_par };
let new_state_cswap_par_c0 = initial_state_cswap_par_c0.cswap(t1_cswap_par, t2_cswap_par, control_cswap_par).unwrap();
assert_eq!(new_state_cswap_par_c0, initial_state_cswap_par_c0, "CSWAP parallel (control=0) failed");
let mut initial_vec_cswap_par_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cswap_par];
let idx_cswap_par_c1_t1_is_1 = (1 << control_cswap_par[0]) | (1 << t1_cswap_par); initial_vec_cswap_par_c1[idx_cswap_par_c1_t1_is_1] = Complex::new(1.0, 0.0);
let initial_state_cswap_par_c1 = State { state_vector: initial_vec_cswap_par_c1, num_qubits: num_test_qubits_cswap_par };
let new_state_cswap_par_c1 = initial_state_cswap_par_c1.cswap(t1_cswap_par, t2_cswap_par, control_cswap_par).unwrap();
let mut expected_vec_cswap_par_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cswap_par];
expected_vec_cswap_par_c1[(1 << control_cswap_par[0]) | (1 << t2_cswap_par)] = Complex::new(1.0, 0.0); let expected_state_cswap_par_c1 = State { state_vector: expected_vec_cswap_par_c1, num_qubits: num_test_qubits_cswap_par };
assert_eq!(new_state_cswap_par_c1, expected_state_cswap_par_c1, "CSWAP parallel (control=1) failed");
#[cfg(feature = "gpu")]
{
let num_qubits_gpu = 15; let t1_gpu = 0;
let t2_gpu = 1;
let mut initial_vec_swap_gpu_unc = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_initial_unc = 1 << t1_gpu;
initial_vec_swap_gpu_unc[idx_initial_unc] = Complex::new(1.0, 0.0);
let initial_state_swap_gpu_unc = State { state_vector: initial_vec_swap_gpu_unc, num_qubits: num_qubits_gpu };
let new_state_swap_gpu_unc = initial_state_swap_gpu_unc.swap(t1_gpu, t2_gpu).unwrap();
let mut expected_vec_swap_gpu_unc = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_expected_unc = 1 << t2_gpu; expected_vec_swap_gpu_unc[idx_expected_unc] = Complex::new(1.0, 0.0);
let expected_state_swap_gpu_unc = State { state_vector: expected_vec_swap_gpu_unc, num_qubits: num_qubits_gpu };
assert_eq!(new_state_swap_gpu_unc, expected_state_swap_gpu_unc, "Uncontrolled SWAP GPU failed");
let control_q_gpu = &[num_qubits_gpu - 1];
let mut initial_vec_cswap_gpu_c0 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_cswap_initial_c0 = 1 << t1_gpu;
initial_vec_cswap_gpu_c0[idx_cswap_initial_c0] = Complex::new(1.0, 0.0);
let initial_state_cswap_gpu_c0 = State { state_vector: initial_vec_cswap_gpu_c0, num_qubits: num_qubits_gpu };
let new_state_cswap_gpu_c0 = initial_state_cswap_gpu_c0.cswap(t1_gpu, t2_gpu, control_q_gpu).unwrap();
assert_eq!(new_state_cswap_gpu_c0, initial_state_cswap_gpu_c0, "Controlled SWAP GPU (control=0) failed");
let mut initial_vec_cswap_gpu_c1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_cswap_initial_c1 = (1 << control_q_gpu[0]) | (1 << t1_gpu);
initial_vec_cswap_gpu_c1[idx_cswap_initial_c1] = Complex::new(1.0, 0.0);
let initial_state_cswap_gpu_c1 = State { state_vector: initial_vec_cswap_gpu_c1, num_qubits: num_qubits_gpu };
let new_state_cswap_gpu_c1 = initial_state_cswap_gpu_c1.cswap(t1_gpu, t2_gpu, control_q_gpu).unwrap();
let mut expected_vec_cswap_gpu_c1 = vec![Complex::new(0.0, 0.0); 1 << num_qubits_gpu];
let idx_cswap_expected_c1 = (1 << control_q_gpu[0]) | (1 << t2_gpu);
expected_vec_cswap_gpu_c1[idx_cswap_expected_c1] = Complex::new(1.0, 0.0);
let expected_state_cswap_gpu_c1 = State { state_vector: expected_vec_cswap_gpu_c1, num_qubits: num_qubits_gpu };
assert_eq!(new_state_cswap_gpu_c1, expected_state_cswap_gpu_c1, "Controlled SWAP GPU (control=1) failed");
}
}
#[test]
fn test_operator_matchgate_success() {
let state: State = State::new_basis_n(3, 5).unwrap(); let new_state: State = state.matchgate(1, PI, PI, 0.0).expect("Matchgate failed");
let expected_state: State = State::new_basis_n(3, 3).unwrap(); assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(3, 5).unwrap(); let new_state: State = state.matchgate(1, PI, PI, 0.0).expect("Matchgate failed");
let new_state_again: State = new_state.matchgate(1, PI, PI, 0.0).expect("Matchgate failed");
assert_eq!(new_state_again, state, "Matchgate should return to original state after two applications");
let state_00: State = State::new_basis_n(2, 0).unwrap(); let state_01: State = State::new_basis_n(2, 1).unwrap(); let state_10: State = State::new_basis_n(2, 2).unwrap(); let state_11: State = State::new_basis_n(2, 3).unwrap();
let theta: f64 = PI;
let phi1: f64 = PI / 2.0;
let phi2: f64 = PI / 3.0;
let new_state_00: State = state_00.matchgate(0, theta, phi1, phi2).expect("Matchgate failed");
let expected_state_00: State = State::new_basis_n(2, 0).unwrap();
assert_eq!(new_state_00, expected_state_00, "Matchgate on |00> failed");
let new_state_01: State = state_01.matchgate(0, theta, phi1, phi2).expect("Matchgate failed");
let expected_state_01: State = State::new_basis_n(2, 2).unwrap();
assert_eq!(new_state_01, expected_state_01, "Matchgate on |01> failed");
let new_state_10: State = state_10.matchgate(0, theta, phi1, phi2).expect("Matchgate failed");
let expected_state_10: State = State::new_basis_n(2, 1).unwrap() * Complex::new(0.0, -1.0);
assert_eq!(new_state_10, expected_state_10, "M|10> = -i|01> failed");
let new_state_11: State = state_11.matchgate(0, theta, phi1, phi2).expect("Matchgate failed");
let expected_state_11: State = State::new_basis_n(2, 3).unwrap() * Complex::exp(Complex::new(0.0, PI / 3.0));
assert_eq!(new_state_11, expected_state_11, "M|11> = e^(i pi/3) |11> failed");
assert_eq!(Matchgate{theta: 1.0, phi1: 2.0, phi2: 3.0}.base_qubits(), 2, "Matchgate base qubits should be 2");
let state_control: State = State::new_basis_n(3, 3).unwrap(); let new_state_control: State = state_control.cmatchgate(1, PI, PI / 2.0, PI / 3.0, &[0]).expect("Controlled Matchgate failed");
let expected_state_control: State = State::new_basis_n(3, 5).unwrap(); assert_eq!(new_state_control, expected_state_control, "Controlled Matchgate failed");
let state_control_0: State = State::new_basis_n(3, 4).unwrap(); let new_state_control_0: State = state_control_0.cmatchgate(1, PI, PI / 2.0, PI / 3.0, &[0]).expect("Controlled Matchgate failed");
let expected_state_control_0: State = State::new_basis_n(3, 4).unwrap(); assert_eq!(new_state_control_0, expected_state_control_0, "Controlled Matchgate with control 0 failed");
let num_test_qubits_matchgate_par = 11;
let theta_matchgate_par = PI;
let phi1_matchgate_par = PI / 2.0;
let phi2_matchgate_par = PI / 3.0;
let state_matchgate_par_01: State = State::new_basis_n(num_test_qubits_matchgate_par, 1).unwrap(); let new_state_matchgate_par_01: State = state_matchgate_par_01.matchgate(0, theta_matchgate_par, phi1_matchgate_par, phi2_matchgate_par).expect("Matchgate parallel (targets 0 and 1) failed");
let expected_state_matchgate_par_01: State = State::new_basis_n(num_test_qubits_matchgate_par, 2).unwrap(); assert_eq!(new_state_matchgate_par_01, expected_state_matchgate_par_01, "Matchgate parallel (targets 0 and 1) failed");
let state_matchgate_par_10: State = State::new_basis_n(num_test_qubits_matchgate_par, 2).unwrap(); let new_state_matchgate_par_10: State = state_matchgate_par_10.matchgate(0, theta_matchgate_par, phi1_matchgate_par, phi2_matchgate_par).expect("Matchgate parallel (targets 0 and 1) failed");
let expected_state_matchgate_par_10: State = State::new_basis_n(num_test_qubits_matchgate_par, 1).unwrap() * Complex::new(0.0, -1.0); assert_eq!(new_state_matchgate_par_10, expected_state_matchgate_par_10, "Matchgate parallel (targets 0 and 1) failed");
let control_matchgate_par = &[num_test_qubits_matchgate_par - 1]; let controls_matchgate_par = &[num_test_qubits_matchgate_par - 1, num_test_qubits_matchgate_par - 2]; let num_test_qubits_cmatchgate_par = 11;
let theta_cmatchgate_par = PI;
let phi1_cmatchgate_par = PI / 2.0;
let phi2_cmatchgate_par = PI / 3.0;
let state_cmatchgate_par_01_c0: State = State::new_basis_n(num_test_qubits_cmatchgate_par, 1).unwrap(); let new_state_cmatchgate_par_01_c0: State = state_cmatchgate_par_01_c0.cmatchgate(0, theta_cmatchgate_par, phi1_cmatchgate_par, phi2_cmatchgate_par, control_matchgate_par).expect("Controlled Matchgate parallel (targets 0 and 1, control 0) failed");
assert_eq!(new_state_cmatchgate_par_01_c0, state_cmatchgate_par_01_c0, "Controlled Matchgate parallel (targets 0 and 1, control 0) failed");
let state_cmatchgate_par_10_c0: State = State::new_basis_n(num_test_qubits_cmatchgate_par, 2).unwrap(); let new_state_cmatchgate_par_10_c0: State = state_cmatchgate_par_10_c0.cmatchgate(0, theta_cmatchgate_par, phi1_cmatchgate_par, phi2_cmatchgate_par, control_matchgate_par).expect("Controlled Matchgate parallel (targets 0 and 1, control 0) failed");
assert_eq!(new_state_cmatchgate_par_10_c0, state_cmatchgate_par_10_c0);
let state_cmatchgate_par_01_c1: State = State::new_basis_n(num_test_qubits_cmatchgate_par, 1024 + 1).unwrap(); let new_state_cmatchgate_par_01_c1: State = state_cmatchgate_par_01_c1.cmatchgate(0, theta_cmatchgate_par, phi1_cmatchgate_par, phi2_cmatchgate_par, control_matchgate_par).expect("Controlled Matchgate parallel (targets 0 and 1, control 1) failed");
let expected_state_cmatchgate_par_01_c1: State = State::new_basis_n(num_test_qubits_cmatchgate_par, 1024 + 2).unwrap(); assert_eq!(new_state_cmatchgate_par_01_c1, expected_state_cmatchgate_par_01_c1, "Controlled Matchgate parallel (targets 0 and 1, control 1) failed");
let state_cmatchgate_par_10_c1: State = State::new_basis_n(num_test_qubits_cmatchgate_par, 1024 + 2).unwrap(); let new_state_cmatchgate_par_10_c1: State = state_cmatchgate_par_10_c1.cmatchgate(0, theta_cmatchgate_par, phi1_cmatchgate_par, phi2_cmatchgate_par, control_matchgate_par).expect("Controlled Matchgate parallel (targets 0 and 1, control 1) failed");
let expected_state_cmatchgate_par_10_c1: State = State::new_basis_n(num_test_qubits_cmatchgate_par, 1024 + 1).unwrap() * Complex::new(0.0, -1.0); assert_eq!(new_state_cmatchgate_par_10_c1, expected_state_cmatchgate_par_10_c1, "Controlled Matchgate parallel (targets 0 and 1, control 1) failed");
let state_cmatchgate_par_01_c01: State = State::new_basis_n(num_test_qubits_cmatchgate_par, 1024 + 1).unwrap(); let new_state_cmatchgate_par_01_c01: State = state_cmatchgate_par_01_c01.cmatchgate(0, theta_cmatchgate_par, phi1_cmatchgate_par, phi2_cmatchgate_par, controls_matchgate_par).expect("Controlled Matchgate parallel (targets 0 and 1, controls 0 and 1) failed");
assert_eq!(new_state_cmatchgate_par_01_c01, state_cmatchgate_par_01_c01, "Controlled Matchgate parallel (targets 0 and 1, controls 0 and 1) failed");
let state_cmatchgate_par_10_c11: State = State::new_basis_n(num_test_qubits_cmatchgate_par, 1024 + 512 + 2).unwrap(); let new_state_cmatchgate_par_10_c11: State = state_cmatchgate_par_10_c11.cmatchgate(0, theta_cmatchgate_par, phi1_cmatchgate_par, phi2_cmatchgate_par, controls_matchgate_par).expect("Controlled Matchgate parallel (targets 0 and 1, controls 1 and 1) failed");
let expected_state_cmatchgate_par_10_c11: State = State::new_basis_n(num_test_qubits_cmatchgate_par, 1024 + 512 + 1).unwrap() * Complex::new(0.0, -1.0); assert_eq!(new_state_cmatchgate_par_10_c11, expected_state_cmatchgate_par_10_c11, "Controlled Matchgate parallel (targets 0 and 1, controls 1 and 1) failed");
#[cfg(feature = "gpu")]
{
let num_test_qubits_matchgate_gpu = 15;
let theta_matchgate_gpu = PI;
let phi1_matchgate_gpu = PI / 2.0;
let phi2_matchgate_gpu = PI / 3.0;
let state_matchgate_gpu_01: State = State::new_basis_n(num_test_qubits_matchgate_gpu, 1).unwrap(); let new_state_matchgate_gpu_01: State = state_matchgate_gpu_01.matchgate(0, theta_matchgate_gpu, phi1_matchgate_gpu, phi2_matchgate_gpu).expect("Matchgate GPU (targets 0 and 1) failed");
let expected_state_matchgate_gpu_01: State = State::new_basis_n(num_test_qubits_matchgate_gpu, 2).unwrap(); assert_eq!(new_state_matchgate_gpu_01, expected_state_matchgate_gpu_01, "Matchgate GPU (targets 0 and 1) failed");
let state_matchgate_gpu_10: State = State::new_basis_n(num_test_qubits_matchgate_gpu, 2).unwrap(); let new_state_matchgate_gpu_10: State = state_matchgate_gpu_10.matchgate(0, theta_matchgate_gpu, phi1_matchgate_gpu, phi2_matchgate_gpu).expect("Matchgate GPU (targets 0 and 1) failed");
let expected_state_matchgate_gpu_10: State = State::new_basis_n(num_test_qubits_matchgate_gpu, 1).unwrap() * Complex::new(0.0, -1.0); assert_eq!(new_state_matchgate_gpu_10, expected_state_matchgate_gpu_10, "Matchgate GPU (targets 0 and 1) failed");
let control_matchgate_gpu = &[num_test_qubits_matchgate_gpu - 1]; let controls_matchgate_gpu = &[num_test_qubits_matchgate_gpu - 1, num_test_qubits_matchgate_gpu - 2]; let num_test_qubits_cmatchgate_gpu = 15;
let theta_cmatchgate_gpu = PI;
let phi1_cmatchgate_gpu = PI / 2.0;
let phi2_cmatchgate_gpu = PI / 3.0;
let state_cmatchgate_gpu_01_c0: State = State::new_basis_n(num_test_qubits_cmatchgate_gpu, 1).unwrap(); let new_state_cmatchgate_gpu_01_c0: State = state_cmatchgate_gpu_01_c0.cmatchgate(0, theta_cmatchgate_gpu, phi1_cmatchgate_gpu, phi2_cmatchgate_gpu, control_matchgate_gpu).expect("Controlled Matchgate GPU (targets 0 and 1, control 0) failed");
assert_eq!(new_state_cmatchgate_gpu_01_c0, state_cmatchgate_gpu_01_c0, "Controlled Matchgate GPU (targets 0 and 1, control 0) failed");
let state_cmatchgate_gpu_10_c0: State = State::new_basis_n(num_test_qubits_cmatchgate_gpu, 2).unwrap(); let new_state_cmatchgate_gpu_10_c0: State = state_cmatchgate_gpu_10_c0.cmatchgate(0, theta_cmatchgate_gpu, phi1_cmatchgate_gpu, phi2_cmatchgate_gpu, control_matchgate_gpu).expect("Controlled Matchgate GPU (targets 0 and 1, control 0) failed");
assert_eq!(new_state_cmatchgate_gpu_10_c0, state_cmatchgate_gpu_10_c0);
let state_cmatchgate_gpu_01_c1: State = State::new_basis_n(num_test_qubits_cmatchgate_gpu, 16384 + 1).unwrap(); let new_state_cmatchgate_gpu_01_c1: State = state_cmatchgate_gpu_01_c1.cmatchgate(0, theta_cmatchgate_gpu, phi1_cmatchgate_gpu, phi2_cmatchgate_gpu, control_matchgate_gpu).expect("Controlled Matchgate GPU (targets 0 and 1, control 1) failed");
let expected_state_cmatchgate_gpu_01_c1: State = State::new_basis_n(num_test_qubits_cmatchgate_gpu, 16384 + 2).unwrap(); assert_eq!(new_state_cmatchgate_gpu_01_c1, expected_state_cmatchgate_gpu_01_c1, "Controlled Matchgate GPU (targets 0 and 1, control 1) failed");
let state_cmatchgate_gpu_10_c1: State = State::new_basis_n(num_test_qubits_cmatchgate_gpu, 16384 + 2).unwrap(); let new_state_cmatchgate_gpu_10_c1: State = state_cmatchgate_gpu_10_c1.cmatchgate(0, theta_cmatchgate_gpu, phi1_cmatchgate_gpu, phi2_cmatchgate_gpu, control_matchgate_gpu).expect("Controlled Matchgate GPU (targets 0 and 1, control 1) failed");
let expected_state_cmatchgate_gpu_10_c1: State = State::new_basis_n(num_test_qubits_cmatchgate_gpu, 16384 + 1).unwrap() * Complex::new(0.0, -1.0); assert_eq!(new_state_cmatchgate_gpu_10_c1, expected_state_cmatchgate_gpu_10_c1, "Controlled Matchgate GPU (targets 0 and 1, control 1) failed");
let state_cmatchgate_gpu_01_c01: State = State::new_basis_n(num_test_qubits_cmatchgate_gpu, 16384 + 1).unwrap(); let new_state_cmatchgate_gpu_01_c01: State = state_cmatchgate_gpu_01_c01.cmatchgate(0, theta_cmatchgate_gpu, phi1_cmatchgate_gpu, phi2_cmatchgate_gpu, controls_matchgate_gpu).expect("Controlled Matchgate GPU (targets 0 and 1, controls 0 and 1) failed");
assert_eq!(new_state_cmatchgate_gpu_01_c01, state_cmatchgate_gpu_01_c01, "Controlled Matchgate GPU (targets 0 and 1, controls 0 and 1) failed");
let state_cmatchgate_gpu_10_c11: State = State::new_basis_n(num_test_qubits_cmatchgate_gpu, 16384 + 8192 + 2).unwrap(); let new_state_cmatchgate_gpu_10_c11: State = state_cmatchgate_gpu_10_c11.cmatchgate(0, theta_cmatchgate_gpu, phi1_cmatchgate_gpu, phi2_cmatchgate_gpu, controls_matchgate_gpu).expect("Controlled Matchgate GPU (targets 0 and 1, controls 1 and 1) failed");
let expected_state_cmatchgate_gpu_10_c11: State = State::new_basis_n(num_test_qubits_cmatchgate_gpu, 16384 + 8192 + 1).unwrap() * Complex::new(0.0, -1.0); assert_eq!(new_state_cmatchgate_gpu_10_c11, expected_state_cmatchgate_gpu_10_c11, "Controlled Matchgate GPU (targets 0 and 1, controls 1 and 1) failed");
}
}
#[test]
fn test_operator_toffoli_success() {
let state: State = State::new_zero(3).unwrap();
let new_state: State = state.toffoli(0, 1, 2).unwrap();
let expected_state: State = State::new_zero(3).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(3, 1).unwrap();
let new_state: State = state.toffoli(0, 1, 2).unwrap();
let expected_state: State = State::new_basis_n(3, 1).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(3, 2).unwrap();
let new_state: State = state.toffoli(0, 1, 2).unwrap();
let expected_state: State = State::new_basis_n(3, 2).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(3, 3).unwrap();
let new_state: State = state.toffoli(0, 1, 2).unwrap();
let expected_state: State = State::new_basis_n(3, 7).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(3, 4).unwrap();
let new_state: State = state.toffoli(0, 1, 2).unwrap();
let expected_state: State = State::new_basis_n(3, 4).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(3, 5).unwrap();
let new_state: State = state.toffoli(0, 1, 2).unwrap();
let expected_state: State = State::new_basis_n(3, 5).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(3, 6).unwrap();
let new_state: State = state.toffoli(0, 1, 2).unwrap();
let expected_state: State = State::new_basis_n(3, 6).unwrap();
assert_eq!(new_state, expected_state);
let state: State = State::new_basis_n(3, 7).unwrap();
let new_state: State = state.toffoli(0, 1, 2).unwrap();
let expected_state: State = State::new_basis_n(3, 3).unwrap();
assert_eq!(new_state, expected_state);
assert_eq!(Toffoli.base_qubits(), 3);
let num_test_qubits_toffoli_par = 11;
let c1_toffoli_par = num_test_qubits_toffoli_par - 1; let c2_toffoli_par = num_test_qubits_toffoli_par - 2; let t_toffoli_par = 0;
let initial_state_toffoli_par_c00 = State::new_zero(num_test_qubits_toffoli_par).unwrap();
let new_state_toffoli_par_c00 = initial_state_toffoli_par_c00.toffoli(c1_toffoli_par, c2_toffoli_par, t_toffoli_par).unwrap();
assert_eq!(new_state_toffoli_par_c00, initial_state_toffoli_par_c00, "Toffoli parallel (controls 00) failed");
let mut initial_vec_toffoli_par_c11 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_toffoli_par];
let idx_toffoli_par_c11_t0 = (1 << c1_toffoli_par) | (1 << c2_toffoli_par); initial_vec_toffoli_par_c11[idx_toffoli_par_c11_t0] = Complex::new(1.0, 0.0);
let initial_state_toffoli_par_c11 = State { state_vector: initial_vec_toffoli_par_c11, num_qubits: num_test_qubits_toffoli_par };
let new_state_toffoli_par_c11 = initial_state_toffoli_par_c11.toffoli(c1_toffoli_par, c2_toffoli_par, t_toffoli_par).unwrap();
let mut expected_vec_toffoli_par_c11 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_toffoli_par];
expected_vec_toffoli_par_c11[idx_toffoli_par_c11_t0 | (1 << t_toffoli_par)] = Complex::new(1.0, 0.0); let expected_state_toffoli_par_c11 = State { state_vector: expected_vec_toffoli_par_c11, num_qubits: num_test_qubits_toffoli_par };
assert_eq!(new_state_toffoli_par_c11, expected_state_toffoli_par_c11, "Toffoli parallel (controls 11) failed");
let num_test_qubits_cccx_par = 11;
let cccx_controls_par = &[num_test_qubits_cccx_par - 1, num_test_qubits_cccx_par - 2, num_test_qubits_cccx_par - 3]; let cccx_target_par = &[0];
let mut initial_vec_cccx_par_one_c0 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cccx_par];
let idx_cccx_par_one_c0 = (1 << cccx_controls_par[0]) | (1 << cccx_controls_par[1]); initial_vec_cccx_par_one_c0[idx_cccx_par_one_c0] = Complex::new(1.0, 0.0);
let initial_state_cccx_par_one_c0 = State { state_vector: initial_vec_cccx_par_one_c0, num_qubits: num_test_qubits_cccx_par };
let new_state_cccx_par_one_c0 = Pauli::X.apply(&initial_state_cccx_par_one_c0, cccx_target_par, cccx_controls_par).unwrap();
assert_eq!(new_state_cccx_par_one_c0, initial_state_cccx_par_one_c0, "CCCX parallel (one control=0) failed");
let mut initial_vec_cccx_par_all_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cccx_par];
let idx_cccx_par_all_c1_t0 = (1 << cccx_controls_par[0]) | (1 << cccx_controls_par[1]) | (1 << cccx_controls_par[2]); initial_vec_cccx_par_all_c1[idx_cccx_par_all_c1_t0] = Complex::new(1.0, 0.0);
let initial_state_cccx_par_all_c1 = State { state_vector: initial_vec_cccx_par_all_c1, num_qubits: num_test_qubits_cccx_par };
let new_state_cccx_par_all_c1 = Pauli::X.apply(&initial_state_cccx_par_all_c1, cccx_target_par, cccx_controls_par).unwrap();
let mut expected_vec_cccx_par_all_c1 = vec![Complex::new(0.0, 0.0); 1 << num_test_qubits_cccx_par];
expected_vec_cccx_par_all_c1[idx_cccx_par_all_c1_t0 | (1 << cccx_target_par[0])] = Complex::new(1.0, 0.0); let expected_state_cccx_par_all_c1 = State { state_vector: expected_vec_cccx_par_all_c1, num_qubits: num_test_qubits_cccx_par };
assert_eq!(new_state_cccx_par_all_c1, expected_state_cccx_par_all_c1, "CCCX parallel (all controls=1) failed");
}
#[test]
fn test_operate_operate_success() {
let h: Hadamard = Hadamard {};
let state: State = State::new_zero(1).unwrap();
let new_state: State = state.operate(h, &[0], &[]).unwrap();
let expected_state: State = State::new_plus(1).unwrap();
assert_eq!(new_state, expected_state);
let cnot: CNOT = CNOT {};
let state: State = State::new_basis_n(2, 1).unwrap();
let new_state: State = state.operate(cnot, &[1], &[0]).unwrap();
let expected_state: State = State::new_basis_n(2, 3).unwrap();
assert_eq!(new_state, expected_state);
}
macro_rules! generate_single_qubit_gate_error_assertions {
($state:ident, $gate_method:ident) => {
paste::paste! { let result_single = $state.$gate_method(2); assert!(matches!(result_single, Err(Error::InvalidQubitIndex(2, 2))),
"Gate '{}' single failed: Expected InvalidQubitIndex(2, 2), got {:?}", stringify!($gate_method), result_single);
let result_multi = $state.[<$gate_method _multi>](&[0, 2]); assert!(matches!(result_multi, Err(Error::InvalidQubitIndex(2, 2))),
"Gate '{}' multi failed: Expected InvalidQubitIndex(2, 2), got {:?}", stringify!($gate_method), result_multi);
}
};
($state:ident, $gate_method:ident, $angle:expr) => {
paste::paste! { let result_single = $state.$gate_method(2, $angle); assert!(matches!(result_single, Err(Error::InvalidQubitIndex(2, 2))),
"Gate '{}' single failed: Expected InvalidQubitIndex(2, 2), got {:?}", stringify!($gate_method), result_single);
let result_multi = $state.[<$gate_method _multi>](&[0, 2], $angle); assert!(matches!(result_multi, Err(Error::InvalidQubitIndex(2, 2))),
"Gate '{}' multi failed: Expected InvalidQubitIndex(2, 2), got {:?}", stringify!($gate_method), result_multi);
}
};
}
#[test]
fn test_single_qubit_gate_errors() {
let state = State::new_zero(2).unwrap();
let angle = PI / 4.0;
generate_single_qubit_gate_error_assertions!(state, h);
generate_single_qubit_gate_error_assertions!(state, x);
generate_single_qubit_gate_error_assertions!(state, y);
generate_single_qubit_gate_error_assertions!(state, z);
generate_single_qubit_gate_error_assertions!(state, s);
generate_single_qubit_gate_error_assertions!(state, t);
generate_single_qubit_gate_error_assertions!(state, s_dag);
generate_single_qubit_gate_error_assertions!(state, t_dag);
generate_single_qubit_gate_error_assertions!(state, i);
generate_single_qubit_gate_error_assertions!(state, p, angle);
generate_single_qubit_gate_error_assertions!(state, rx, angle);
generate_single_qubit_gate_error_assertions!(state, ry, angle);
generate_single_qubit_gate_error_assertions!(state, rz, angle);
}
#[test]
fn test_multi_qubit_gate_errors() {
let num_qubits = 3;
let invalid_index = 3; let state = State::new_zero(num_qubits).unwrap();
let cnot_invalid_control = state.cnot(invalid_index, 0);
assert!(
matches!(
cnot_invalid_control,
Err(Error::InvalidQubitIndex(_invalid_index, _num_qubits))
),
"CNOT failed (invalid control): Expected InvalidQubitIndex({}, {}), got {:?}",
invalid_index,
num_qubits,
cnot_invalid_control
);
let cnot_invalid_target = state.cnot(0, invalid_index);
assert!(
matches!(
cnot_invalid_target,
Err(Error::InvalidQubitIndex(_invalid_index, _num_qubits))
),
"CNOT failed (invalid target): Expected InvalidQubitIndex({}, {}), got {:?}",
invalid_index,
num_qubits,
cnot_invalid_target
);
let swap_invalid_q1 = state.swap(invalid_index, 1);
assert!(
matches!(
swap_invalid_q1,
Err(Error::InvalidQubitIndex(_invalid_index, _num_qubits))
),
"SWAP failed (invalid qubit1): Expected InvalidQubitIndex({}, {}), got {:?}",
invalid_index,
num_qubits,
swap_invalid_q1
);
let swap_invalid_q2 = state.swap(0, invalid_index);
assert!(
matches!(
swap_invalid_q2,
Err(Error::InvalidQubitIndex(_invalid_index, _num_qubits))
),
"SWAP failed (invalid qubit2): Expected InvalidQubitIndex({}, {}), got {:?}",
invalid_index,
num_qubits,
swap_invalid_q2
);
let toffoli_invalid_c1 = state.toffoli(invalid_index, 1, 2);
assert!(
matches!(
toffoli_invalid_c1,
Err(Error::InvalidQubitIndex(_invalid_index, _num_qubits))
),
"Toffoli failed (invalid control1): Expected InvalidQubitIndex({}, {}), got {:?}",
invalid_index,
num_qubits,
toffoli_invalid_c1
);
let toffoli_invalid_c2 = state.toffoli(0, invalid_index, 2);
assert!(
matches!(
toffoli_invalid_c2,
Err(Error::InvalidQubitIndex(_invalid_index, _num_qubits))
),
"Toffoli failed (invalid control2): Expected InvalidQubitIndex({}, {}), got {:?}",
invalid_index,
num_qubits,
toffoli_invalid_c2
);
let toffoli_invalid_target = state.toffoli(0, 1, invalid_index);
assert!(
matches!(
toffoli_invalid_target,
Err(Error::InvalidQubitIndex(_invalid_index, _num_qubits))
),
"Toffoli failed (invalid target): Expected InvalidQubitIndex({}, {}), got {:?}",
invalid_index,
num_qubits,
toffoli_invalid_target
);
let num_qubits = state.num_qubits();
let invalid_index = num_qubits;
let last_index = num_qubits - 1;
let matchgate_invalid_q1 = state.matchgate(invalid_index, PI, 0.0, 0.0);
assert!(
matches!(
matchgate_invalid_q1,
Err(Error::InvalidQubitIndex(idx, nq)) if idx == invalid_index && nq == num_qubits
),
"Matchgate failed (invalid q1): Expected InvalidQubitIndex({}, {}), got {:?}",
invalid_index, num_qubits, matchgate_invalid_q1
);
let matchgate_invalid_q1_last = state.matchgate(last_index, PI, 0.0, 0.0);
assert!(
matches!(
matchgate_invalid_q1_last,
Err(Error::InvalidQubitIndex(idx, nq)) if idx == last_index && nq == num_qubits
),
"Matchgate failed (invalid q1 last): Expected InvalidQubitIndex({}, {}), got {:?}",
last_index, num_qubits, matchgate_invalid_q1_last
);
let matchgate_overlapping_control = state.cmatchgate(
0, PI, 0.0, 0.0, &[0]
);
assert!(
matches!(
matchgate_overlapping_control,
Err(Error::OverlappingControlAndTargetQubits(c, t)) if c == 0 && t == 0
),
"Matchgate failed (overlapping control): Expected OverlappingControlAndTargetQubits(0, 0), got {:?}",
matchgate_overlapping_control
);
}