diff --git a/synir/src/data_structures.rs b/synir/src/data_structures.rs index cd7143cb..98aade8b 100644 --- a/synir/src/data_structures.rs +++ b/synir/src/data_structures.rs @@ -55,39 +55,39 @@ pub trait MaskedPropagateClifford where Self: Sized, { - fn masked_cx(&self, control: IndexType, target: IndexType, mask: &BitVec) -> &Self; - fn masked_s(&self, target: IndexType, mask: &BitVec) -> &Self; - fn masked_v(&self, target: IndexType, mask: &BitVec) -> &Self; + fn masked_cx(&mut self, control: IndexType, target: IndexType, mask: &BitVec) -> &mut Self; + fn masked_s(&mut self, target: IndexType, mask: &BitVec) -> &mut Self; + fn masked_v(&mut self, target: IndexType, mask: &BitVec) -> &mut Self; - fn masked_s_dgr(&self, target: IndexType, mask: &BitVec) -> &Self { + fn masked_s_dgr(&mut self, target: IndexType, mask: &BitVec) -> &mut Self { self.masked_z(target, mask).masked_s(target, mask) } - fn masked_v_dgr(&self, target: IndexType, mask: &BitVec) -> &Self { + fn masked_v_dgr(&mut self, target: IndexType, mask: &BitVec) -> &mut Self { self.masked_x(target, mask).masked_v(target, mask) } - fn masked_x(&self, target: IndexType, mask: &BitVec) -> &Self { + fn masked_x(&mut self, target: IndexType, mask: &BitVec) -> &mut Self { self.masked_v(target, mask).masked_v(target, mask) } - fn masked_y(&self, target: IndexType, mask: &BitVec) -> &Self { + fn masked_y(&mut self, target: IndexType, mask: &BitVec) -> &mut Self { self.masked_s_dgr(target, mask) .masked_x(target, mask) .masked_s(target, mask) } - fn masked_z(&self, target: IndexType, mask: &BitVec) -> &Self { + fn masked_z(&mut self, target: IndexType, mask: &BitVec) -> &mut Self { self.masked_s(target, mask).masked_s(target, mask) } - fn masked_h(&self, target: IndexType, mask: &BitVec) -> &Self { + fn masked_h(&mut self, target: IndexType, mask: &BitVec) -> &mut Self { self.masked_s(target, mask) .masked_v(target, mask) .masked_s(target, mask) } - fn masked_cz(&self, control: IndexType, target: IndexType, mask: &BitVec) -> &Self { + fn masked_cz(&mut self, control: IndexType, target: IndexType, mask: &BitVec) -> &mut Self { self.masked_h(target, mask); self.masked_cx(control, target, mask); self.masked_h(target, mask) diff --git a/synir/src/data_structures/clifford_tableau.rs b/synir/src/data_structures/clifford_tableau.rs index eaf1d451..3c7ac932 100644 --- a/synir/src/data_structures/clifford_tableau.rs +++ b/synir/src/data_structures/clifford_tableau.rs @@ -62,21 +62,20 @@ impl CliffordTableau { /// Implements algorithms from https://doi.org/10.22331/q-2022-06-13-734 and Qiskit Clifford implementation pub(crate) fn prepend(&self, lhs: &Self) -> Self { let size = self.size(); - let pauli_columns = vec![PauliString::from_text(&"I".repeat(2 * size)); size]; + let mut pauli_columns = vec![PauliString::from_text(&"I".repeat(2 * size)); size]; // Matrix-multiplication for M(rhs o self) = M(self) * M(rhs) as this is a row-permutation. // Loop re-order to be (k, i, j) as j ordering is contiguous. for (k, rhs_pauli_column) in self.pauli_columns.iter().enumerate() { for i in 0..size { - let mut x = pauli_columns[k].x.write().unwrap(); - let mut z = pauli_columns[k].z.write().unwrap(); - *x ^= BitVec::repeat(rhs_pauli_column.x(i), 2 * size) - & lhs.pauli_columns[i].x.read().unwrap().as_bitslice(); + let column = &mut pauli_columns[k]; + let x = &mut column.x; + let z = &mut column.z; + *x ^= BitVec::repeat(rhs_pauli_column.x(i), 2 * size) & &lhs.pauli_columns[i].x; *x ^= BitVec::repeat(rhs_pauli_column.x(i + size), 2 * size) - & lhs.pauli_columns[i].z.read().unwrap().as_bitslice(); - *z ^= BitVec::repeat(rhs_pauli_column.z(i), 2 * size) - & lhs.pauli_columns[i].x.read().unwrap().as_bitslice(); + & &lhs.pauli_columns[i].z; + *z ^= BitVec::repeat(rhs_pauli_column.z(i), 2 * size) & &lhs.pauli_columns[i].x; *z ^= BitVec::repeat(rhs_pauli_column.z(i + size), 2 * size) - & lhs.pauli_columns[i].z.read().unwrap().as_bitslice(); + & &lhs.pauli_columns[i].z; } } @@ -139,10 +138,8 @@ impl CliffordTableau { // Contribution of combination of signs in rhs basis. // Calculate matrix vector M(lhs) * sign(rhs) for (j, lhs_pauli_column) in lhs.pauli_columns.iter().enumerate() { - new_signs ^= BitVec::repeat(self.signs[j], 2 * size) - & lhs_pauli_column.x.read().unwrap().as_bitslice(); - new_signs ^= BitVec::repeat(self.signs[j + size], 2 * size) - & lhs_pauli_column.z.read().unwrap().as_bitslice(); + new_signs ^= BitVec::repeat(self.signs[j], 2 * size) & &lhs_pauli_column.x; + new_signs ^= BitVec::repeat(self.signs[j + size], 2 * size) & &lhs_pauli_column.z; } // Get rid of `i` factors and convert to sign flips @@ -185,7 +182,7 @@ impl HasAdjoint for CliffordTableau { let size = self.size(); // Create new CliffordTableau entries - let new_columns = vec![PauliString::from_text(&"I".repeat(2 * size)); size]; + let mut new_columns = vec![PauliString::from_text(&"I".repeat(2 * size)); size]; (0..size).for_each(|i| { for (j, pauli_column) in self.pauli_columns.iter().enumerate() { let ((x1, z1), (x2, z2)) = reverse_flow( @@ -195,8 +192,9 @@ impl HasAdjoint for CliffordTableau { pauli_column.z(i + size), ); - let mut x = new_columns[i].x.write().unwrap(); - let mut z = new_columns[i].z.write().unwrap(); + let new_column = &mut new_columns[i]; + let x = &mut new_column.x; + let z = &mut new_column.z; x.replace(j, x1); z.replace(j, z1); x.replace(j + size, x2); @@ -250,10 +248,10 @@ impl PropagateClifford for CliffordTableau { .unwrap(); let mut scratch = BitVec::repeat(true, 2 * n); - scratch ^= target.x.read().unwrap().as_bitslice(); - scratch ^= control.z.read().unwrap().as_bitslice(); - scratch &= control.x.read().unwrap().as_bitslice(); - scratch &= target.z.read().unwrap().as_bitslice(); + scratch ^= &target.x; + scratch ^= &control.z; + scratch &= &control.x; + scratch &= &target.z; self.signs ^= scratch; cx(control, target); diff --git a/synir/src/data_structures/pauli_polynomial.rs b/synir/src/data_structures/pauli_polynomial.rs index 3f1e4b17..ff38897b 100644 --- a/synir/src/data_structures/pauli_polynomial.rs +++ b/synir/src/data_structures/pauli_polynomial.rs @@ -1,4 +1,4 @@ -use std::{iter::zip, sync::RwLock}; +use std::iter::zip; use bitvec::vec::BitVec; use itertools::zip_eq; @@ -8,23 +8,13 @@ use super::{pauli_string::PauliString, IndexType, MaskedPropagateClifford, Propa // todo: Make this into a union / type Angle type Angle = f64; -#[derive(Debug, Default)] +#[derive(Debug, Clone, Default)] pub struct PauliPolynomial { chains: Vec, - angles: RwLock>, + angles: Vec, size: usize, } -impl Clone for PauliPolynomial { - fn clone(&self) -> Self { - PauliPolynomial { - chains: self.chains.clone(), - angles: RwLock::new(self.angles.read().unwrap().clone()), - size: self.size, - } - } -} - impl PauliPolynomial { pub fn from_hamiltonian(hamiltonian_representation: Vec<(&str, Angle)>) -> Self { assert!(!hamiltonian_representation.is_empty()); @@ -48,7 +38,7 @@ impl PauliPolynomial { PauliPolynomial { chains, - angles: RwLock::new(angles), + angles, size: num_qubits, } } @@ -58,7 +48,11 @@ impl PauliPolynomial { } pub fn length(&self) -> usize { - self.angles.read().unwrap().len() + self.angles.len() + } + + pub fn chain(&self, i: usize) -> &PauliString { + &self.chains[i] } pub fn chains(&self) -> &Vec { @@ -66,7 +60,7 @@ impl PauliPolynomial { } pub fn angle(&self, i: usize) -> Angle { - self.angles.read().unwrap()[i] + self.angles[i] } } @@ -76,13 +70,13 @@ impl PropagateClifford for PauliPolynomial { let [control, target] = self.chains.get_disjoint_mut([control, target]).unwrap(); - bit_mask ^= control.z.read().unwrap().as_bitslice(); - bit_mask ^= target.x.read().unwrap().as_bitslice(); - bit_mask &= control.x.read().unwrap().as_bitslice(); - bit_mask &= target.z.read().unwrap().as_bitslice(); + bit_mask ^= &control.z; + bit_mask ^= &target.x; + bit_mask &= &control.x; + bit_mask &= &target.z; super::pauli_string::cx(control, target); - for (angle, flip) in zip(self.angles.write().unwrap().iter_mut(), bit_mask.iter()) { + for (angle, flip) in zip(self.angles.iter_mut(), bit_mask.iter()) { if *flip { *angle *= -1.0; } @@ -95,7 +89,7 @@ impl PropagateClifford for PauliPolynomial { let chains_target = self.chains.get_mut(target).unwrap(); // Update angles let y_vec = chains_target.y_bitmask(); - for (angle, flip) in zip(self.angles.write().unwrap().iter_mut(), y_vec.iter()) { + for (angle, flip) in zip(self.angles.iter_mut(), y_vec.iter()) { if *flip { *angle *= -1.0; } @@ -109,7 +103,7 @@ impl PropagateClifford for PauliPolynomial { chains_target.v(); // Update angles let y_vec = chains_target.y_bitmask(); - for (angle, flip) in zip(self.angles.write().unwrap().iter_mut(), y_vec.iter()) { + for (angle, flip) in zip(self.angles.iter_mut(), y_vec.iter()) { if *flip { *angle *= -1.0; } @@ -119,20 +113,18 @@ impl PropagateClifford for PauliPolynomial { } impl MaskedPropagateClifford for PauliPolynomial { - fn masked_cx(&self, control: IndexType, target: IndexType, mask: &BitVec) -> &Self { - let mut bit_mask = BitVec::repeat(true, self.angles.read().unwrap().len()); - // let [control, target] = self.chains.get_many([control, target]).unwrap(); - let control = self.chains.get(control).unwrap(); - let target = self.chains.get(target).unwrap(); - - bit_mask ^= control.z.read().unwrap().as_bitslice(); - bit_mask ^= target.x.read().unwrap().as_bitslice(); - bit_mask &= control.x.read().unwrap().as_bitslice(); - bit_mask &= target.z.read().unwrap().as_bitslice(); + fn masked_cx(&mut self, control: IndexType, target: IndexType, mask: &BitVec) -> &mut Self { + let mut bit_mask = BitVec::repeat(true, self.length()); + let [control, target] = self.chains.get_disjoint_mut([control, target]).unwrap(); + + bit_mask ^= &control.z; + bit_mask ^= &target.x; + bit_mask &= &control.x; + bit_mask &= &target.z; bit_mask &= mask; super::pauli_string::masked_cx(control, target, mask); - for (angle, flip) in zip(self.angles.write().unwrap().iter_mut(), bit_mask.iter()) { + for (angle, flip) in zip(self.angles.iter_mut(), bit_mask.iter()) { if *flip { *angle *= -1.0; } @@ -141,12 +133,12 @@ impl MaskedPropagateClifford for PauliPolynomial { self } - fn masked_s(&self, target: IndexType, mask: &BitVec) -> &Self { - let chains_target = self.chains.get(target).unwrap(); + fn masked_s(&mut self, target: IndexType, mask: &BitVec) -> &mut Self { + let chains_target = &mut self.chains[target]; // Update angles let y_vec = chains_target.masked_y_bitmask(mask); - for (angle, flip) in zip(self.angles.write().unwrap().iter_mut(), y_vec.iter()) { + for (angle, flip) in zip(self.angles.iter_mut(), y_vec.iter()) { if *flip { *angle *= -1.0; } @@ -155,12 +147,12 @@ impl MaskedPropagateClifford for PauliPolynomial { self } - fn masked_v(&self, target: IndexType, mask: &BitVec) -> &Self { - let chains_target = self.chains.get(target).unwrap(); + fn masked_v(&mut self, target: IndexType, mask: &BitVec) -> &mut Self { + let chains_target = &mut self.chains[target]; chains_target.masked_v(mask); // Update angles let y_vec = chains_target.masked_y_bitmask(mask); - for (angle, flip) in zip(self.angles.write().unwrap().iter_mut(), y_vec.iter()) { + for (angle, flip) in zip(self.angles.iter_mut(), y_vec.iter()) { if *flip { *angle *= -1.0; } @@ -174,8 +166,7 @@ mod tests { impl PartialEq for PauliPolynomial { fn eq(&self, other: &Self) -> bool { - self.chains == other.chains - && *self.angles.read().unwrap() == *other.angles.read().unwrap() + self.chains == other.chains && self.angles == other.angles } } @@ -194,7 +185,7 @@ mod tests { let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref, pg4_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -222,7 +213,7 @@ mod tests { let angles_ref = vec![0.3, 0.7, 0.12]; PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, } } @@ -248,7 +239,7 @@ mod tests { let angles_ref = vec![0.3, -0.7, -0.12]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -273,7 +264,7 @@ mod tests { let angles_ref = vec![-0.3, 0.7, 0.12]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -298,7 +289,7 @@ mod tests { let angles_ref = vec![0.3, 0.7, 0.12]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -323,7 +314,7 @@ mod tests { let angles_ref = vec![-0.3, -0.7, 0.12]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -348,7 +339,7 @@ mod tests { let angles_ref = vec![0.3, -0.7, -0.12]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -371,7 +362,7 @@ mod tests { PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, } } @@ -397,7 +388,7 @@ mod tests { let angles_ref = vec![0.3, 0.7, 0.12, 0.15]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -423,7 +414,7 @@ mod tests { let angles_ref = vec![0.3, 0.7, 0.12, -0.15]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -449,7 +440,7 @@ mod tests { let angles_ref = vec![0.3, 0.7, -0.12, 0.15]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -475,7 +466,7 @@ mod tests { let angles_ref = vec![0.3, 0.7, 0.12, 0.15]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -502,7 +493,7 @@ mod tests { let angles_ref = vec![0.3, 0.7, 0.12, 0.15]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -528,7 +519,7 @@ mod tests { let angles_ref = vec![0.3, 0.7, -0.12, 0.15]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -554,7 +545,7 @@ mod tests { let angles_ref = vec![0.3, -0.7, 0.12, 0.15]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); @@ -580,7 +571,7 @@ mod tests { let angles_ref = vec![0.3, 0.7, 0.12, 0.15]; let pp_ref = PauliPolynomial { chains: vec![pg1_ref, pg2_ref, pg3_ref], - angles: RwLock::new(angles_ref), + angles: angles_ref, size, }; assert_eq!(pp, pp_ref); diff --git a/synir/src/data_structures/pauli_string.rs b/synir/src/data_structures/pauli_string.rs index 69a143b8..6b1fd7d8 100644 --- a/synir/src/data_structures/pauli_string.rs +++ b/synir/src/data_structures/pauli_string.rs @@ -1,32 +1,13 @@ use bitvec::{prelude::BitVec, slice::BitSlice}; use std::fmt; use std::iter::zip; -use std::sync::RwLock; use super::PauliLetter; -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct PauliString { - pub(super) x: RwLock, - pub(super) z: RwLock, -} - -impl PartialEq for PauliString { - fn eq(&self, other: &Self) -> bool { - *self.x.read().unwrap() == *other.x.read().unwrap() - && *self.z.read().unwrap() == *other.z.read().unwrap() - } -} - -impl Eq for PauliString {} - -impl Clone for PauliString { - fn clone(&self) -> Self { - PauliString { - x: RwLock::new(self.x.read().unwrap().clone()), - z: RwLock::new(self.z.read().unwrap().clone()), - } - } + pub(super) x: BitVec, + pub(super) z: BitVec, } impl PauliString { @@ -34,8 +15,8 @@ impl PauliString { pub fn new(pauli_x: BitVec, pauli_z: BitVec) -> Self { assert_eq!(pauli_x.len(), pauli_z.len()); PauliString { - x: RwLock::new(pauli_x), - z: RwLock::new(pauli_z), + x: pauli_x, + z: pauli_z, } } @@ -69,11 +50,11 @@ impl PauliString { } pub fn x(&self, i: usize) -> bool { - self.x.read().unwrap()[i] + self.x[i] } pub fn z(&self, i: usize) -> bool { - self.z.read().unwrap()[i] + self.z[i] } pub fn pauli(&self, i: usize) -> PauliLetter { @@ -81,82 +62,82 @@ impl PauliString { } pub fn len(&self) -> usize { - self.x.read().unwrap().len() + self.x.len() } pub fn is_empty(&self) -> bool { - self.x.read().unwrap().is_empty() + self.x.is_empty() } - pub(crate) fn s(&self) { - *self.z.write().unwrap() ^= self.x.read().unwrap().as_bitslice(); + pub(crate) fn s(&mut self) { + self.z ^= &self.x; } - pub(crate) fn masked_s(&self, mask: &BitSlice) { + pub(crate) fn masked_s(&mut self, mask: &BitSlice) { let mut mask = mask.to_owned(); - mask &= self.x.read().unwrap().as_bitslice(); - *self.z.write().unwrap() ^= &mask; + mask &= &self.x; + self.z ^= &mask; } - pub(crate) fn v(&self) { - *self.x.write().unwrap() ^= self.z.read().unwrap().as_bitslice(); + pub(crate) fn v(&mut self) { + self.x ^= &self.z; } - pub(crate) fn masked_v(&self, mask: &BitSlice) { + pub(crate) fn masked_v(&mut self, mask: &BitSlice) { let mut mask = mask.to_owned(); - mask &= self.z.read().unwrap().as_bitslice(); - *self.x.write().unwrap() ^= &mask; + mask &= &self.z; + self.x ^= &mask; } #[allow(dead_code)] - pub(crate) fn h(&self) { - std::mem::swap(&mut *self.x.write().unwrap(), &mut *self.z.write().unwrap()); + pub(crate) fn h(&mut self) { + std::mem::swap(&mut self.x, &mut self.z); } #[allow(dead_code)] - pub(crate) fn masked_h(&self, mask: &BitSlice) { + pub(crate) fn masked_h(&mut self, mask: &BitSlice) { let mut mask = mask.to_owned(); - *self.x.write().unwrap() ^= self.z.read().unwrap().as_bitslice(); - mask &= self.x.read().unwrap().as_bitslice(); - *self.z.write().unwrap() ^= &mask; - *self.x.write().unwrap() ^= self.z.read().unwrap().as_bitslice(); + self.x ^= &self.z; + mask &= &self.x; + self.z ^= &mask; + self.x ^= &self.z; } pub(crate) fn y_bitmask(&self) -> BitVec { - let mut mask = self.x.read().unwrap().clone(); - mask &= self.z.read().unwrap().as_bitslice(); + let mut mask = self.x.clone(); + mask &= &self.z; mask } pub(crate) fn masked_y_bitmask(&self, mask: &BitSlice) -> BitVec { let mut mask = mask.to_owned(); - mask &= self.x.read().unwrap().as_bitslice(); - mask &= self.z.read().unwrap().as_bitslice(); + mask &= &self.x; + mask &= &self.z; mask } } -pub(crate) fn cx(control: &PauliString, target: &PauliString) { +pub(crate) fn cx(control: &mut PauliString, target: &mut PauliString) { assert_eq!(control.len(), target.len()); - *target.x.write().unwrap() ^= control.x.read().unwrap().as_bitslice(); - *control.z.write().unwrap() ^= target.z.read().unwrap().as_bitslice(); + target.x ^= &control.x; + control.z ^= &target.z; } -pub(crate) fn masked_cx(control: &PauliString, target: &PauliString, mask: &BitSlice) { +pub(crate) fn masked_cx(control: &mut PauliString, target: &mut PauliString, mask: &BitSlice) { assert_eq!(control.len(), target.len()); let mut x_mask = mask.to_owned(); let mut z_mask = mask.to_owned(); - x_mask &= control.x.read().unwrap().as_bitslice(); - z_mask &= target.z.read().unwrap().as_bitslice(); - *target.x.write().unwrap() ^= &x_mask; - *control.z.write().unwrap() ^= &z_mask; + x_mask &= &control.x; + z_mask &= &target.z; + target.x ^= &x_mask; + control.z ^= &z_mask; } impl fmt::Display for PauliString { // This trait requires `fmt` with this exact signature. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut pauli_str = String::new(); - for (x, z) in zip(self.x.read().unwrap().iter(), self.z.read().unwrap().iter()) { + for (x, z) in zip(&self.x, &self.z) { match (*x, *z) { (false, false) => pauli_str.push('I'), (false, true) => pauli_str.push('Z'), @@ -182,8 +163,8 @@ mod tests { let length = 5; let paulivec = PauliString::from_basis_int(i, length); - assert!(paulivec.x.read().unwrap().get(i).unwrap()); - assert!(paulivec.z.read().unwrap().get(i + length).unwrap()); + assert!(paulivec.x(i)); + assert!(paulivec.z(i + length)); } #[test] @@ -200,8 +181,8 @@ mod tests { let paulivec = PauliString::from_text(pauli_string); let x_ref = bitvec![0, 1, 1, 0]; let z_ref = bitvec![0, 0, 1, 1]; - assert_eq!(paulivec.x.read().unwrap().as_bitslice(), &x_ref); - assert_eq!(paulivec.z.read().unwrap().as_bitslice(), &z_ref); + assert_eq!(paulivec.x, x_ref); + assert_eq!(paulivec.z, z_ref); } #[test] @@ -218,7 +199,7 @@ mod tests { #[test] fn test_pauli_string_s() { - let paulivec = PauliString::from_text("IXYZ"); + let mut paulivec = PauliString::from_text("IXYZ"); paulivec.s(); let paulivec_ref = PauliString::from_text("IYXZ"); @@ -227,7 +208,7 @@ mod tests { #[test] fn test_pauli_string_v() { - let paulivec = PauliString::from_text("IXYZ"); + let mut paulivec = PauliString::from_text("IXYZ"); paulivec.v(); let paulivec_ref = PauliString::from_text("IXZY"); @@ -236,7 +217,7 @@ mod tests { #[test] fn test_pauli_string_h() { - let paulivec = PauliString::from_text("IXYZ"); + let mut paulivec = PauliString::from_text("IXYZ"); paulivec.h(); let paulivec_ref = PauliString::from_text("IZYX"); @@ -245,7 +226,7 @@ mod tests { #[test] fn test_pauli_string_masked_s() { - let paulivec = PauliString::from_text("IXYZIXYZ"); + let mut paulivec = PauliString::from_text("IXYZIXYZ"); let mask = bits![usize, Lsb0; 0, 0, 0, 0, 1, 1, 1, 1]; paulivec.masked_s(mask); let paulivec_ref = PauliString::from_text("IXYZIYXZ"); @@ -255,7 +236,7 @@ mod tests { #[test] fn test_pauli_string_masked_v() { - let paulivec = PauliString::from_text("IXYZIXYZ"); + let mut paulivec = PauliString::from_text("IXYZIXYZ"); let mask = bits![usize, Lsb0; 0, 0, 0, 0, 1, 1, 1, 1]; paulivec.masked_v(mask); let paulivec_ref = PauliString::from_text("IXYZIXZY"); @@ -265,7 +246,7 @@ mod tests { #[test] fn test_pauli_string_masked_h() { - let paulivec = PauliString::from_text("IXYZIXYZ"); + let mut paulivec = PauliString::from_text("IXYZIXYZ"); let mask = bits![usize, Lsb0; 0, 0, 0, 0, 1, 1, 1, 1]; paulivec.masked_h(mask); let paulivec_ref = PauliString::from_text("IXYZIZYX"); @@ -275,9 +256,9 @@ mod tests { #[test] fn test_pauli_string_cx() { - let control = PauliString::from_text("IIIIXXXXYYYYZZZZ"); - let target = PauliString::from_text("IXYZIXYZIXYZIXYZ"); - cx(&control, &target); + let mut control = PauliString::from_text("IIIIXXXXYYYYZZZZ"); + let mut target = PauliString::from_text("IXYZIXYZIXYZIXYZ"); + cx(&mut control, &mut target); let control_ref = PauliString::from_text("IIZZXXYYYYXXZZII"); let target_ref = PauliString::from_text("IXYZXIZYXIZYIXYZ"); @@ -287,10 +268,10 @@ mod tests { #[test] fn test_pauli_string_masked_cx() { - let control = PauliString::from_text("IIIIXXXXYYYYZZZZIIIIXXXXYYYYZZZZ"); - let target = PauliString::from_text("IXYZIXYZIXYZIXYZIXYZIXYZIXYZIXYZ"); + let mut control = PauliString::from_text("IIIIXXXXYYYYZZZZIIIIXXXXYYYYZZZZ"); + let mut target = PauliString::from_text("IXYZIXYZIXYZIXYZIXYZIXYZIXYZIXYZ"); let mask = bits![usize, Lsb0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; - masked_cx(&control, &target, mask); + masked_cx(&mut control, &mut target, mask); let control_ref = PauliString::from_text("IIIIXXXXYYYYZZZZIIZZXXYYYYXXZZII"); let target_ref = PauliString::from_text("IXYZIXYZIXYZIXYZIXYZXIZYXIZYIXYZ"); diff --git a/synir/src/ir/pauli_polynomial/helper.rs b/synir/src/ir/pauli_polynomial/helper.rs index 73e30474..127f5ad1 100644 --- a/synir/src/ir/pauli_polynomial/helper.rs +++ b/synir/src/ir/pauli_polynomial/helper.rs @@ -35,9 +35,9 @@ impl PropagateClifford for VecDeque { } impl MaskedPropagateClifford for VecDeque { - fn masked_cx(&self, control: usize, target: usize, mask: &BitVec) -> &Self { + fn masked_cx(&mut self, control: usize, target: usize, mask: &BitVec) -> &mut Self { self[0].masked_cx(control, target, mask); - for pauli_polynomial in self.iter().skip(1) { + for pauli_polynomial in self.iter_mut().skip(1) { pauli_polynomial.masked_cx( control, target, @@ -47,17 +47,17 @@ impl MaskedPropagateClifford for VecDeque { self } - fn masked_s(&self, target: usize, mask: &BitVec) -> &Self { + fn masked_s(&mut self, target: usize, mask: &BitVec) -> &mut Self { self[0].masked_s(target, mask); - for pauli_polynomial in self.iter().skip(1) { + for pauli_polynomial in self.iter_mut().skip(1) { pauli_polynomial.masked_s(target, &bitvec![usize, Lsb0; 1; pauli_polynomial.length()]); } self } - fn masked_v(&self, target: usize, mask: &BitVec) -> &Self { + fn masked_v(&mut self, target: usize, mask: &BitVec) -> &mut Self { self[0].masked_v(target, mask); - for pauli_polynomial in self.iter().skip(1) { + for pauli_polynomial in self.iter_mut().skip(1) { pauli_polynomial.masked_v(target, &bitvec![usize, Lsb0; 1; pauli_polynomial.length()]); } self @@ -68,7 +68,7 @@ pub(super) fn push_down_pauli_polynomial_update( pauli_polynomials: &mut VecDeque, repr: &mut G, clifford_tableau: &mut CliffordTableau, - pauli_polynomial: PauliPolynomial, + mut pauli_polynomial: PauliPolynomial, num_gadgets: usize, mut mask: BitVec, ) where @@ -76,7 +76,8 @@ pub(super) fn push_down_pauli_polynomial_update( { for col in 0..num_gadgets { let mut affected_qubits = Vec::new(); - for (i, row) in pauli_polynomial.chains().iter().enumerate() { + for i in 0..pauli_polynomial.size() { + let row = pauli_polynomial.chain(i); match row.pauli(col) { PauliLetter::I => {} PauliLetter::X => {