Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
748685d
Add helper function in PauliString to calculate hamming weight
Jul 4, 2025
80898a7
Update connectivity to fix unintended behavior
Jul 4, 2025
b9fd2c7
Correct pivot selection for custom callback
Jul 4, 2025
f1d3cbf
Add helper functions for PermRowCol
Jul 4, 2025
ce3de00
Implement PermRowCol for CliffordTableau
Jul 4, 2025
2daa86d
Add tests for PermRowCol for CliffordTableau
Jul 4, 2025
cd47a94
Update benchmark code
Jul 4, 2025
67c388e
Remove unused import
Jul 4, 2025
4004b86
Remove println statement
Jul 4, 2025
735acfa
Remove unused imports and print statements
Jul 4, 2025
220fa3f
Add more PauliString and PauliPolynomial helper functions
Aug 6, 2025
dac6380
Shift pauli checks up one folder level to allow all synthesis methods…
Aug 6, 2025
5793804
Implement PSGS strategy for PauliPolynomials
Aug 6, 2025
218d9d8
Add tests for PSGS implementation, extend synthesis method enum to in…
Aug 6, 2025
5cd6480
Update Cargo.lock
Aug 6, 2025
5394668
Remove uneeded references, return calls and imports
Aug 14, 2025
a2d0f1d
Reformat docs
Aug 14, 2025
65632e8
Add helper function in PauliString to calculate hamming weight
Jul 4, 2025
2738ac0
Correct pivot selection for custom callback
Jul 4, 2025
b4b2257
Add tests for PermRowCol for CliffordTableau
Jul 4, 2025
0e57fdc
Remove unused import
Jul 4, 2025
6c4fccc
Rename edge_ and node_bound to edge_ and node_count
Sep 20, 2025
b19a5aa
Replace clean_naive_pivot with clean_pivot
Oct 6, 2025
1fcaa69
Add PermRowCol as strategy in pauli_exponential.rs
Oct 6, 2025
fc2f652
Add ability to modify row and column selection strategy for PermRowCo…
Oct 6, 2025
28ba059
test refactor
Aerylia Oct 15, 2025
b9698ac
Rebase on main
Oct 29, 2025
bd26205
Implement tests from Cowtan, fix sign flip error
Nov 4, 2025
647fd96
Remove CliffordTableau from PauliPolynomialSynthesizers
Nov 4, 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
506 changes: 506 additions & 0 deletions src/ir/clifford_tableau/helper.rs

Large diffs are not rendered by default.

150 changes: 150 additions & 0 deletions src/ir/clifford_tableau/permrowcol.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
use std::fmt::Debug;

use crate::{
architecture::connectivity::Connectivity,
data_structures::{CliffordTableau, PauliLetter},
ir::{
clifford_tableau::helper::{clean_pivot, clean_prc, pick_column, pick_row},
AdjointSynthesizer, CliffordGates,
},
};

use super::helper::clean_signs;

// #[derive(Default)]
pub struct PermRowColCliffordSynthesizer {
connectivity: Connectivity,
permutation: Vec<usize>,
row_strategy: fn(&CliffordTableau, &Connectivity, &[usize]) -> usize,
column_strategy: fn(&CliffordTableau, &Connectivity) -> usize,
}

impl Default for PermRowColCliffordSynthesizer {
fn default() -> Self {
PermRowColCliffordSynthesizer {
connectivity: Connectivity::default(),
permutation: Vec::<usize>::default(),
row_strategy: pick_row,
column_strategy: pick_column,
}
}
}

impl PermRowColCliffordSynthesizer {
pub fn new(connectivity: Connectivity) -> Self {
let size = connectivity.node_count();

Self {
connectivity,
permutation: (0..size).collect(),
row_strategy: pick_row,
column_strategy: pick_column,
}
}

pub fn permutation(&self) -> &[usize] {
&self.permutation
}

pub fn set_row_strategy(
&mut self,
row_strategy: fn(&CliffordTableau, &Connectivity, &[usize]) -> usize,
) {
(self.row_strategy) = row_strategy;
}

pub fn set_column_strategy(
&mut self,
column_strategy: fn(&CliffordTableau, &Connectivity) -> usize,
) {
(self.column_strategy) = column_strategy;
}
}

impl<G> AdjointSynthesizer<CliffordTableau, G> for PermRowColCliffordSynthesizer
where
G: CliffordGates,
{
fn synthesize_adjoint(&mut self, mut clifford_tableau: CliffordTableau, repr: &mut G) {
let num_qubits = clifford_tableau.size();
let machine_size = self.connectivity.node_count();
assert!(
num_qubits <= machine_size,
"Number of qubits {} exceeds machine size {}",
num_qubits,
machine_size
);
// Mapping between logical qubit to physical qubit
let mut permutation = (0..num_qubits).collect::<Vec<_>>();
// logical qubit remaining to be disconnected
let mut remaining_columns = (0..num_qubits).collect::<Vec<_>>();
// stabilizers / destabilizers that are not yet identity rows
let mut remaining_rows = (0..num_qubits).collect::<Vec<_>>();

while !remaining_columns.is_empty() {
let pivot_row =
(self.row_strategy)(&clifford_tableau, &self.connectivity, &remaining_rows);
let pivot_column = (self.column_strategy)(&clifford_tableau, &self.connectivity);
let column = clifford_tableau.column(pivot_column);
let x_weight = column.x_weight();
let z_weight = column.z_weight();

let (first_letter, second_letter) = if z_weight > x_weight {
(PauliLetter::Z, PauliLetter::X)
} else {
(PauliLetter::X, PauliLetter::Z)
};

remaining_columns.retain(|&x| x != pivot_column);
remaining_rows.retain(|&x| x != pivot_row);
{
clean_pivot(
repr,
&mut clifford_tableau,
pivot_column,
pivot_row,
first_letter,
);

// Use the pivot to remove all other terms in the X observable.
clean_prc(
repr,
&mut clifford_tableau,
&self.connectivity,
&remaining_columns,
pivot_column,
pivot_row,
first_letter,
);

clean_pivot(
repr,
&mut clifford_tableau,
pivot_column,
pivot_row,
second_letter,
);

// Use the pivot to remove all other terms in the Z observable.
clean_prc(
repr,
&mut clifford_tableau,
&self.connectivity,
&remaining_columns,
pivot_column,
pivot_row,
second_letter,
);
}

// If the pivot row is now an identity row, we can remove it from the tableau.

permutation[pivot_row] = pivot_column;
self.connectivity.remove_node(pivot_column);
}

clean_signs(repr, &mut clifford_tableau, &permutation);

self.permutation = permutation;
}
}
35 changes: 35 additions & 0 deletions src/ir/helper.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::data_structures::PauliLetter;

#[allow(dead_code)]
pub(super) fn is_i(pauli_letter: PauliLetter) -> bool {
pauli_letter == PauliLetter::I
}

pub(super) fn is_not_i(pauli_letter: PauliLetter) -> bool {
pauli_letter != PauliLetter::I
}

pub(super) fn is_x(pauli_letter: PauliLetter) -> bool {
pauli_letter == PauliLetter::X
}

pub(super) fn is_not_x(pauli_letter: PauliLetter) -> bool {
pauli_letter != PauliLetter::X
}

pub(super) fn is_y(pauli_letter: PauliLetter) -> bool {
pauli_letter == PauliLetter::Y
}

#[allow(dead_code)]
pub(super) fn is_not_y(pauli_letter: PauliLetter) -> bool {
pauli_letter != PauliLetter::Y
}

pub(super) fn is_z(pauli_letter: PauliLetter) -> bool {
pauli_letter == PauliLetter::Z
}

pub(super) fn is_not_z(pauli_letter: PauliLetter) -> bool {
pauli_letter != PauliLetter::Z
}
2 changes: 0 additions & 2 deletions synir/benches/clifford_tableau.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ use synir::ir::CliffordGates;
use synir::ir::Synthesizer;
use synir::IndexType;

mod connectivity;

#[derive(Debug, Default)]
pub struct MockCircuit {
commands: Vec<MockCommand>,
Expand Down
2 changes: 1 addition & 1 deletion synir/src/architecture/connectivity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn get_non_cutting_vertices(
.collect()
}

#[derive(Debug)]
#[derive(Debug, Default)]
pub struct Connectivity {
graph: StableUnGraph<NodeWeight, EdgeWeight, GraphIndex>,
non_cutting: Vec<GraphIndex>,
Expand Down
2 changes: 2 additions & 0 deletions synir/src/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub use clifford_tableau::CliffordTableau;
pub use pauli_polynomial::PauliPolynomial;
pub use pauli_string::PauliString;

pub type Angle = f64;

pub trait HasAdjoint {
fn adjoint(&self) -> Self;
}
Expand Down
Loading
Loading