rqism 0.4.1

A multi-backend quantum circuit simulator
Documentation
use ndarray::Array2;
use num::Complex;
use rand::{distributions::WeightedIndex, prelude::Distribution, rngs::ThreadRng, Rng};

use crate::{
    circuit::Circuit,
    counts::Counts,
    instruction::{Instruction, PauliKind},
};

/// Trait that must be implemented for all simulators. Includes common behaviour
pub trait Simulator {
    fn execute_instruction(&mut self, ins: &Instruction);
    fn execute_circuit(&mut self, circuit: &Circuit);
    fn get_counts(&self, circuit: &Circuit, n: usize) -> Counts;
    fn get_random(&mut self) -> &mut ThreadRng;

    fn apply_local_depolarizing_noise(&mut self, target: usize, p: f32) {
        let rng = self.get_random();
        let pauli_kinds = [
            None,
            Some(PauliKind::X),
            Some(PauliKind::Y),
            Some(PauliKind::Z),
        ];

        let weights = [1.0 - p, p / 3.0, p / 3.0, p / 3.0];

        let dist = WeightedIndex::new(weights).unwrap();

        let op = pauli_kinds[dist.sample(rng)];

        if let Some(k) = op {
            self.execute_instruction(&Instruction::Pauli { kind: k, target });
        }
    }

    fn apply_amplitude_damping(&mut self, target: usize, gamma: f32) {
        let e0 = Array2::from_shape_vec(
            (2, 2),
            vec![
                Complex::new(1.0, 0.0),
                Complex::new(0.0, 0.0),
                Complex::new(0.0, 0.0),
                Complex::new((1.0 - gamma).sqrt(), 0.0),
            ],
        )
        .unwrap();

        let e1 = Array2::from_shape_vec(
            (2, 2),
            vec![
                Complex::new(0.0, 0.0),
                Complex::new(gamma.sqrt(), 0.0),
                Complex::new(0.0, 0.0),
                Complex::new(0.0, 0.0),
            ],
        )
        .unwrap();

        let k = self.get_random().gen_range(0.0..1.0);

        self.execute_instruction(&Instruction::Gate {
            matrix: std::borrow::Cow::Owned(if k < gamma { e1 } else { e0 }),
            indices: vec![target],
            kind: None,
        });
    }
}