stabilizer_ch_form_rust/form/
kron.rs

1use crate::{StabilizerCHForm, error::Result};
2use ndarray::{Axis, s};
3
4impl StabilizerCHForm {
5    /// Computes the tensor product of this state with another: |self> ⊗ |other>.
6    ///
7    /// ## Arguments
8    /// * `other` - The other StabilizerCHForm to tensor with.
9    ///
10    /// ## Returns
11    /// A [`Result`] containing the new `StabilizerCHForm` representing the tensor product state.
12    pub fn kron(&self, other: &StabilizerCHForm) -> Result<StabilizerCHForm> {
13        let n_total = self.n + other.n;
14        let mut new_state = StabilizerCHForm::new(n_total)?;
15
16        // Create block-diagonal matrices for G, F, and M
17        new_state
18            .mat_g
19            .slice_mut(s![..self.n, ..self.n])
20            .assign(&self.mat_g);
21        new_state
22            .mat_g
23            .slice_mut(s![self.n.., self.n..])
24            .assign(&other.mat_g);
25
26        new_state
27            .mat_f
28            .slice_mut(s![..self.n, ..self.n])
29            .assign(&self.mat_f);
30        new_state
31            .mat_f
32            .slice_mut(s![self.n.., self.n..])
33            .assign(&other.mat_f);
34
35        new_state
36            .mat_m
37            .slice_mut(s![..self.n, ..self.n])
38            .assign(&self.mat_m);
39        new_state
40            .mat_m
41            .slice_mut(s![self.n.., self.n..])
42            .assign(&other.mat_m);
43
44        // Concatenate vectors by creating a slice of views directly.
45        new_state.gamma = ndarray::concatenate(Axis(0), &[self.gamma.view(), other.gamma.view()])
46            .expect("Failed to concatenate gamma vectors");
47
48        new_state.vec_v = ndarray::concatenate(Axis(0), &[self.vec_v.view(), other.vec_v.view()])
49            .expect("Failed to concatenate v vectors");
50
51        new_state.vec_s = ndarray::concatenate(Axis(0), &[self.vec_s.view(), other.vec_s.view()])
52            .expect("Failed to concatenate s vectors");
53
54        // Combine global phases and phase factors
55        new_state.set_global_phase(self.global_phase() * other.global_phase());
56        new_state.phase_factor = self.phase_factor * other.phase_factor;
57
58        Ok(new_state)
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65    use crate::circuit::CliffordCircuit;
66    use crate::test_utils::{assert_eq_complex_array1, tensor_statevectors};
67
68    #[test]
69    fn test_kron() {
70        let num_qubits_1 = 3;
71        let num_qubits_2 = 3;
72        let trials = 10;
73        for i in 0..trials {
74            let circuit_1 = CliffordCircuit::random_clifford(num_qubits_1, Some([i + 56; 32]));
75            let circuit_2 = CliffordCircuit::random_clifford(num_qubits_2, Some([i + 78; 32]));
76            let state_1 = StabilizerCHForm::from_clifford_circuit(&circuit_1).unwrap();
77            let state_2 = StabilizerCHForm::from_clifford_circuit(&circuit_2).unwrap();
78            let kron_state = state_1.kron(&state_2).unwrap();
79            let expected_statevector = tensor_statevectors(
80                &state_1.to_statevector().unwrap(),
81                &state_2.to_statevector().unwrap(),
82            );
83            let kron_statevector = kron_state.to_statevector().unwrap();
84            assert_eq_complex_array1(&kron_statevector, &expected_statevector);
85        }
86    }
87}