use crate::{
circuit::Circuit,
components::gate::Gate,
errors::Error,
circuit::CircuitBuilder,
};
pub struct Subroutine {
pub gates: Vec<Gate>,
pub num_qubits: usize,
}
impl Subroutine {
pub fn new(num_qubits: usize) -> Self {
Subroutine {
gates: Vec::new(),
num_qubits,
}
}
pub fn with_gates(gates: Vec<Gate>, num_qubits: usize) -> Subroutine {
Subroutine { gates, num_qubits }
}
pub fn get_gates(&self) -> &Vec<Gate> {
&self.gates
}
pub fn add_gate(&mut self, gate: Gate) {
self.gates.push(gate);
}
pub fn add_gates(&mut self, gates: Vec<Gate>) {
self.gates.extend(gates);
}
pub fn get_num_qubits(&self) -> usize {
self.num_qubits
}
pub fn qft(qubits: Vec<usize>, num_qubits: usize) -> Subroutine {
let mut builder: CircuitBuilder = CircuitBuilder::new(num_qubits);
let n: usize = qubits.len();
for i in 0..n {
builder.h_gate(qubits[i]);
let mut power_of_2_denominator = 2.0; for k_loop_val in 1..(n - i) { let original_j_qubit_index = i + k_loop_val; let angle = std::f64::consts::PI / power_of_2_denominator;
builder.cp_gates(vec![qubits[i]], vec![qubits[original_j_qubit_index]], angle);
power_of_2_denominator *= 2.0; }
}
for i in 0..(n / 2) {
builder.swap_gate(qubits[i], qubits[n - 1 - i]);
}
builder.build_subroutine()
}
pub fn iqft(qubits: Vec<usize>, num_qubits: usize) -> Subroutine {
let mut builder: CircuitBuilder = CircuitBuilder::new(num_qubits);
let n: usize = qubits.len();
for i in 0..(n / 2) {
builder.swap_gate(qubits[i], qubits[n - 1 - i]);
}
for i in (0..n).rev() {
if n > i + 1 { let k_initial = (n - 1) - i; let mut power_of_2_denominator = 2_f64.powi(k_initial as i32);
for iteration_count in 0..k_initial {
let k_loop_val = k_initial - iteration_count; let original_j_qubit_index = i + k_loop_val;
let angle = -std::f64::consts::PI / power_of_2_denominator;
builder.cp_gates(vec![qubits[i]], vec![qubits[original_j_qubit_index]], angle);
if k_loop_val > 1 { power_of_2_denominator /= 2.0; }
}
}
builder.h_gate(qubits[i]);
}
builder.build_subroutine()
}
}
impl TryFrom<Subroutine> for Circuit {
fn try_from(value: Subroutine) -> Result<Self, Self::Error> {
let mut circuit = Circuit::new(value.num_qubits);
for gate in value.gates {
circuit.add_gate(gate)?;
}
Ok(circuit)
}
type Error = Error;
}