ket/decompose/
mod.rs

1// SPDX-FileCopyrightText: 2024 Evandro Chagas Ribeiro da Rosa <evandro@quantuloop.com>
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use 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}