microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.25.1

Branches

Tags

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

Clone

HTTPS

Download ZIP

source/paulimer/src/pauli/algorithms.rs

128lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use super::{anti_commutes_with, DensePauli, Pauli, PauliBinaryOps};
5use crate::{
6 bits::{BitMatrix, Bitwise},
7 setwise::complement,
8 NeutralElement,
9};
10
11/// # Panics
12/// Will panic if the input `paulis` are not independent
13pub fn complete_to_full_pauli_basis<PauliLike: Pauli>(
14 paulis: &[PauliLike],
15 qubit_count: usize,
16) -> Vec<DensePauli>
17where
18 DensePauli: PauliBinaryOps<PauliLike>,
19{
20 let mut paulis_as_bitmatrix = bitmatrix_from_paulis(paulis, qubit_count);
21 let rank_profile = paulis_as_bitmatrix.echelonize();
22 assert_eq!(rank_profile.len(), paulis.len());
23 let rank_profile_complement = complement(&rank_profile, 2 * qubit_count);
24 let mut result = Vec::new();
25 for pauli in paulis {
26 let mut dense_pauli = DensePauli::neutral_element_of_size(qubit_count);
27 dense_pauli.assign(pauli);
28 result.push(dense_pauli);
29 }
30 for column_index in rank_profile_complement {
31 if column_index < qubit_count {
32 result.push(DensePauli::x(column_index, qubit_count));
33 } else {
34 result.push(DensePauli::z(column_index - qubit_count, qubit_count));
35 }
36 }
37 result
38}
39
40pub fn bitmatrix_from_paulis<PauliLike: Pauli>(
41 paulis: &[PauliLike],
42 qubit_count: usize,
43) -> BitMatrix {
44 let mut result = BitMatrix::zeros(paulis.len(), 2 * qubit_count);
45 for (row_index, pauli) in paulis.iter().enumerate() {
46 for x_column_index in pauli.x_bits().support() {
47 result.set((row_index, x_column_index), true);
48 }
49 for z_column_index in pauli.z_bits().support() {
50 result.set((row_index, qubit_count + z_column_index), true);
51 }
52 }
53 result
54}
55
56pub fn paulis_qubit_count<PauliLike: Pauli>(pauli: &[PauliLike]) -> usize {
57 pauli
58 .iter()
59 .map(super::Pauli::qubit_count)
60 .max()
61 .unwrap_or(0)
62}
63
64pub fn are_the_same_group_up_to_phases<PauliLike1: Pauli, PauliLike2: Pauli>(
65 paulis_left: &[PauliLike1],
66 paulis_right: &[PauliLike2],
67) -> bool {
68 let qubit_count = paulis_qubit_count(paulis_left);
69 if paulis_qubit_count(paulis_right) != qubit_count {
70 return false;
71 }
72 let mut matrix_left = bitmatrix_from_paulis(paulis_left, qubit_count);
73 let mut matrix_right = bitmatrix_from_paulis(paulis_right, qubit_count);
74 let left_rank_profile = matrix_left.echelonize();
75 let right_rank_profile = matrix_right.echelonize();
76 let rank = left_rank_profile.len();
77 if rank == right_rank_profile.len() {
78 matrix_left
79 .rows()
80 .take(rank)
81 .zip(matrix_right.rows().take(rank))
82 .all(|(row_left, row_right)| row_left == row_right)
83 } else {
84 false
85 }
86}
87
88pub fn are_mutually_commuting<PauliLike: Pauli>(paulis: &[PauliLike]) -> bool {
89 for i in 0..paulis.len() {
90 for j in 0..i {
91 if anti_commutes_with(&paulis[i], &paulis[j]) {
92 return false;
93 }
94 }
95 }
96 true
97}
98
99pub fn apply_pauli_exponent<PauliLike: Pauli + PauliBinaryOps>(
100 target: &mut PauliLike,
101 exponent: &PauliLike,
102) {
103 if anti_commutes_with(target, exponent) {
104 target.mul_assign_left(exponent);
105 target.add_assign_phase_exp(1);
106 }
107}
108
109pub fn apply_root_x<PauliLike: Pauli + PauliBinaryOps>(target: &mut PauliLike, qubit_index: usize) {
110 if target.z_bits().index(qubit_index) {
111 target.mul_assign_left_x(qubit_index);
112 target.add_assign_phase_exp(3);
113 }
114}
115
116pub fn apply_root_y<PauliLike: Pauli + PauliBinaryOps>(target: &mut PauliLike, qubit_index: usize) {
117 if !(target.z_bits().index(qubit_index) & target.x_bits().index(qubit_index)) {
118 target.mul_assign_left_y(qubit_index);
119 target.add_assign_phase_exp(3);
120 }
121}
122
123pub fn apply_root_z<PauliLike: Pauli + PauliBinaryOps>(target: &mut PauliLike, qubit_index: usize) {
124 if target.x_bits().index(qubit_index) {
125 target.mul_assign_left_z(qubit_index);
126 target.add_assign_phase_exp(3);
127 }
128}
129