use crate::gate::Axis;
use crate::{Error, Result, Unitary};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Angle {
Constant(f64),
Parameter {
index: usize,
scale: f64,
offset: f64,
},
Input {
index: usize,
scale: f64,
offset: f64,
},
}
impl Angle {
pub fn parameter(index: usize) -> Self {
Self::Parameter {
index,
scale: 1.,
offset: 0.,
}
}
pub fn input(index: usize) -> Self {
Self::Input {
index,
scale: 1.,
offset: 0.,
}
}
pub(super) fn validate(&self, parameters: usize, inputs: usize) -> Result<()> {
let valid = match self {
Self::Constant(x) => x.is_finite(),
Self::Parameter {
index,
scale,
offset,
} => *index < parameters && scale.is_finite() && offset.is_finite(),
Self::Input {
index,
scale,
offset,
} => *index < inputs && scale.is_finite() && offset.is_finite(),
};
if valid {
Ok(())
} else {
Err(Error::InvalidValue(
"invalid angle expression or binding index".into(),
))
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Rotation {
pub axis: Axis,
pub levels: [usize; 2],
pub angle: Angle,
}
impl Rotation {
pub fn qubit(axis: Axis, angle: Angle) -> Self {
Self {
axis,
levels: [0, 1],
angle,
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Operation {
Unitary {
wires: Vec<usize>,
gate: Unitary,
},
Rotate {
wire: usize,
rotation: Rotation,
},
ControlledX {
controls: Vec<(usize, usize)>,
target: usize,
},
PhaseFlip {
controls: Vec<(usize, usize)>,
},
}