Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d6e74ea
add some method for visualization of tableaus and pp
tungbuidang Aug 12, 2025
6028ad2
add visualization to pauli polynomial
tungbuidang Aug 13, 2025
6427129
clean up the logic for visualization
tungbuidang Aug 18, 2025
9892c69
remove unnecessary getter setter method
tungbuidang Aug 18, 2025
64d257c
added visualization to data structure in examples folder
tungbuidang Aug 18, 2025
465b330
fix some issue from pull request comments
tungbuidang Aug 20, 2025
10137fe
fix example to fit visualization case
tungbuidang Aug 21, 2025
53e4037
fix logic to true assign to - sign and false to + sign
tungbuidang Aug 21, 2025
1dab1df
add example and test for pauli polynomial
tungbuidang Aug 21, 2025
be06cdc
clean up and add Display trait to pe
tungbuidang Aug 22, 2025
633158a
clean up and add Display trait to pe
tungbuidang Aug 22, 2025
e63f18b
remove unnecessary method, make display for pp a bit more efficient b…
tungbuidang Aug 22, 2025
5da88f3
Merge remote-tracking branch 'origin' into 41-visualization
tungbuidang Aug 27, 2025
ff9d3bc
change Display function to use pauli letter instead of to_string method
tungbuidang Aug 29, 2025
0b5d2d4
Merge remote-tracking branch 'origin' into 41-visualization
tungbuidang Sep 1, 2025
2c4bce9
changed name of examples file to better match its functionality
tungbuidang Sep 1, 2025
ffe6f30
change compose function to test if python build can pass. The compile…
tungbuidang Sep 1, 2025
8eae13b
rewrite clifford tableaus Display trait to correctly print row and co…
tungbuidang Sep 2, 2025
b739ca7
update test
tungbuidang Sep 2, 2025
d0aa460
change clifford tableau display trait to use string construction, for…
tungbuidang Sep 2, 2025
ff982f1
update test
tungbuidang Sep 2, 2025
2f9c90a
fix tableaux because French
tungbuidang Sep 2, 2025
705cf68
added new display for Pauli Exponential
tungbuidang Sep 4, 2025
f7b8a55
support multi pauli polynomials printing for pauli exponential
tungbuidang Sep 10, 2025
367d185
fix pauli exponential display to not show multiple 'QB' column
tungbuidang Sep 10, 2025
832716f
add logic to correctly format clifford tableaux for big case. Also cl…
tungbuidang Sep 10, 2025
e5694c4
support print alignment of up to 99 qubits
tungbuidang Sep 11, 2025
695551f
test print empty data structure
tungbuidang Oct 21, 2025
5d0cc53
fix for merge conlfict
tungbuidang Oct 21, 2025
1f0a1e6
swap Stabilizer/Destabilizer
tungbuidang Oct 23, 2025
f9502fe
add print empty for clifford tableau and pauli polynomial
tungbuidang Oct 23, 2025
5a2fa61
fix test to pass build
tungbuidang Oct 23, 2025
26f053c
test display fix
tungbuidang Oct 24, 2025
201ae27
added printing empty logic for all data structures
tungbuidang Oct 24, 2025
1bcbf46
add some edge case for printing empty exponential
tungbuidang Oct 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions examples/plot_data_structure.rs
Comment thread
tungbuidang marked this conversation as resolved.
Outdated
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use std::collections::VecDeque;

use bitvec::bitvec;
use bitvec::prelude::Lsb0;
use syn::data_structures::{CliffordTableau, PauliPolynomial, PauliString};
use syn::ir::pauli_exponential::PauliExponential;

fn main() {
// test tableaus
// Stab: ZZZ, -YIY, XIX
// Destab: -IXI, XXI, IYY

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think these stabilizers and destabilizers correspond ot the tableau you are creating in the code

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed it in the latest commit

// qubit 1x: ZYI
// qubit 1z: IZZ
let pauli_1 = PauliString::from_text("ZYIIZZ");
// qubit 2x: ZIX
// qubit 2z: XII
let pauli_2 = PauliString::from_text("ZIXXII");
// qubit 3x: ZYY
// qubit 3z: IIZ
let pauli_3 = PauliString::from_text("ZYYIIZ");
let signs = bitvec![0, 1, 0, 1, 0, 0];
let my_tableaus = CliffordTableau::from_parts(vec![pauli_1, pauli_2, pauli_3], signs);
Comment thread
tungbuidang marked this conversation as resolved.
Outdated

println!("{}", my_tableaus);

// test pauli polynomial

let ham = vec![("IXYZ", 0.3), ("XXII", 0.7), ("YYII", 0.12)];
let pp = PauliPolynomial::from_hamiltonian(ham);
println!("{}", pp);

// // visualize_pauli_exponential_simple(&pe);
let ham = vec![("IZZZ", 0.3)];
let pp = PauliPolynomial::from_hamiltonian(ham);
let ct = CliffordTableau::new(4);
let pe = PauliExponential::new(VecDeque::from([pp]), ct);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can reuse the pp and tableau from before

println!("{}", pe);

// //visualize_pauli_exponential complex
let ham = vec![("IXYZ", 0.3), ("XXII", 0.7), ("YYII", 0.12)];

let pauli_polynomial = PauliPolynomial::from_hamiltonian(ham);
let clifford_tableau = CliffordTableau::new(4);
let complex_pe = PauliExponential::new(VecDeque::from([pauli_polynomial]), clifford_tableau);
println!("{}", complex_pe);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then this would be redundant

}
71 changes: 58 additions & 13 deletions src/data_structures/clifford_tableau.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use std::fmt;
use std::iter::zip;
use std::ops::Mul;

use crate::data_structures::PauliLetter;

use super::HasAdjoint;
use super::{
pauli_string::{cx, PauliString},
Expand Down Expand Up @@ -41,6 +43,10 @@ impl CliffordTableau {
self.size
}

pub fn signs(&self) -> &BitVec {
&self.signs
}

pub(crate) fn x_signs(&self) -> BitVec {
let n = self.size();
self.signs[0..n].to_bitvec()
Expand All @@ -55,7 +61,7 @@ impl CliffordTableau {
&self.pauli_columns[i]
}

pub fn compose(&self, rhs: &Self) -> Self {
pub(crate) fn compose(&self, rhs: &Self) -> Self {
rhs.prepend(self)
}

Expand Down Expand Up @@ -301,20 +307,59 @@ impl Mul for CliffordTableau {

impl fmt::Display for CliffordTableau {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "CliffordTableau({})", self.size())?;
for pauli_column in self.pauli_columns.iter() {
writeln!(f, "{}", pauli_column)?;
write!(f, " ||")?;
for i in 0..self.size() {
write!(f, " X{} Z{}|", i + 1, i + 1)?;
}
writeln!(f)?;
write!(f, "+/- ||")?;
for (i, sign) in self.signs().iter().enumerate() {
if *sign {
write!(f, " - ")?;
} else {
write!(f, " + ")?;
}
if i % 2 != 0 {
write!(f, "|")?;
}
}
let mut sign_str = String::new();
for bit in self.signs.iter() {
match *bit {
true => sign_str.push('-'),
false => sign_str.push('+'),
writeln!(f)?;

for (i, column) in self.pauli_columns.iter().enumerate() {
write!(f, "QB{} ||", i)?;
let mut out = String::new();
let mut letter_count = 0;
for j in 0..column.len() {
// let letter = column.pauli(j);
match column.pauli(j) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you are printing the tableau transposed. i.e. the columns are printed as rows.

PauliLetter::I => {
out.push('I');
letter_count += 1;
}
PauliLetter::X => {
out.push('X');
letter_count += 1;
}
PauliLetter::Z => {
out.push('Z');
letter_count += 1;
}
PauliLetter::Y => {
out.push('Y');
letter_count += 1;
}
}
if letter_count % 2 == 1 {
out.push(' ');
} else {
out.push_str(" |");
}
out.push(' ');
}
sign_str.push(' ')
out.push('\n');
write!(f, " {}", out)?;
}
sign_str.pop();
write!(f, "{}", sign_str)
writeln!(f)
}
}

Expand Down Expand Up @@ -1194,7 +1239,7 @@ mod tests {
let ct = setup_sample_ct();
assert_eq!(
ct.to_string(),
"CliffordTableau(3)\nZ Y I I Z Z\nZ I X X I I\nZ Y Y I I Z\n+ - + - + +"
" || X1 Z1| X2 Z2| X3 Z3|\n+/- || + - | + - | + + |\nQB0 || Z Y | I I | Z Z | \nQB1 || Z I | X X | I I | \nQB2 || Z Y | Y I | I Z | \n\n"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you are printing the transpose, which was the limitation of the debug formatter because it's easy to print the columns are rows.
Something like this:

"    || Stabilizers | Destabilizers |\n QB0 || + Z Z Z | - I X I | \nQB1 || - Y I Y | + Z I I | \nQB2 || + I X Y | + Z I Z | \n\n"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be correct now

);
}
}
39 changes: 37 additions & 2 deletions src/data_structures/pauli_polynomial.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::{iter::zip, sync::RwLock};

use bitvec::vec::BitVec;
use itertools::zip_eq;
use itertools::Itertools;
use std::fmt;
use std::{iter::zip, sync::RwLock};

use super::{pauli_string::PauliString, IndexType, MaskedPropagateClifford, PropagateClifford};

Expand Down Expand Up @@ -168,6 +169,32 @@ impl MaskedPropagateClifford for PauliPolynomial {
self
}
}

impl fmt::Display for PauliPolynomial {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let angles = self.angles.read().unwrap();
let string_angles = angles
.iter()
.map(|x| format!("{:.3}", x)) //force 3 decimal place for formatting
.join(" | ");
writeln!(f, "Angles | {} |", string_angles)?;
let chains = self.chains();
for (i, pauli) in chains.iter().enumerate() {
write!(f, "Qubit {}|", i)?;
let chain_str = pauli.to_string();
let mut out = String::new();
for ch in chain_str.chars() {
out.push(ch);
if !ch.is_whitespace() {
out.push_str(" |");
}
}
writeln!(f, " {}", out)?;
}
writeln!(f)
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -585,4 +612,12 @@ mod tests {
};
assert_eq!(pp, pp_ref);
}
#[test]
fn test_pauli_polynomial_display() {
let pp = setup_sample_pp();
assert_eq!(
pp.to_string(),
"Angles | 0.300 | 0.700 | 0.120 |\nQubit 0| I | X | Y |\nQubit 1| Z | Y | X |\nQubit 2| Y | I | X |\n\n"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be more consistent with the formatting wrt the tableau. "QB0" vs "Qubit 0".

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

);
}
}
12 changes: 12 additions & 0 deletions src/ir/pauli_exponential.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::VecDeque;
use std::fmt;

use crate::data_structures::{CliffordTableau, HasAdjoint, PauliPolynomial};

Expand Down Expand Up @@ -29,6 +30,17 @@ impl PauliExponential {
}
}

impl fmt::Display for PauliExponential {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "Clifford Tableau: \n{}", self.clifford_tableau)?;
writeln!(f, "Pauli Polynomials:")?;
for (i, pp) in self.pauli_polynomials.iter().enumerate() {
writeln!(f, "Pauli {} ", i)?;
writeln!(f, "{}", pp)?;
}
writeln!(f)
}
}
#[derive(Default)]
pub struct PauliExponentialSynthesizer {
pauli_strategy: PauliPolynomialSynthStrategy,
Expand Down
Loading