mod bytecode;
mod cpu;
mod network;
mod tree;
pub use bytecode::Bytecode;
pub use cpu::PinnedTNVM;
pub use cpu::TNVM;
pub use cpu::TNVMResult;
pub use cpu::TNVMReturnType;
pub use network::QuditCircuitTensorNetworkBuilder;
pub use network::QuditTensor;
pub use network::QuditTensorNetwork;
pub fn compile_network(network: QuditTensorNetwork) -> Bytecode {
let optimal_path = network.solve_for_path();
let tree = network.path_to_ttgt_tree(optimal_path);
crate::bytecode::BytecodeGenerator::new().generate(tree)
}
#[cfg(test)]
mod tests {
use crate::bytecode::BytecodeGenerator;
use qudit_core::{ParamInfo, Radices};
use qudit_expr::GRADIENT;
use qudit_expr::TensorExpression;
use super::*;
#[test]
fn test_projective_measurement() {
let u3 = TensorExpression::new(
"U3(a, b, c) {
[
[cos(a/2), ~e^(c*i)*sin(a/2)],
[e^(b*i)*sin(a/2), e^(i*(b+c))*cos(a/2)],
]
}",
);
let classically_controlled_u3 = u3.stack_with_identity(&[1], 2);
let zz = TensorExpression::new(
"ZZParity() {
[
[
[ 1, 0, 0, 0 ],
[ 0, 0, 0, 0 ],
[ 0, 0, 0, 0 ],
[ 0, 0, 0, 1 ],
],
[
[ 0, 0, 0, 0 ],
[ 0, 1, 0, 0 ],
[ 0, 0, 1, 0 ],
[ 0, 0, 0, 0 ],
],
]
}",
);
let network = QuditCircuitTensorNetworkBuilder::new(Radices::new([2, 2]), None)
.prepend_expression(
zz.clone(),
ParamInfo::empty(),
vec![0, 1],
vec![0, 1],
vec!["a".to_string()],
)
.prepend_expression(
classically_controlled_u3.clone(),
ParamInfo::parameterized(vec![0, 1, 2]),
vec![0],
vec![0],
vec!["a".to_string()],
)
.build();
let optimal_path = network.solve_for_path();
println!("Optimal Path: {:?}", optimal_path.path);
let tree = network.path_to_ttgt_tree(optimal_path);
println!("Expression Tree: {:?}", tree);
let code = BytecodeGenerator::new().generate(tree);
println!("Bytecode: \n{:?}", code);
let params = [1.7, 1.7, 1.7];
let mut tnvm = TNVM::<qudit_core::c64, GRADIENT>::new(&code, None);
let out = tnvm.evaluate::<GRADIENT>(¶ms);
let out_fn = out.get_fn_result().unpack_tensor3d();
println!("{:?}", out_fn);
let out_fn = out.get_grad_result().unpack_tensor4d();
println!("{:?}", out_fn);
}
}