use super::gates::{
TQHadamard, TQPauliX, TQPauliY, TQPauliZ, TQRx, TQRy, TQRz, TQCNOT, TQCRX, TQCRY, TQCRZ, TQCZ,
TQRXX, TQRYY, TQRZX, TQRZZ, TQS, TQSWAP, TQSX, TQT, TQU1, TQU2, TQU3,
};
use super::{TQDevice, TQOperator};
use crate::error::{MLError, Result};
use std::f64::consts::PI;
pub fn hadamard(qdev: &mut TQDevice, wire: usize) -> Result<()> {
let mut gate = TQHadamard::new();
gate.apply(qdev, &[wire])
}
pub fn paulix(qdev: &mut TQDevice, wire: usize) -> Result<()> {
let mut gate = TQPauliX::new();
gate.apply(qdev, &[wire])
}
pub fn pauliy(qdev: &mut TQDevice, wire: usize) -> Result<()> {
let mut gate = TQPauliY::new();
gate.apply(qdev, &[wire])
}
pub fn pauliz(qdev: &mut TQDevice, wire: usize) -> Result<()> {
let mut gate = TQPauliZ::new();
gate.apply(qdev, &[wire])
}
pub fn s(qdev: &mut TQDevice, wire: usize) -> Result<()> {
let mut gate = TQS::new();
gate.apply(qdev, &[wire])
}
pub fn t(qdev: &mut TQDevice, wire: usize) -> Result<()> {
let mut gate = TQT::new();
gate.apply(qdev, &[wire])
}
pub fn sx(qdev: &mut TQDevice, wire: usize) -> Result<()> {
let mut gate = TQSX::new();
gate.apply(qdev, &[wire])
}
pub fn rx(qdev: &mut TQDevice, wire: usize, theta: f64) -> Result<()> {
let mut gate = TQRx::new(true, false);
gate.apply_with_params(qdev, &[wire], Some(&[theta]))
}
pub fn ry(qdev: &mut TQDevice, wire: usize, theta: f64) -> Result<()> {
let mut gate = TQRy::new(true, false);
gate.apply_with_params(qdev, &[wire], Some(&[theta]))
}
pub fn rz(qdev: &mut TQDevice, wire: usize, theta: f64) -> Result<()> {
let mut gate = TQRz::new(true, false);
gate.apply_with_params(qdev, &[wire], Some(&[theta]))
}
pub fn u1(qdev: &mut TQDevice, wire: usize, lambda: f64) -> Result<()> {
let mut gate = TQU1::new(true, false);
gate.apply_with_params(qdev, &[wire], Some(&[lambda]))
}
pub fn u2(qdev: &mut TQDevice, wire: usize, phi: f64, lambda: f64) -> Result<()> {
let mut gate = TQU2::new(true, false);
gate.apply_with_params(qdev, &[wire], Some(&[phi, lambda]))
}
pub fn u3(qdev: &mut TQDevice, wire: usize, theta: f64, phi: f64, lambda: f64) -> Result<()> {
let mut gate = TQU3::new(true, false);
gate.apply_with_params(qdev, &[wire], Some(&[theta, phi, lambda]))
}
pub fn cnot(qdev: &mut TQDevice, control: usize, target: usize) -> Result<()> {
let mut gate = TQCNOT::new();
gate.apply(qdev, &[control, target])
}
pub fn cz(qdev: &mut TQDevice, wire0: usize, wire1: usize) -> Result<()> {
let mut gate = TQCZ::new();
gate.apply(qdev, &[wire0, wire1])
}
pub fn swap(qdev: &mut TQDevice, wire0: usize, wire1: usize) -> Result<()> {
let mut gate = TQSWAP::new();
gate.apply(qdev, &[wire0, wire1])
}
pub fn rxx(qdev: &mut TQDevice, wire0: usize, wire1: usize, theta: f64) -> Result<()> {
let mut gate = TQRXX::new(true, false);
gate.apply_with_params(qdev, &[wire0, wire1], Some(&[theta]))
}
pub fn ryy(qdev: &mut TQDevice, wire0: usize, wire1: usize, theta: f64) -> Result<()> {
let mut gate = TQRYY::new(true, false);
gate.apply_with_params(qdev, &[wire0, wire1], Some(&[theta]))
}
pub fn rzz(qdev: &mut TQDevice, wire0: usize, wire1: usize, theta: f64) -> Result<()> {
let mut gate = TQRZZ::new(true, false);
gate.apply_with_params(qdev, &[wire0, wire1], Some(&[theta]))
}
pub fn rzx(qdev: &mut TQDevice, wire0: usize, wire1: usize, theta: f64) -> Result<()> {
let mut gate = TQRZX::new(true, false);
gate.apply_with_params(qdev, &[wire0, wire1], Some(&[theta]))
}
pub fn crx(qdev: &mut TQDevice, control: usize, target: usize, theta: f64) -> Result<()> {
let mut gate = TQCRX::new(true, false);
gate.apply_with_params(qdev, &[control, target], Some(&[theta]))
}
pub fn cry(qdev: &mut TQDevice, control: usize, target: usize, theta: f64) -> Result<()> {
let mut gate = TQCRY::new(true, false);
gate.apply_with_params(qdev, &[control, target], Some(&[theta]))
}
pub fn crz(qdev: &mut TQDevice, control: usize, target: usize, theta: f64) -> Result<()> {
let mut gate = TQCRZ::new(true, false);
gate.apply_with_params(qdev, &[control, target], Some(&[theta]))
}
pub fn rot(qdev: &mut TQDevice, wire: usize, phi: f64, theta: f64, omega: f64) -> Result<()> {
rx(qdev, wire, phi)?;
ry(qdev, wire, theta)?;
rz(qdev, wire, omega)?;
Ok(())
}
pub fn bell_state(qdev: &mut TQDevice, wire0: usize, wire1: usize) -> Result<()> {
hadamard(qdev, wire0)?;
cnot(qdev, wire0, wire1)?;
Ok(())
}
pub fn ghz_state(qdev: &mut TQDevice, wires: &[usize]) -> Result<()> {
if wires.is_empty() {
return Err(MLError::InvalidConfiguration(
"GHZ state requires at least one wire".to_string(),
));
}
hadamard(qdev, wires[0])?;
for i in 1..wires.len() {
cnot(qdev, wires[i - 1], wires[i])?;
}
Ok(())
}
pub fn barrier(_qdev: &mut TQDevice, _wires: &[usize]) -> Result<()> {
Ok(())
}
pub fn reset(qdev: &mut TQDevice, wire: usize) -> Result<()> {
qdev.reset_states(qdev.bsz);
let _ = wire;
Ok(())
}
pub fn qft(qdev: &mut TQDevice, wires: &[usize]) -> Result<()> {
let n = wires.len();
for i in 0..n {
hadamard(qdev, wires[i])?;
for j in (i + 1)..n {
let k = j - i;
let theta = PI / (1 << k) as f64;
crz(qdev, wires[j], wires[i], theta)?;
}
}
for i in 0..(n / 2) {
swap(qdev, wires[i], wires[n - 1 - i])?;
}
Ok(())
}
pub fn iqft(qdev: &mut TQDevice, wires: &[usize]) -> Result<()> {
let n = wires.len();
for i in 0..(n / 2) {
swap(qdev, wires[i], wires[n - 1 - i])?;
}
for i in (0..n).rev() {
for j in ((i + 1)..n).rev() {
let k = j - i;
let theta = -PI / (1 << k) as f64;
crz(qdev, wires[j], wires[i], theta)?;
}
hadamard(qdev, wires[i])?;
}
Ok(())
}