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
extern crate num;
use crate::types::Precision;
use num::Complex;
use std::fmt;
pub enum PrecisionUnitaryOp<'a, P: Precision> {
Matrix(Vec<u64>, Vec<Complex<P>>),
SparseMatrix(Vec<u64>, Vec<Vec<(u64, Complex<P>)>>),
Swap(Vec<u64>, Vec<u64>),
Control(Vec<u64>, Vec<u64>, Box<PrecisionUnitaryOp<'a, P>>),
Function(
Vec<u64>,
Vec<u64>,
&'a (dyn Fn(u64) -> (u64, f64) + Send + Sync),
),
}
impl<'a, P: Precision> fmt::Debug for PrecisionUnitaryOp<'a, P> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (name, indices) = match self {
PrecisionUnitaryOp::Matrix(indices, _) => ("Matrix".to_string(), indices.clone()),
PrecisionUnitaryOp::SparseMatrix(indices, _) => {
("SparseMatrix".to_string(), indices.clone())
}
PrecisionUnitaryOp::Swap(a_indices, b_indices) => {
let indices: Vec<_> = a_indices
.iter()
.cloned()
.chain(b_indices.iter().cloned())
.collect();
("Swap".to_string(), indices)
}
PrecisionUnitaryOp::Control(indices, _, op) => {
let name = format!("C({:?})", *op);
(name, indices.clone())
}
PrecisionUnitaryOp::Function(a_indices, b_indices, _) => {
let indices: Vec<_> = a_indices
.iter()
.cloned()
.chain(b_indices.iter().cloned())
.collect();
("F".to_string(), indices)
}
};
let int_strings = indices
.iter()
.map(|x| x.clone().to_string())
.collect::<Vec<String>>();
write!(f, "{}[{}]", name, int_strings.join(", "))
}
}
pub fn precision_num_indices<P: Precision>(op: &PrecisionUnitaryOp<P>) -> usize {
match &op {
PrecisionUnitaryOp::Matrix(indices, _) => indices.len(),
PrecisionUnitaryOp::SparseMatrix(indices, _) => indices.len(),
PrecisionUnitaryOp::Swap(a, b) => a.len() + b.len(),
PrecisionUnitaryOp::Control(cs, os, _) => cs.len() + os.len(),
PrecisionUnitaryOp::Function(inputs, outputs, _) => inputs.len() + outputs.len(),
}
}
pub fn precision_get_index<P: Precision>(op: &PrecisionUnitaryOp<P>, i: usize) -> u64 {
match &op {
PrecisionUnitaryOp::Matrix(indices, _) => indices[i],
PrecisionUnitaryOp::SparseMatrix(indices, _) => indices[i],
PrecisionUnitaryOp::Swap(a, b) => {
if i < a.len() {
a[i]
} else {
b[i - a.len()]
}
}
PrecisionUnitaryOp::Control(cs, os, _) => {
if i < cs.len() {
cs[i]
} else {
os[i - cs.len()]
}
}
PrecisionUnitaryOp::Function(inputs, outputs, _) => {
if i < inputs.len() {
inputs[i]
} else {
outputs[i - inputs.len()]
}
}
}
}