aboutsummaryrefslogtreecommitdiff
path: root/libpsi/src/core/component.rs
blob: 51e0551e64fa01774c577b046aa4f23e75906a2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use crate::{ColumnVector, Complex, Matrix, VectorMatrix};
use std::ops;

pub type QuantumBit = ColumnVector<Complex<f64>>;
pub type QuantumGate = Matrix<Complex<f64>>;

pub struct QuantumRegister {
    state: ColumnVector<Complex<f64>>,
    qubits: Vec<QuantumBit>,
}

#[macro_export]
macro_rules! count {
    () => { 0 };
    ($head:expr $(,$tail:expr)*) => { 1 + count!($( $tail ),*) };
}

#[macro_export]
macro_rules! qubit {
    ($(($re:expr, $im:expr)),*) => {
        {
            let mut vector = Vec::new();
            $(
                vector.push(complex!($re, $im));
            )*
            QuantumBit::new(vector)
        }
    };
}

#[macro_export]
macro_rules! quantum_register {
    ($($bit:expr),*) => {
        {
            const N: usize = count!($($bit),*);
            let mut bits: [QuantumBit; N] = [$($bit),*];
            QuantumRegister::from(&mut bits)
        }
    };
}

impl QuantumBit {
    pub fn get_state(&self) -> i32 {
        (self[1] != Complex::new(0.0, 0.0)) as i32
    }
}

impl QuantumRegister {
    pub fn from(bits: &mut [QuantumBit]) -> QuantumRegister {
        let matrices: Vec<Matrix<Complex<f64>>> = bits.iter().map(|bit| bit.to_matrix()).collect();
        let mut result = matrices[0].clone();
        for matrix in &matrices[1..] {
            result = result.kronecker(matrix);
        }

        QuantumRegister {
            qubits: bits.to_vec(),
            state: ColumnVector::from_matrix(&result),
        }
    }

    pub fn apply(&mut self, gate: &QuantumGate, index: usize) {
        let result: ColumnVector<Complex<f64>> = self.state.mul_matrix(gate).unwrap();
        self.qubits[index] = result;
    }
}

impl ops::Index<usize> for QuantumRegister {
    type Output = QuantumBit;

    fn index(&self, index: usize) -> &Self::Output {
        &self.qubits[index]
    }
}

impl ops::IndexMut<usize> for QuantumRegister {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        &mut self.qubits[index]
    }
}