use crate::gates::Gate;
use crate::stabilizer::PauliOp;
pub struct V
{
}
impl V
{
pub fn new() -> Self
{
V { }
}
}
impl crate::gates::Gate for V
{
fn cost(&self) -> f64
{
crate::gates::U3::cost()
}
fn description(&self) -> &str
{
"V"
}
fn nr_affected_bits(&self) -> usize
{
1
}
fn matrix(&self) -> crate::cmatrix::CMatrix
{
let h = 0.5 * crate::cmatrix::COMPLEX_ONE;
let hi = 0.5 * crate::cmatrix::COMPLEX_I;
array![[h+hi, h-hi], [h-hi, h+hi]]
}
fn is_stabilizer(&self) -> bool
{
true
}
fn conjugate(&self, ops: &mut [PauliOp]) -> crate::error::Result<bool>
{
self.check_nr_bits(ops.len())?;
let (op, phase) = match ops[0]
{
PauliOp::I => (PauliOp::I, false),
PauliOp::Z => (PauliOp::Y, true),
PauliOp::X => (PauliOp::X, false),
PauliOp::Y => (PauliOp::Z, false)
};
ops[0] = op;
Ok(phase)
}
}
impl crate::export::OpenQasm for V
{
fn open_qasm(&self, bit_names: &[String], bits: &[usize])
-> crate::error::Result<String>
{
Ok(format!("u3(pi/2, -pi/2, pi/2) {}", bit_names[bits[0]]))
}
}
impl crate::export::CQasm for V
{
fn c_qasm(&self, bit_names: &[String], bits: &[usize])
-> crate::error::Result<String>
{
Ok(format!("x90 {}", bit_names[bits[0]]))
}
}
impl crate::export::Latex for V
{
fn latex(&self, bits: &[usize], state: &mut crate::export::LatexExportState)
-> crate::error::Result<()>
{
self.check_nr_bits(bits.len())?;
state.add_block_gate(bits, "V")
}
}
pub struct Vdg
{
}
impl Vdg
{
pub fn new() -> Self
{
Vdg { }
}
}
impl crate::gates::Gate for Vdg
{
fn cost(&self) -> f64
{
crate::gates::U3::cost()
}
fn description(&self) -> &str
{
"V†"
}
fn nr_affected_bits(&self) -> usize
{
1
}
fn matrix(&self) -> crate::cmatrix::CMatrix
{
let h = 0.5 * crate::cmatrix::COMPLEX_ONE;
let hi = 0.5 * crate::cmatrix::COMPLEX_I;
array![[h-hi, h+hi], [h+hi, h-hi]]
}
fn is_stabilizer(&self) -> bool
{
true
}
fn conjugate(&self, ops: &mut [PauliOp]) -> crate::error::Result<bool>
{
self.check_nr_bits(ops.len())?;
let (op, phase) = match ops[0]
{
PauliOp::I => (PauliOp::I, false),
PauliOp::Z => (PauliOp::Y, false),
PauliOp::X => (PauliOp::X, false),
PauliOp::Y => (PauliOp::Z, true)
};
ops[0] = op;
Ok(phase)
}
}
impl crate::export::OpenQasm for Vdg
{
fn open_qasm(&self, bit_names: &[String], bits: &[usize])
-> crate::error::Result<String>
{
Ok(format!("u3(pi/2, pi/2, -pi/2) {}", bit_names[bits[0]]))
}
}
impl crate::export::CQasm for Vdg
{
fn c_qasm(&self, bit_names: &[String], bits: &[usize])
-> crate::error::Result<String>
{
Ok(format!("mx90 {}", bit_names[bits[0]]))
}
}
impl crate::export::Latex for Vdg
{
fn latex(&self, bits: &[usize], state: &mut crate::export::LatexExportState)
-> crate::error::Result<()>
{
self.check_nr_bits(bits.len())?;
state.add_block_gate(bits, r"V^\dagger")
}
}
#[cfg(test)]
mod tests
{
use super::{V, Vdg};
use crate::export::{Latex, LatexExportState, OpenQasm, CQasm};
use crate::gates::{gate_test, Gate};
use crate::stabilizer::PauliOp;
#[test]
fn test_description()
{
let gate = V::new();
assert_eq!(gate.description(), "V");
let gate = Vdg::new();
assert_eq!(gate.description(), "V†");
}
#[test]
fn test_cost()
{
let gate = V::new();
assert_eq!(gate.cost(), 201.0);
let gate = Vdg::new();
assert_eq!(gate.cost(), 201.0);
}
#[test]
fn test_matrix()
{
let h = 0.5*crate::cmatrix::COMPLEX_ONE;
let hi = 0.5*crate::cmatrix::COMPLEX_I;
let gate = V::new();
assert_complex_matrix_eq!(gate.matrix(), array![[h+hi, h-hi], [h-hi, h+hi]]);
let gate = Vdg::new();
assert_complex_matrix_eq!(gate.matrix(), array![[h-hi, h+hi], [h+hi, h-hi]]);
}
#[test]
fn test_apply()
{
let z = crate::cmatrix::COMPLEX_ZERO;
let o = crate::cmatrix::COMPLEX_ONE;
let i = crate::cmatrix::COMPLEX_I;
let x = crate::cmatrix::COMPLEX_HSQRT2;
let h = 0.5 * o;
let hi = 0.5 * i;
let mut state = array![
[o, z, x, x],
[z, o, x, -x]
];
let result = array![
[h+hi, h-hi, x, x*i],
[h-hi, h+hi, x, -x*i]
];
gate_test(V::new(), &mut state, &result);
let mut state = array![
[o, z, x, x],
[z, o, x, -x]
];
let result = array![
[h-hi, h+hi, x, -x*i],
[h+hi, h-hi, x, x*i]
];
gate_test(Vdg::new(), &mut state, &result);
}
#[test]
fn test_open_qasm()
{
let bit_names = [String::from("qb")];
let qasm = V::new().open_qasm(&bit_names, &[0]);
assert_eq!(qasm, Ok(String::from("u3(pi/2, -pi/2, pi/2) qb")));
let qasm = Vdg::new().open_qasm(&bit_names, &[0]);
assert_eq!(qasm, Ok(String::from("u3(pi/2, pi/2, -pi/2) qb")));
}
#[test]
fn test_c_qasm()
{
let bit_names = [String::from("qb")];
let qasm = V::new().c_qasm(&bit_names, &[0]);
assert_eq!(qasm, Ok(String::from("x90 qb")));
let qasm = Vdg::new().c_qasm(&bit_names, &[0]);
assert_eq!(qasm, Ok(String::from("mx90 qb")));
}
#[test]
fn test_latex()
{
let gate = V::new();
let mut state = LatexExportState::new(1, 0);
assert_eq!(gate.latex(&[0], &mut state), Ok(()));
assert_eq!(state.code(),
r#"\Qcircuit @C=1em @R=.7em {
\lstick{\ket{0}} & \gate{V} & \qw \\
}
"#);
let gate = Vdg::new();
let mut state = LatexExportState::new(1, 0);
assert_eq!(gate.latex(&[0], &mut state), Ok(()));
assert_eq!(state.code(),
r#"\Qcircuit @C=1em @R=.7em {
\lstick{\ket{0}} & \gate{V^\dagger} & \qw \\
}
"#);
}
#[test]
fn test_conjugate()
{
let mut op = [PauliOp::I];
assert_eq!(V::new().conjugate(&mut op), Ok(false));
assert_eq!(op, [PauliOp::I]);
let mut op = [PauliOp::Z];
assert_eq!(V::new().conjugate(&mut op), Ok(true));
assert_eq!(op, [PauliOp::Y]);
let mut op = [PauliOp::X];
assert_eq!(V::new().conjugate(&mut op), Ok(false));
assert_eq!(op, [PauliOp::X]);
let mut op = [PauliOp::Y];
assert_eq!(V::new().conjugate(&mut op), Ok(false));
assert_eq!(op, [PauliOp::Z]);
let mut op = [PauliOp::I];
assert_eq!(Vdg::new().conjugate(&mut op), Ok(false));
assert_eq!(op, [PauliOp::I]);
let mut op = [PauliOp::Z];
assert_eq!(Vdg::new().conjugate(&mut op), Ok(false));
assert_eq!(op, [PauliOp::Y]);
let mut op = [PauliOp::X];
assert_eq!(Vdg::new().conjugate(&mut op), Ok(false));
assert_eq!(op, [PauliOp::X]);
let mut op = [PauliOp::Y];
assert_eq!(Vdg::new().conjugate(&mut op), Ok(true));
assert_eq!(op, [PauliOp::Z]);
}
}