1use num::Integer;
6use serde::Serialize;
7use x::CXMode;
8
9use crate::ir::qubit::LogicalQubit;
10
11pub(crate) mod network;
12pub(crate) mod su2;
13pub(crate) mod u2;
14pub(crate) mod util;
15pub(crate) mod x;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Hash)]
18pub enum AuxMode {
19 Clean,
20 Dirty,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Hash)]
24pub enum DepthMode {
25 Log,
26 Linear,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Default, Hash)]
30pub(crate) enum Algorithm {
31 VChain(CXMode, AuxMode),
32 NetworkU2(CXMode),
33 NetworkPauli(CXMode),
34 SingleAux(DepthMode, AuxMode),
35 SingleAuxU2,
36 #[default]
37 LinearDepth,
38 SU2(DepthMode),
39 SU2Rewrite,
40 AdjustableDepth,
41 NoAuxCX,
42 CU2,
43}
44
45impl std::fmt::Display for Algorithm {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 write!(f, "{self:?}")
48 }
49}
50
51#[derive(Debug, Clone, Default)]
52pub(crate) struct Schema {
53 pub algorithm: Algorithm,
54 pub aux_qubits: Option<(usize, Vec<LogicalQubit>)>,
55 pub approximated: bool,
56}
57
58#[derive(Debug, Clone, Default)]
59pub(crate) enum State {
60 #[default]
61 Begin,
62 End,
63}
64
65#[derive(Debug, Clone, Default)]
66pub(crate) struct Registry {
67 pub algorithm: Algorithm,
68 pub aux_qubits_id: Option<usize>,
69 pub state: State,
70 pub num_u4: i64,
71}
72
73fn num_aux_network_u2(cx_mode: &CXMode, n: usize) -> usize {
74 let n_cx = match cx_mode {
75 CXMode::C2X => 2,
76 CXMode::C3X => 3,
77 };
78
79 let (a, rem) = n.div_rem(&n_cx);
80
81 if n == 1 {
82 0
83 } else if n == 2 && matches!(cx_mode, CXMode::C3X) {
84 1
85 } else {
86 a + num_aux_network_u2(cx_mode, a + rem)
87 }
88}
89
90fn num_aux_network_pauli(cx_mode: &CXMode, n: usize) -> usize {
91 let n_cx = match cx_mode {
92 CXMode::C2X => 2,
93 CXMode::C3X => 3,
94 };
95
96 let (a, rem) = n.div_rem(&n_cx);
97
98 if n <= n_cx {
99 0
100 } else {
101 a + num_aux_network_pauli(cx_mode, a + rem)
102 }
103}
104
105impl Algorithm {
106 pub fn aux_needed(&self, n: usize) -> usize {
107 match self {
108 Algorithm::VChain(cx_mode, _) => match cx_mode {
109 CXMode::C2X => n - 2,
110 CXMode::C3X => usize::div_ceil(n - 3, 2),
111 },
112 Algorithm::NetworkU2(cx_mode) => num_aux_network_u2(cx_mode, n),
113 Algorithm::NetworkPauli(cx_mode) => num_aux_network_pauli(cx_mode, n),
114 Algorithm::SingleAux(_, _) => 1,
115 Algorithm::SingleAuxU2 => 1,
116 Algorithm::LinearDepth => 0,
117 Algorithm::SU2(_) => 0,
118 Algorithm::SU2Rewrite => 1,
119 Algorithm::AdjustableDepth => std::cmp::max(
120 std::env::var("KET_ADJUSTABLE_DEPTH")
121 .unwrap_or("2".to_string())
122 .parse()
123 .unwrap_or((n as f64 * 0.1) as usize),
124 2,
125 ),
126 Algorithm::NoAuxCX => 0,
127 Algorithm::CU2 => 0,
128 }
129 }
130
131 pub fn aux_mode(&self) -> AuxMode {
132 match self {
133 Algorithm::VChain(_, aux_mode) => *aux_mode,
134 Algorithm::SingleAux(_, aux_mode) => *aux_mode,
135 _ => AuxMode::Clean,
136 }
137 }
138
139 pub fn need_aux(&self) -> bool {
140 self.aux_needed(100) > 0
141 }
142}