microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
brlackey/neutral-atom-models

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/paulimer/src/clifford.rs

189lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::bits::{BitMatrix, Bitwise, WORD_COUNT_DEFAULT};
5use crate::pauli::{Pauli, PauliBinaryOps, PauliBits, PauliMutable, PauliUnitary};
6use crate::quantum_core;
7use crate::UnitaryOp;
8use num_derive::{FromPrimitive, ToPrimitive};
9
10#[derive(FromPrimitive, ToPrimitive, Clone, Copy, Debug, PartialEq, Eq)]
11pub enum XOrZ {
12 X = Axis::X as isize,
13 Z = Axis::Z as isize,
14}
15
16pub trait Clifford {
17 type PhaseExponentValue;
18 type DensePauli: PauliMutable + Pauli<PhaseExponentValue = Self::PhaseExponentValue>;
19 fn num_qubits(&self) -> usize;
20 fn qubits(&self) -> std::ops::Range<usize> {
21 0..self.num_qubits()
22 }
23
24 fn is_valid(&self) -> bool;
25 fn is_identity(&self) -> bool;
26
27 #[must_use]
28 fn identity(num_qubits: usize) -> Self;
29 #[must_use]
30 fn zero(num_qubits: usize) -> Self;
31 #[must_use]
32 fn random(num_qubits: usize, random_number_generator: &mut impl rand::Rng) -> Self;
33
34 fn preimage_x(&self, qubit_index: usize) -> Self::DensePauli;
35 fn preimage_z(&self, qubit_index: usize) -> Self::DensePauli;
36 fn preimage_x_bits(&self, x_bits: &impl Bitwise) -> Self::DensePauli;
37 fn preimage_z_bits(&self, z_bits: &impl Bitwise) -> Self::DensePauli;
38 fn preimage<PauliLike: Pauli<PhaseExponentValue = Self::PhaseExponentValue>>(
39 &self,
40 pauli: &PauliLike,
41 ) -> Self::DensePauli;
42
43 fn image_x(&self, qubit_index: usize) -> Self::DensePauli;
44 fn image_z(&self, qubit_index: usize) -> Self::DensePauli;
45 fn image_x_bits(&self, x_bits: &impl Bitwise) -> Self::DensePauli;
46 fn image_z_bits(&self, z_bits: &impl Bitwise) -> Self::DensePauli;
47 fn image<PauliLike: Pauli<PhaseExponentValue = Self::PhaseExponentValue>>(
48 &self,
49 pauli: &PauliLike,
50 ) -> Self::DensePauli;
51
52 #[must_use]
53 fn multiply_with(&self, rhs: &Self) -> Self;
54 #[must_use]
55 fn tensor(&self, rhs: &Self) -> Self;
56 #[must_use]
57 fn inverse(&self) -> Self;
58 #[must_use]
59 fn from_preimages(preimages: &[Self::DensePauli]) -> Self;
60 #[must_use]
61 fn from_css_preimage_indicators(x_indicators: &BitMatrix, z_indicators: &BitMatrix) -> Self;
62
63 fn is_diagonal(&self, axis: XOrZ) -> bool;
64 fn is_diagonal_resource_encoder(&self, axis: XOrZ) -> bool;
65 fn is_css(&self) -> bool;
66 fn unitary_from_diagonal_resource_state(&self, axis: XOrZ) -> Option<Self>
67 where
68 Self: Sized;
69
70 fn symplectic_matrix(&self) -> BitMatrix;
71}
72
73pub trait CliffordMutable {
74 type PhaseExponentValue;
75
76 fn left_mul_x(&mut self, qubit_index: usize);
77 fn left_mul_y(&mut self, qubit_index: usize);
78 fn left_mul_z(&mut self, qubit_index: usize);
79
80 fn left_mul_hadamard(&mut self, qubit_index: usize);
81 fn left_mul_root_z(&mut self, qubit_index: usize);
82 fn left_mul_root_z_inverse(&mut self, qubit_index: usize);
83 fn left_mul_root_x(&mut self, qubit_index: usize);
84 fn left_mul_root_x_inverse(&mut self, qubit_index: usize);
85 fn left_mul_root_y(&mut self, qubit_index: usize);
86 fn left_mul_root_y_inverse(&mut self, qubit_index: usize);
87
88 fn left_mul_cx(&mut self, control_qubit_index: usize, target_qubit_index: usize);
89 fn left_mul_cz(&mut self, qubit1_index: usize, qubit2_index: usize);
90 fn left_mul_prepare_bell(&mut self, qubit1_index: usize, qubit2_index: usize);
91 fn left_mul_swap(&mut self, qubit_index1: usize, qubit_index2: usize);
92
93 fn left_mul(&mut self, unitary_op: UnitaryOp, support: &[usize]);
94
95 fn left_mul_pauli<PauliLike: Pauli>(&mut self, pauli: &PauliLike);
96 fn left_mul_pauli_exp<PauliLike: Pauli<PhaseExponentValue = Self::PhaseExponentValue>>(
97 &mut self,
98 pauli: &PauliLike,
99 );
100 fn left_mul_controlled_pauli<PauliLike: Pauli<PhaseExponentValue = Self::PhaseExponentValue>>(
101 &mut self,
102 control: &PauliLike,
103 target: &PauliLike,
104 );
105
106 fn left_mul_permutation(&mut self, permutation: &[usize], support: &[usize]);
107 fn left_mul_clifford<CliffordLike>(&mut self, clifford: &CliffordLike, support: &[usize])
108 where
109 CliffordLike: Clifford<PhaseExponentValue = Self::PhaseExponentValue>
110 + PreimageViews<PhaseExponentValue = Self::PhaseExponentValue>;
111}
112
113pub trait PreimageViews {
114 type PhaseExponentValue;
115 type PreImageView<'life>: Pauli<PhaseExponentValue = Self::PhaseExponentValue>
116 where
117 Self: 'life;
118 type ImageViewUpToPhase<'life>: Pauli<PhaseExponentValue = ()>
119 where
120 Self: 'life;
121
122 fn preimage_x_view(&self, index: usize) -> Self::PreImageView<'_>;
123 fn preimage_z_view(&self, index: usize) -> Self::PreImageView<'_>;
124 fn x_image_view_up_to_phase(&self, qubit_index: usize) -> Self::ImageViewUpToPhase<'_>;
125 fn z_image_view_up_to_phase(&self, qubit_index: usize) -> Self::ImageViewUpToPhase<'_>;
126}
127
128pub trait MutablePreImages {
129 type PhaseExponentValue;
130 type PreImageViewMut<'life>: PauliBinaryOps
131 + Pauli<PhaseExponentValue = Self::PhaseExponentValue>
132 where
133 Self: 'life;
134 fn preimage_x_view_mut(&mut self, qubit_index: usize) -> Self::PreImageViewMut<'_>;
135 fn preimage_z_view_mut(&mut self, qubit_index: usize) -> Self::PreImageViewMut<'_>;
136 fn preimage_xz_views_mut(
137 &mut self,
138 index: usize,
139 ) -> (Self::PreImageViewMut<'_>, Self::PreImageViewMut<'_>);
140 fn preimage_xz_views_mut_distinct(
141 &mut self,
142 index: (usize, usize),
143 ) -> crate::Tuple2x2<Self::PreImageViewMut<'_>>;
144}
145
146pub mod generic_algos;
147
148#[must_use]
149#[derive(Eq, Clone)]
150pub struct CliffordUnitary {
151 bits: BitMatrix<WORD_COUNT_DEFAULT>,
152 preimage_phase_exponents: Vec<u8>,
153}
154
155#[must_use]
156#[derive(Eq, Clone)]
157pub struct CliffordUnitaryModPauli {
158 bits: BitMatrix<WORD_COUNT_DEFAULT>,
159}
160
161#[must_use]
162#[repr(C, align(64))]
163#[derive(Eq, PartialEq, Clone, Debug)]
164pub struct CliffordModPauliBatch<const WORD_COUNT: usize, const QUBIT_COUNT: usize> {
165 pub preimages: [[[u64; WORD_COUNT]; QUBIT_COUNT]; 4],
166}
167
168pub struct PauliExponent<Bits: PauliBits, Phase: crate::pauli::generic::PhaseExponent>(
169 PauliUnitary<Bits, Phase>,
170);
171pub struct ControlledPauli<Bits: PauliBits, Phase: crate::pauli::generic::PhaseExponent>(
172 PauliUnitary<Bits, Phase>,
173 PauliUnitary<Bits, Phase>,
174);
175pub struct Swap(pub usize, pub usize);
176pub struct Hadamard(pub usize);
177
178mod clifford_impl;
179pub use clifford_impl::{
180 apply_qubit_clifford_by_axis, group_encoding_clifford_of, prepare_all_plus, prepare_all_zero,
181 random_clifford_via_operations_sampling, recover_z_images_phases, split_clifford_encoder,
182 split_clifford_encoder_mod_pauli, split_clifford_mod_pauli_with_transforms, split_phased_css,
183 split_qubit_cliffords_and_css, split_qubit_tensor_product_encoder,
184};
185use quantum_core::Axis;
186mod special_clifford;
187
188#[derive(Debug, PartialEq, Eq, Default)]
189pub struct CliffordStringParsingError;
190