pub mod factored;
pub mod factored_stabilizer;
pub mod mps;
pub mod product;
pub(crate) mod simd;
pub mod sparse;
pub mod stabilizer;
pub mod statevector;
pub mod tensornetwork;
use num_complex::Complex64;
use crate::circuit::Instruction;
use crate::error::Result;
#[cfg(feature = "parallel")]
pub(crate) const PARALLEL_THRESHOLD_QUBITS: usize = 14;
#[cfg(feature = "parallel")]
pub(crate) const MIN_PAR_ELEMS: usize = 4096;
#[cfg(feature = "parallel")]
pub(crate) const MIN_PAR_ITERS: usize = 2048;
#[cfg(feature = "parallel")]
pub(crate) const MIN_QUBITS_FOR_PAR_GATES: usize = 128;
#[cfg(feature = "parallel")]
pub(crate) const MIN_ANTI_ROWS_FOR_PAR: usize = 4;
pub(crate) const NORM_CLAMP_MIN: f64 = 1e-30;
pub(crate) const PHASE_IS_ONE_EPS: f64 = 1e-15;
pub(crate) const MAX_PROB_QUBITS: usize = 25;
#[inline(always)]
pub(crate) fn is_phase_one(phase: Complex64) -> bool {
(phase.re - 1.0).abs() < PHASE_IS_ONE_EPS && phase.im.abs() < PHASE_IS_ONE_EPS
}
#[inline(always)]
pub(crate) fn measurement_inv_norm(outcome: bool, prob_one: f64) -> f64 {
let prob_outcome = if outcome { prob_one } else { 1.0 - prob_one };
1.0 / prob_outcome.clamp(NORM_CLAMP_MIN, 1.0).sqrt()
}
#[inline(always)]
pub(crate) fn init_classical_bits(bits: &mut Vec<bool>, num: usize) {
if bits.len() == num {
bits.fill(false);
} else {
*bits = vec![false; num];
}
}
#[cfg(feature = "parallel")]
pub(crate) fn init_thread_pool() {
use std::sync::Once;
static INIT: Once = Once::new();
INIT.call_once(|| {
if std::env::var("RAYON_NUM_THREADS").is_err() {
let threads = num_cpus::get();
rayon::ThreadPoolBuilder::new()
.num_threads(threads)
.build_global()
.ok();
}
});
}
#[inline(always)]
pub(crate) fn sorted_mcu_qubits(controls: &[usize], target: usize, buf: &mut [usize; 10]) -> usize {
let n = controls.len() + 1;
buf[..controls.len()].copy_from_slice(controls);
buf[controls.len()] = target;
buf[..n].sort_unstable();
n
}
pub trait Backend {
fn name(&self) -> &'static str;
fn init(&mut self, num_qubits: usize, num_classical_bits: usize) -> Result<()>;
fn apply(&mut self, instruction: &Instruction) -> Result<()>;
fn classical_results(&self) -> &[bool];
fn probabilities(&self) -> Result<Vec<f64>>;
fn num_qubits(&self) -> usize;
fn apply_instructions(&mut self, instructions: &[Instruction]) -> Result<()> {
for instruction in instructions {
self.apply(instruction)?;
}
Ok(())
}
fn supports_fused_gates(&self) -> bool {
true
}
fn supports_qft_block(&self) -> bool {
false
}
fn export_statevector(&self) -> Result<Vec<Complex64>> {
Err(crate::error::PrismError::BackendUnsupported {
backend: self.name().to_string(),
operation: "statevector export".to_string(),
})
}
fn qubit_probability(&self, qubit: usize) -> Result<f64> {
let rho = self.reduced_density_matrix_1q(qubit)?;
Ok(rho[1][1].re.clamp(0.0, 1.0))
}
fn reduced_density_matrix_1q(&self, _qubit: usize) -> Result<[[Complex64; 2]; 2]> {
Err(crate::error::PrismError::BackendUnsupported {
backend: self.name().to_string(),
operation: "reduced_density_matrix_1q".to_string(),
})
}
fn reset(&mut self, _qubit: usize) -> Result<()> {
Err(crate::error::PrismError::BackendUnsupported {
backend: self.name().to_string(),
operation: "reset".to_string(),
})
}
fn apply_1q_matrix(&mut self, qubit: usize, matrix: &[[Complex64; 2]; 2]) -> Result<()> {
use crate::circuit::smallvec;
self.apply(&crate::circuit::Instruction::Gate {
gate: crate::gates::Gate::Fused(Box::new(*matrix)),
targets: smallvec![qubit],
})
}
}