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
113
114
115
116
117
use ndarray::{s, Array1, Array2, ArrayView1};
use num_complex::Complex;
pub type C64 = Complex<f64>;
pub const ONE_C: C64 = Complex::new(1f64, 0f64);
pub const ZERO_C: C64 = Complex::new(0f64, 0f64);
pub const I_C: C64 = Complex::new(0f64, 1f64);
#[cfg(feature = "web-sys-log")]
fn log_message(msg: &str) {
web_sys::console::log_1(&msg.into());
}
#[cfg(not(feature = "web-sys-log"))]
fn log_message(msg: &str) {
println!("{}", msg);
}
pub fn log_as_err<T>(msg: String) -> Result<T, String> {
log(&msg);
Err(msg)
}
pub fn log(msg: &str) {
log_message(msg);
}
pub fn swap_columns<T: Clone>(data: &mut Array2<T>, idxs: (usize, usize)) {
let tmp_a = data.slice(s![.., idxs.0]).to_owned();
let tmp_b = data.slice(s![.., idxs.1]).to_owned();
data.slice_mut(s![.., idxs.0]).assign(&tmp_b);
data.slice_mut(s![.., idxs.1]).assign(&tmp_a);
}
pub fn set_vec_to_row_sum(data: &mut Array1<bool>, matrix: &Array2<bool>, idx_source: usize) {
for idx_col in 0..matrix.shape()[1] - 1 {
data[idx_col] ^= matrix[(idx_source, idx_col)];
}
let idx_phase = data.shape()[0] - 1;
data[idx_phase] = phase_product(&data.slice(s![..]), &matrix.slice(s![idx_source, ..]));
}
pub fn set_row_to_row_sum(data: &mut Array2<bool>, idx_source: usize, idx_target: usize) {
for idx_col in 0..data.shape()[1] - 1 {
data[(idx_target, idx_col)] ^= data[(idx_source, idx_col)];
}
let idx_phase = data.shape()[1] - 1;
data[(idx_target, idx_phase)] = phase_product(
&data.slice(s![idx_target, ..]),
&data.slice(s![idx_source, ..]),
);
}
fn g(x1: bool, z1: bool, x2: bool, z2: bool) -> i32 {
match (x1, z1) {
(false, false) => 0,
(true, true) => (if z2 { 1 } else { 0 }) - (if x2 { 1 } else { 0 }),
(true, false) => (if z2 { 1 } else { 0 }) * (if x2 { 1 } else { -1 }),
(false, true) => (if x2 { 1 } else { 0 }) * (if z2 { 1 } else { -1 }),
}
}
pub fn split_row(row: &ArrayView1<bool>) -> (Array1<bool>, Array1<bool>, bool) {
let n_qubits = (row.shape()[0] - 1) / 2;
(
row.slice(s![0..n_qubits]).to_owned(),
row.slice(s![n_qubits..]).to_owned(),
row[2 * n_qubits],
)
}
pub fn phase_product(row1: &ArrayView1<bool>, row2: &ArrayView1<bool>) -> bool {
let mut acc = 0i32;
let (xs1, zs1, r1) = split_row(row1);
let (xs2, zs2, r2) = split_row(row2);
for idx_col in 0..xs1.shape()[0] {
acc += g(xs1[idx_col], zs1[idx_col], xs2[idx_col], zs2[idx_col]);
}
((if r1 { 2 } else { 0 }) + (if r2 { 2 } else { 0 }) + acc) % 4 == 2
}