use num_complex::Complex64;
use std::f64::consts::{FRAC_PI_2, PI};
use super::Qubit;
use std::collections::{HashMap, BTreeMap};
pub struct QuantumGate;
impl QuantumGate {
pub fn hadamard(qubit: &mut Qubit) {
let (alpha, beta) = qubit.amplitudes();
let s: _ = 1.0 / 2.0_f64.sqrt();
let new_alpha: _ = s * (alpha + beta);
let new_beta: _ = s * (alpha - beta);
qubit.set_amplitudes(new_alpha, new_beta);
}
pub fn pauli_x(qubit: &mut Qubit) {
let (alpha, beta) = qubit.amplitudes();
qubit.set_amplitudes(beta, alpha);
}
pub fn pauli_y(qubit: &mut Qubit) {
let (alpha, beta) = qubit.amplitudes();
let i: _ = Complex64::new(0.0, 1.0);
let new_alpha: _ = -i * beta;
let new_beta: _ = i * alpha;
qubit.set_amplitudes(new_alpha, new_beta);
}
pub fn pauli_z(qubit: &mut Qubit) {
let (alpha, beta) = qubit.amplitudes();
qubit.set_amplitudes(alpha, -beta);
}
pub fn phase(qubit: &mut Qubit, theta: f64) {
let (alpha, beta) = qubit.amplitudes();
let phase_factor: _ = Complex64::from_polar(1.0, theta);
qubit.set_amplitudes(alpha, beta * phase_factor);
}
pub fn s_gate(qubit: &mut Qubit) {
Self::phase(qubit, FRAC_PI_2);
}
pub fn t_gate(qubit: &mut Qubit) {
Self::phase(qubit, PI / 4.0);
}
pub fn rotation_x(qubit: &mut Qubit, theta: f64) {
let (alpha, beta) = qubit.amplitudes();
let c: _ = Complex64::new((theta / 2.0).cos(), 0.0);
let s: _ = Complex64::new(0.0, -(theta / 2.0).sin());
let new_alpha: _ = c * alpha + s * beta;
let new_beta: _ = s * alpha + c * beta;
qubit.set_amplitudes(new_alpha, new_beta);
}
pub fn rotation_y(qubit: &mut Qubit, theta: f64) {
let (alpha, beta) = qubit.amplitudes();
let c: _ = (theta / 2.0).cos();
let s: _ = (theta / 2.0).sin();
let new_alpha: _ = Complex64::new(c, 0.0) * alpha - Complex64::new(s, 0.0) * beta;
let new_beta: _ = Complex64::new(s, 0.0) * alpha + Complex64::new(c, 0.0) * beta;
qubit.set_amplitudes(new_alpha, new_beta);
}
pub fn rotation_z(qubit: &mut Qubit, theta: f64) {
let (alpha, beta) = qubit.amplitudes();
let phase_neg: _ = Complex64::from_polar(1.0, -theta / 2.0);
let phase_pos: _ = Complex64::from_polar(1.0, theta / 2.0);
qubit.set_amplitudes(alpha * phase_neg, beta * phase_pos);
}
pub fn hadamard_matrix() -> [[Complex64; 2]; 2] {
let s: _ = Complex64::new(1.0 / 2.0_f64.sqrt(), 0.0);
[[s, s], [s, -s]]
}
pub fn cnot_matrix() -> [[Complex64; 4]; 4] {
let zero: _ = Complex64::new(0.0, 0.0);
let one: _ = Complex64::new(1.0, 0.0);
[
[one, zero, zero, zero], [zero, one, zero, zero], [zero, zero, zero, one], [zero, zero, one, zero], ]
}
pub fn cz_matrix() -> [[Complex64; 4]; 4] {
let zero: _ = Complex64::new(0.0, 0.0);
let one: _ = Complex64::new(1.0, 0.0);
let neg_one: _ = Complex64::new(-1.0, 0.0);
[
[one, zero, zero, zero],
[zero, one, zero, zero],
[zero, zero, one, zero],
[zero, zero, zero, neg_one],
]
}
pub fn swap_matrix() -> [[Complex64; 4]; 4] {
let zero: _ = Complex64::new(0.0, 0.0);
let one: _ = Complex64::new(1.0, 0.0);
[
[one, zero, zero, zero],
[zero, zero, one, zero],
[zero, one, zero, zero],
[zero, zero, zero, one],
]
}
}
#[derive(Debug, Clone)]
pub enum GateType {
Hadamard(usize),
PauliX(usize),
PauliY(usize),
PauliZ(usize),
Phase(usize, f64),
RotationX(usize, f64),
RotationY(usize, f64),
RotationZ(usize, f64),
SGate(usize),
TGate(usize),
CNOT(usize, usize), CZ(usize, usize),
SWAP(usize, usize),
Measure(usize),
Barrier,
}
impl GateType {
pub fn qubits(&self) -> Vec<usize> {
match self {
GateType::Hadamard(q) | GateType::PauliX(q) | GateType::PauliY(q) |
GateType::PauliZ(q) | GateType::Phase(q, _) |
GateType::RotationX(q, _) | GateType::RotationY(q, _) |
GateType::RotationZ(q, _) | GateType::SGate(q) | GateType::TGate(q) |
GateType::Measure(q) => vec![*q],
GateType::CNOT(c, t) | GateType::CZ(c, t) | GateType::SWAP(c, t) => vec![*c, *t],
GateType::Barrier => vec![],
}
}
pub fn can_parallel_with(&self, other: &GateType) -> bool {
let self_qubits: _ = self.qubits();
let other_qubits: _ = other.qubits();
for q in &self_qubits {
if other_qubits.contains(q) {
return false;
}
}
true
}
}