aboutsummaryrefslogtreecommitdiff
path: root/libpsi-core/src/runtimes/basic_rt.rs
blob: ed162058e97b2f7f286a981bb3044eba014c09b3 (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use crate::{
    ColumnVector, Complex, ExecutationData, Numeric, QuantumBit, QuantumCircuit, QuantumRegister,
    Runtime, RuntimeBase, Vector,
};

pub struct BasicRT {
    circuit: QuantumCircuit,
}

impl RuntimeBase for BasicRT {
    fn get_circuit(&self) -> &QuantumCircuit {
        &self.circuit
    }
}

impl BasicRT {
    fn calculate_state(state: &ColumnVector<Complex<f64>>, n: usize) -> QuantumBit {
        let num_states = 1 << n;
        let half_states = num_states >> 1;

        let mut alpha = Complex::zero();
        let mut beta = Complex::zero();

        for i in 0..num_states {
            if i < half_states {
                alpha += state[i];
            } else {
                beta += state[i];
            }
        }

        QuantumBit::new(vec![alpha, beta])
    }

    fn calculate_probabilities(state: &ColumnVector<Complex<f64>>, n: usize) -> (f64, f64) {
        let num_states = 1 << n;
        let half_states = num_states >> 1;

        let mut state_0 = 0.0;
        let mut state_1 = 0.0;

        for i in 0..num_states {
            let prob = state[i].norm() * state[i].norm();
            if i < half_states {
                state_0 += prob;
            } else {
                state_1 += prob;
            }
        }

        (state_0, state_1)
    }
}

impl Runtime for BasicRT {
    fn new(circuit: QuantumCircuit) -> BasicRT {
        BasicRT { circuit }
    }

    fn execute(&self, repeat: usize) -> Vec<ExecutationData> {
        let mut result: Vec<ExecutationData> = Vec::with_capacity(repeat);
        for _ in 0..repeat {
            let mut executation_data = ExecutationData::new(
                self.circuit.get_quantum_bits(),
                self.circuit.get_classical_registers(),
            );

            for instruction in self.circuit.get_instructions() {
                let mut control_bits: Vec<QuantumBit> = Vec::new();
                let mut target_bits: Vec<QuantumBit> = Vec::new();
                let mut quantum_bits: Vec<QuantumBit> = Vec::new();

                for index in instruction.control_indices.clone() {
                    control_bits.push(executation_data.quantum_states.clone()[index].clone());
                    quantum_bits.push(executation_data.quantum_states.clone()[index].clone());
                }

                for index in instruction.target_indices.clone() {
                    target_bits.push(executation_data.quantum_states.clone()[index].clone());
                    quantum_bits.push(executation_data.quantum_states.clone()[index].clone());
                }

                if control_bits.len() > 0 {
                    let control_register = QuantumRegister::from(&mut control_bits);
                    let control_register_state_vector = control_register.get_state();
                    let (control_register_state_0, control_register_state_1) =
                        BasicRT::calculate_probabilities(
                            &control_register_state_vector,
                            control_register.get_bits().len(),
                        );

                    if control_register_state_0 > control_register_state_1 {
                        continue;
                    }
                }

                let target_register = QuantumRegister::from(&mut quantum_bits);
                let target_state_vector = target_register.apply(&instruction.gate);
                let target_state =
                    BasicRT::calculate_state(&target_state_vector, quantum_bits.len());
                executation_data.quantum_states[instruction.target_indices.clone()[0]] =
                    target_state;
            }

            let final_quantum_register =
                QuantumRegister::from(&mut executation_data.quantum_states.clone());
            final_quantum_register.measure(&mut executation_data.classical_states);
            result.push(executation_data);
        }
        result
    }
}