use crate::errors::CircuitError;
use crate::{Register, UnitaryBuilder};
use num::Complex;
use std::ops::Not;
pub fn chain<B: UnitaryBuilder>(b: &mut B, r: Register) -> SingleRegisterChain<B> {
SingleRegisterChain::new(b, r)
}
pub fn chain_tuple<B: UnitaryBuilder>(
b: &mut B,
ra: Register,
rb: Register,
) -> DoubleRegisterChain<B> {
DoubleRegisterChain::new(b, ra, rb)
}
pub fn chain_vec<B: UnitaryBuilder>(b: &mut B, rs: Vec<Register>) -> VecRegisterChain<B> {
VecRegisterChain::new(b, rs)
}
#[derive(Debug)]
pub struct SingleRegisterChain<'a, B: UnitaryBuilder> {
builder: &'a mut B,
r: Register,
}
#[derive(Debug)]
pub struct DoubleRegisterChain<'a, B: UnitaryBuilder> {
builder: &'a mut B,
ra: Register,
rb: Register,
}
#[derive(Debug)]
pub struct VecRegisterChain<'a, B: UnitaryBuilder> {
builder: &'a mut B,
rs: Vec<Register>,
}
impl<'a, B: UnitaryBuilder> SingleRegisterChain<'a, B> {
pub fn new(builder: &'a mut B, r: Register) -> Self {
SingleRegisterChain::<'a, B> { builder, r }
}
pub fn release(self) -> Register {
self.r()
}
pub fn r(self) -> Register {
self.r
}
pub fn split(self, indices: &[u64]) -> Result<DoubleRegisterChain<'a, B>, CircuitError> {
let (ra, rb) = self.builder.split(self.r, indices)?;
Ok(DoubleRegisterChain::new(self.builder, ra, rb))
}
pub fn split_absolute(
self,
selected_indices: &[u64],
) -> Result<DoubleRegisterChain<'a, B>, CircuitError> {
let (ra, rb) = self.builder.split_absolute(self.r, selected_indices)?;
Ok(DoubleRegisterChain::new(self.builder, ra, rb))
}
pub fn split_all(self) -> Result<VecRegisterChain<'a, B>, CircuitError> {
let rs = self.builder.split_all(self.r);
Ok(VecRegisterChain::new(self.builder, rs))
}
pub fn apply_mat(self, name: &str, mat: Vec<Complex<f64>>) -> Result<Self, CircuitError> {
let r = self.builder.mat(name, self.r, mat)?;
Ok(Self::new(self.builder, r))
}
pub fn apply_sparse_mat(
self,
name: &str,
mat: Vec<Vec<(u64, Complex<f64>)>>,
natural_order: bool,
) -> Result<Self, CircuitError> {
let r = self.builder.sparse_mat(name, self.r, mat, natural_order)?;
Ok(Self::new(self.builder, r))
}
pub fn x(self) -> Self {
let r = self.builder.x(self.r);
Self::new(self.builder, r)
}
pub fn y(self) -> Self {
let r = self.builder.y(self.r);
Self::new(self.builder, r)
}
pub fn z(self) -> Self {
let r = self.builder.z(self.r);
Self::new(self.builder, r)
}
pub fn hadamard(self) -> Self {
let r = self.builder.hadamard(self.r);
Self::new(self.builder, r)
}
pub fn apply(self, f: impl FnOnce(&mut B, Register) -> Register) -> Self {
let r = f(self.builder, self.r);
Self::new(self.builder, r)
}
pub fn apply_cut(
self,
f: impl FnOnce(&mut B, Register) -> (Register, Register),
) -> DoubleRegisterChain<'a, B> {
let (ra, rb) = f(self.builder, self.r);
DoubleRegisterChain::new(self.builder, ra, rb)
}
pub fn apply_split(
self,
f: impl FnOnce(&mut B, Register) -> Vec<Register>,
) -> VecRegisterChain<'a, B> {
let rs = f(self.builder, self.r);
VecRegisterChain::new(self.builder, rs)
}
}
impl<'a, B: UnitaryBuilder> Not for SingleRegisterChain<'a, B> {
type Output = SingleRegisterChain<'a, B>;
fn not(self) -> Self {
let r = self.builder.not(self.r);
Self::new(self.builder, r)
}
}
impl<'a, B: UnitaryBuilder> DoubleRegisterChain<'a, B> {
pub fn new(builder: &'a mut B, ra: Register, rb: Register) -> Self {
DoubleRegisterChain::<'a, B> { builder, ra, rb }
}
pub fn release(self) -> (Register, Register) {
self.rab()
}
pub fn rab(self) -> (Register, Register) {
(self.ra, self.rb)
}
pub fn merge(self) -> SingleRegisterChain<'a, B> {
let r = self.builder.merge(vec![self.ra, self.rb]).unwrap();
SingleRegisterChain::new(self.builder, r)
}
pub fn split_all(self) -> VecRegisterChain<'a, B> {
let r = self.builder.merge(vec![self.ra, self.rb]).unwrap();
let qs = self.builder.split_all(r);
VecRegisterChain::new(self.builder, qs)
}
pub fn swap(self) -> Result<Self, CircuitError> {
let (ra, rb) = self.builder.swap(self.ra, self.rb)?;
Ok(Self::new(self.builder, ra, rb))
}
pub fn physical_swap(self) -> Self {
Self::new(self.builder, self.rb, self.ra)
}
pub fn apply_function_op(
self,
f: impl Fn(u64) -> (u64, f64) + Send + Sync + 'static,
) -> Result<Self, CircuitError> {
let (ra, rb) = self.builder.apply_function(self.ra, self.rb, Box::new(f))?;
Ok(Self::new(self.builder, ra, rb))
}
pub fn apply_boxed_function_op(
self,
f: Box<dyn Fn(u64) -> (u64, f64) + Send + Sync>,
) -> Result<Self, CircuitError> {
let (ra, rb) = self.builder.apply_function(self.ra, self.rb, f)?;
Ok(Self::new(self.builder, ra, rb))
}
pub fn apply_merge(
self,
f: impl FnOnce(&mut B, Register, Register) -> Register,
) -> SingleRegisterChain<'a, B> {
let r = f(self.builder, self.ra, self.rb);
SingleRegisterChain::new(self.builder, r)
}
pub fn apply(self, f: impl FnOnce(&mut B, Register, Register) -> (Register, Register)) -> Self {
let (ra, rb) = f(self.builder, self.ra, self.rb);
Self::new(self.builder, ra, rb)
}
pub fn apply_split(
self,
f: impl FnOnce(&mut B, Register, Register) -> Vec<Register>,
) -> VecRegisterChain<'a, B> {
let rs = f(self.builder, self.ra, self.rb);
VecRegisterChain::new(self.builder, rs)
}
}
impl<'a, B: UnitaryBuilder> VecRegisterChain<'a, B> {
pub fn new(builder: &'a mut B, rs: Vec<Register>) -> Self {
VecRegisterChain::<'a, B> { builder, rs }
}
pub fn release(self) -> Vec<Register> {
self.rs()
}
pub fn rs(self) -> Vec<Register> {
self.rs
}
pub fn merge(self) -> SingleRegisterChain<'a, B> {
let r = self.builder.merge(self.rs).unwrap();
SingleRegisterChain::new(self.builder, r)
}
pub fn partition_by_relative(
self,
f: impl Fn(u64) -> bool,
) -> Result<DoubleRegisterChain<'a, B>, CircuitError> {
let (a, b): (Vec<_>, Vec<_>) = self
.rs
.into_iter()
.enumerate()
.partition(|(i, _)| f(*i as u64));
if a.is_empty() {
CircuitError::make_str_err(
"Partition must provide at least one Register to first entry.",
)
} else if b.is_empty() {
CircuitError::make_str_err(
"Partition must provide at least one Register to second entry.",
)
} else {
let f = |vs: Vec<(usize, Register)>| -> Vec<Register> {
vs.into_iter().map(|(_, r)| r).collect()
};
let ra = self.builder.merge(f(a))?;
let rb = self.builder.merge(f(b))?;
Ok(DoubleRegisterChain::new(self.builder, ra, rb))
}
}
pub fn flatten(self) -> Self {
let rs = self.rs;
let builder = self.builder;
let qs: Vec<_> = rs
.into_iter()
.map(|r| builder.split_all(r))
.flatten()
.collect();
Self::new(builder, qs)
}
pub fn apply_merge(
self,
f: impl FnOnce(&mut B, Vec<Register>) -> Register,
) -> SingleRegisterChain<'a, B> {
let r = f(self.builder, self.rs);
SingleRegisterChain::new(self.builder, r)
}
pub fn apply_partition(
self,
f: impl FnOnce(&mut B, Vec<Register>) -> (Register, Register),
) -> DoubleRegisterChain<'a, B> {
let (ra, rb) = f(self.builder, self.rs);
DoubleRegisterChain::new(self.builder, ra, rb)
}
pub fn apply(self, f: impl FnOnce(&mut B, Vec<Register>) -> Vec<Register>) -> Self {
let rs = f(self.builder, self.rs);
Self::new(self.builder, rs)
}
}