Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5d2d7d0
Coercing integer types to floats when appending a PPR to a circuit
alexanderivrii Mar 15, 2026
dff5668
Extending RemoveIdentityEquiv and CommutativeOptimization to handle PPRs
alexanderivrii Mar 15, 2026
49960e1
reno
alexanderivrii Mar 15, 2026
0dde194
Improve commutation checking of PPRs and PPMs
alexanderivrii Mar 15, 2026
4cd1ff4
reno
alexanderivrii Mar 16, 2026
789e1c6
Merge branch 'main' into opt_ppr_ppm_in_cc
alexanderivrii Mar 31, 2026
de13108
canonicalizing PPM instruction as well
alexanderivrii Mar 31, 2026
087362f
faster method based on comparing two sorted vectors
alexanderivrii Mar 31, 2026
08f9fa5
Revert "faster method based on comparing two sorted vectors"
alexanderivrii Apr 1, 2026
1beefa4
moving the efficient check to commutative optimization
alexanderivrii Apr 1, 2026
e45c48a
merge with main
alexanderivrii Apr 3, 2026
6cbce16
More tests for commutations of pauli-based gates
alexanderivrii Apr 3, 2026
b654130
Adding CommutativeOptimization tests
alexanderivrii Apr 3, 2026
d889df0
enforcing PPM & PPR types for sorted checking
alexanderivrii Apr 4, 2026
06cbb55
Replacing vec by hash_map
alexanderivrii Apr 4, 2026
f4a9df6
sorting arguments before pauli-based check
alexanderivrii Apr 4, 2026
b13a58d
Addressing review comments by Janani
alexanderivrii Apr 4, 2026
76a8c74
removing gates equivalent to identity
alexanderivrii Apr 9, 2026
55e93d1
fix to actually simplify the circuit + tests
alexanderivrii Apr 9, 2026
c90835c
merge with main + a few fixes
alexanderivrii Apr 16, 2026
b3e6456
improve commutation checker
alexanderivrii Apr 16, 2026
a685517
updating commutative optimization for PPMs
alexanderivrii Apr 16, 2026
9f7a432
merge with main
alexanderivrii Apr 17, 2026
fb03d53
code cleanup
alexanderivrii Apr 17, 2026
c2c3ca5
typos and comments, following review
alexanderivrii Apr 17, 2026
a669772
combining tests
alexanderivrii Apr 17, 2026
a67a060
Addressing review comments
alexanderivrii Apr 23, 2026
d13a51a
ore review comments
alexanderivrii Apr 23, 2026
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
59 changes: 56 additions & 3 deletions crates/transpiler/src/commutation_checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ fn try_extract_op_from_ppr(
Some(out.compose_map(&local, |i| qubits[i as usize].0))
}

Comment thread
alexanderivrii marked this conversation as resolved.
fn try_pauli_generator(
fn try_sparse_observable_generator(
operation: &OperationRef,
qubits: &[Qubit],
num_qubits: u32,
Expand All @@ -248,6 +248,16 @@ fn try_pauli_generator(
}
}

/// Checks if the generator can be represented as a single Pauli term.
/// If so, returns the generator in the (Z, X) form.
fn try_pauli_generator<'a>(operation: &'a OperationRef) -> Option<(&'a Vec<bool>, &'a Vec<bool>)> {
match operation {
OperationRef::PauliProductRotation(ppr) => Some((&ppr.z, &ppr.x)),
OperationRef::PauliProductMeasurement(ppm) => Some((&ppm.z, &ppm.x)),
_ => None,
}
}

fn get_bits_from_py<T>(
py_bits1: &Bound<'_, PyTuple>,
py_bits2: &Bound<'_, PyTuple>,
Expand Down Expand Up @@ -332,6 +342,7 @@ impl CommutationChecker {
max_num_qubits,
matrix_max_num_qubits,
approximation_degree,
false,
)?)
}

Expand Down Expand Up @@ -364,6 +375,7 @@ impl CommutationChecker {
max_num_qubits,
matrix_max_num_qubits,
approximation_degree,
false,
)?)
}

Expand Down Expand Up @@ -456,6 +468,7 @@ impl CommutationChecker {
max_num_qubits: Option<u32>,
matrix_max_num_qubits: u32,
approximation_degree: f64,
assume_sorted_pp: bool, // true if qubits in PPRs and PPMs cab be assumed to be sorted
Comment thread
alexanderivrii marked this conversation as resolved.
Outdated
) -> Result<bool, CommutationError> {
// If the average gate infidelity is below this tolerance, they commute. The tolerance
// is set to max(1e-12, 1 - approximation_degree), to account for roundoffs and for
Expand Down Expand Up @@ -521,10 +534,50 @@ impl CommutationChecker {
_ => (),
};

if let (Some((z1, x1)), Some((z2, x2))) =
(try_pauli_generator(op1), try_pauli_generator(op2))
{
let mut parity = false;
let mut adjust_parity = |i1: usize, i2: usize| {
parity ^= (x1[i1] && z2[i2]) ^ (z1[i1] && x2[i2]);
};

if assume_sorted_pp {
// The qubits in PPRs and PPMs are known to be sorted by qubit index.
let (n1, n2) = (qargs1.len(), qargs2.len());
let (mut i1, mut i2) = (0, 0);

while i1 < n1 && i2 < n2 {
match qargs1[i1].cmp(&qargs2[i2]) {
std::cmp::Ordering::Less => i1 += 1,
std::cmp::Ordering::Greater => i2 += 1,
std::cmp::Ordering::Equal => {
adjust_parity(i1, i2);
i1 += 1;
i2 += 1;
}
}
}
} else {
// The qubits in PPRs and PPMs are not known to be sorted by qubit index.
let max_q1 = qargs1.iter().map(|q| q.index()).max().unwrap_or(0);
let mut in_q1 = vec![usize::MAX; max_q1 + 1];
for (i, &q) in qargs1.iter().enumerate() {
in_q1[q.index()] = i;
}
for (i2, &q) in qargs2.iter().enumerate() {
if let Some(&i1) = in_q1.get(q.index()).filter(|&&i1| i1 != usize::MAX) {
adjust_parity(i1, i2);
}
}
}
return Ok(!parity);
}

// Handle commutations in between Pauli-based gates, like PauliGate or PauliEvolutionGate
let size = qargs1.iter().chain(qargs2.iter()).max().unwrap().0 + 1;
if let Some(obs1) = try_pauli_generator(op1, qargs1, size) {
if let Some(obs2) = try_pauli_generator(op2, qargs2, size) {
if let Some(obs1) = try_sparse_observable_generator(op1, qargs1, size) {
if let Some(obs2) = try_sparse_observable_generator(op2, qargs2, size) {
return Ok(obs1.commutes(&obs2, tol));
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/transpiler/src/passes/commutation_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ pub fn analyze_commutations(
None,
MAX_NUM_QUBITS,
approximation_degree,
false,
)?;
if !all_commute {
break;
Expand Down
38 changes: 36 additions & 2 deletions crates/transpiler/src/passes/commutative_optimization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use crate::passes::remove_identity_equiv::{average_gate_fidelity_below_tol, is_i
use qiskit_circuit::circuit_instruction::OperationFromPython;
use qiskit_circuit::dag_circuit::DAGCircuit;
use qiskit_circuit::operations::{
Operation, OperationRef, Param, PauliBased, PauliProductRotation, StandardGate, multiply_param,
radd_param,
Operation, OperationRef, Param, PauliBased, PauliProductMeasurement, PauliProductRotation,
StandardGate, multiply_param, radd_param,
};
use qiskit_circuit::{BlocksMode, Clbit, NoBlocks, Qubit, imports};

Expand Down Expand Up @@ -229,6 +229,39 @@ fn canonicalize(
return Some((canonical_instruction, Param::Float(0.)));
}

if let OperationRef::PauliProductMeasurement(ppm) = inst.op.view() {
Comment thread
alexanderivrii marked this conversation as resolved.
let qargs = dag.get_qargs(inst.qubits);
let mut paired = qargs
.iter()
.zip(ppm.z.iter())
.zip(ppm.x.iter())
.map(|((q, z), x)| (q, z, x))
.collect::<Vec<_>>();
paired.sort_by_key(|(q, _, _)| **q);
let (sorted_qargs, sorted_z, sorted_x) =
paired
.into_iter()
.multiunzip::<(Vec<Qubit>, Vec<bool>, Vec<bool>)>();
let sorted_ppm = PauliProductMeasurement {
z: sorted_z,
x: sorted_x,
neg: ppm.neg,
};

let sorted_qubits = dag.add_qargs(&sorted_qargs);

let canonical_instruction = PackedInstruction {
op: PauliBased::PauliProductMeasurement(sorted_ppm).into(),
qubits: sorted_qubits,
clbits: inst.clbits,
params: inst.params.clone(),
label: None,
#[cfg(feature = "cache_pygates")]
py_op: std::sync::OnceLock::new(),
};
return Some((canonical_instruction, Param::Float(0.)));
}

None
}

Expand Down Expand Up @@ -268,6 +301,7 @@ fn commute(
None,
matrix_max_num_qubits,
approximation_degree,
true, // PPRs and PPMs are sorted in canonicalize
)?)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
features_transpiler:
- Improved the performance of commutation checking for :class:`.PauliProductRotationGate` and
:class:`.PauliProductMeasurement`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would we like to mention here very briefly as to what has improved to improve the performance of the commutation checker?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks for the great feedback, Janani! I have addressed and your other review comments in b13a58d.