use super::{Backend, drive};
use crate::circuit::Circuit;
use crate::gate::{Gate1, Gate2};
use crate::kernel;
use crate::measure::measure_qubit;
use crate::rng::Rng;
use crate::state::State;
pub struct StateVectorBackend {
state: State,
rng: Rng,
}
#[derive(Clone, Debug)]
pub struct Execution {
state: State,
classical: Vec<bool>,
}
impl Execution {
#[must_use]
pub fn state(&self) -> &State {
&self.state
}
#[must_use]
pub fn classical(&self) -> &[bool] {
&self.classical
}
#[must_use]
pub fn into_state(self) -> State {
self.state
}
}
impl StateVectorBackend {
pub fn run(circuit: &Circuit) -> crate::Result<Execution> {
Self::run_seeded(circuit, 0)
}
pub fn run_seeded(circuit: &Circuit, seed: u64) -> crate::Result<Execution> {
circuit.validate()?;
let mut backend = Self {
state: State::zero(circuit.num_qubits()),
rng: Rng::seed_from_u64(seed),
};
let classical = drive(&mut backend, circuit.ops(), circuit.num_classical());
Ok(Execution {
state: backend.state,
classical,
})
}
}
impl Backend for StateVectorBackend {
fn apply_1q(&mut self, gate: &Gate1, target: usize) {
kernel::apply_1q(self.state.amplitudes_mut(), target, gate);
}
fn apply_2q(&mut self, gate: &Gate2, a: usize, b: usize) {
kernel::apply_2q(self.state.amplitudes_mut(), a, b, gate);
}
fn apply_controlled(&mut self, controls: &[usize], gate: &Gate1, target: usize) {
kernel::apply_controlled_1q(self.state.amplitudes_mut(), controls, target, gate);
}
fn measure(&mut self, qubit: usize) -> bool {
measure_qubit(&mut self.state, qubit, &mut self.rng)
}
}