Skip to content

Commit b43a2f3

Browse files
authored
Correctly enforce matrix size check in CommutationChecker (#15933)
* Fixed the matrix size check for non-cachable gates in the commutation checker. A typo in the matrix size check allowed to sneak into a matrix-based check even if the operations exceeded the maximum matrix size. The operations `first_..` and `second_..` are sorted, but `..1` and `..2` are not! The wrong one was used here. * Reduce test size This test now doesn't rely on the internal path panicking, but still tests the right behavior since the results with and without a matrix check differ.
1 parent 50c18fa commit b43a2f3

3 files changed

Lines changed: 27 additions & 3 deletions

File tree

crates/transpiler/src/commutation_checker.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -569,9 +569,9 @@ impl CommutationChecker {
569569
is_cachable(first_op, first_params) && is_cachable(second_op, second_params);
570570

571571
if !check_cache {
572-
// The arguments are sorted, so if qargs1.len() > matrix_max_num_qubits, then
573-
// qargs1.len() > matrix_max_num_qubits as well.
574-
if qargs2.len() > matrix_max_num_qubits as usize {
572+
// The arguments are sorted, so if first_qargs.len() > matrix_max_num_qubits, then
573+
// second_qargs.len() > matrix_max_num_qubits as well.
574+
if second_qargs.len() > matrix_max_num_qubits as usize {
575575
return Ok(false);
576576
}
577577

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
fixes:
3+
- |
4+
Fixed a bug in :class:`.CommutationChecker` where certain Rust-backed gates, such as
5+
the :class:`.UnitaryGate`, could circumvent the matrix size check and cause the
6+
calculation of large matrices.

test/python/circuit/test_commutation_checker.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,24 @@ def test_approximation_degree(self):
501501
scc.commute(almost_identity, [0], [], other, [0], [], approximation_degree=1 - 1e-4)
502502
)
503503

504+
def test_matrix_threshold_noncachable(self):
505+
"""Test the matrix threshold is obeyed for non-cachable gates."""
506+
num_qubits = 2
507+
big = UnitaryGate(np.eye(2**num_qubits))
508+
qubits = list(range(num_qubits))
509+
other = HGate()
510+
511+
# We check passing args in both orders; [A, B] and [B, A] since the commutation
512+
# checking does some sorting which we want to also test here.
513+
# Since we should skip the test, the commutation should come out to ``False``,
514+
# and only if the matrix check is run (which it shouldn't) this would be ``True``.
515+
self.assertFalse(
516+
scc.commute(big, qubits, [], other, [0], [], matrix_max_num_qubits=num_qubits - 1)
517+
)
518+
self.assertFalse(
519+
scc.commute(other, [0], [], big, qubits, [], matrix_max_num_qubits=num_qubits - 1)
520+
)
521+
504522
@data("pauli", "evolution", "measure")
505523
def test_pauli_based_gates(self, gate_type):
506524
"""Test Pauli-based gates."""

0 commit comments

Comments
 (0)