use crate::builder_traits::{
AdvancedCircuitBuilder, CircuitBuilder, QubitRegister, SplitManyResult, Subcircuitable,
};
use crate::conditioning::{Conditionable, ConditionableSubcircuit};
use crate::errors::CircuitResult;
use crate::types::Precision;
pub trait RecursiveCircuitBuilder<P: Precision>:
Invertable<SimilarBuilder = Self::RecursiveSimilarBuilder>
+ Conditionable
+ AdvancedCircuitBuilder<P>
+ Subcircuitable
+ ConditionableSubcircuit
{
type RecursiveSimilarBuilder: RecursiveCircuitBuilder<P>
+ Subcircuitable<Subcircuit = Self::Subcircuit>;
}
pub trait Invertable: Subcircuitable {
type SimilarBuilder: Subcircuitable<Subcircuit = Self::Subcircuit>;
fn new_similar(&self) -> Self::SimilarBuilder;
fn invert_subcircuit(sc: Self::Subcircuit) -> CircuitResult<Self::Subcircuit>;
fn apply_inverted_subcircuit(
&mut self,
sc: Self::Subcircuit,
r: Self::Register,
) -> CircuitResult<Self::Register> {
let sc = Self::invert_subcircuit(sc)?;
self.apply_subcircuit(sc, r)
}
}
pub fn inverter_args<T, CB, F>(
cb: &mut CB,
rs: Vec<CB::Register>,
f: F,
t: T,
) -> CircuitResult<Vec<CB::Register>>
where
CB: Invertable,
F: Fn(
&mut CB::SimilarBuilder,
Vec<<CB::SimilarBuilder as CircuitBuilder>::Register>,
T,
) -> CircuitResult<Vec<<CB::SimilarBuilder as CircuitBuilder>::Register>>,
{
let mut sub_cb = cb.new_similar();
let sub_rs = rs
.iter()
.map(|r| sub_cb.register(r.n_nonzero()))
.collect::<_>();
let _ = f(&mut sub_cb, sub_rs, t)?;
let subcircuit = sub_cb.make_subcircuit()?;
let (_, ranges) = rs
.iter()
.map(|r| r.n())
.fold((0, vec![]), |(n, mut acc), rn| {
acc.push(n..n + rn);
(n + rn, acc)
});
let r = cb.merge_registers(rs).unwrap();
let r = cb.apply_inverted_subcircuit(subcircuit, r)?;
match cb.split_relative_index_groups(r, ranges) {
SplitManyResult::AllSelected(rs) => Ok(rs),
SplitManyResult::Remaining(_, _) => unreachable!(),
}
}
pub fn inverter<CB, F>(cb: &mut CB, r: Vec<CB::Register>, f: F) -> CircuitResult<Vec<CB::Register>>
where
CB: Invertable,
F: Fn(
&mut CB::SimilarBuilder,
Vec<<CB::SimilarBuilder as CircuitBuilder>::Register>,
) -> CircuitResult<Vec<<CB::SimilarBuilder as CircuitBuilder>::Register>>,
{
inverter_args(cb, r, |r, cb, _| f(r, cb), ())
}
#[cfg(test)]
mod inverter_test {
}