Skip to content

Commit

Permalink
Fix CC for comparison with rotation gates on angles k*pi (#13399)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cryoris authored Nov 5, 2024
1 parent 185383d commit c7ccbd4
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 16 deletions.
4 changes: 3 additions & 1 deletion crates/accelerate/src/commutation_checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ static SUPPORTED_OP: Lazy<HashSet<&str>> = Lazy::new(|| {
])
});

const TWOPI: f64 = 2.0 * std::f64::consts::PI;

// map rotation gates to their generators, or to ``None`` if we cannot currently efficiently
// represent the generator in Rust and store the commutation relation in the commutation dictionary
static SUPPORTED_ROTATIONS: Lazy<HashMap<&str, Option<OperationRef>>> = Lazy::new(|| {
Expand Down Expand Up @@ -632,7 +634,7 @@ fn map_rotation<'a>(
// commute with everything, and we simply return the operation with the flag that
// it commutes trivially
if let Param::Float(angle) = params[0] {
if (angle % std::f64::consts::PI).abs() < tol {
if (angle % TWOPI).abs() < tol {
return (op, params, true);
};
};
Expand Down
54 changes: 39 additions & 15 deletions test/python/circuit/test_commutation_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from test import QiskitTestCase # pylint: disable=wrong-import-order

import numpy as np
from ddt import data, ddt
from ddt import idata, ddt

from qiskit import ClassicalRegister
from qiskit.circuit import (
Expand Down Expand Up @@ -52,9 +52,25 @@
SGate,
XGate,
ZGate,
HGate,
)
from qiskit.dagcircuit import DAGOpNode

ROTATION_GATES = [
RXGate,
RYGate,
RZGate,
PhaseGate,
CRXGate,
CRYGate,
CRZGate,
CPhaseGate,
RXXGate,
RYYGate,
RZZGate,
RZXGate,
]


class NewGateCX(Gate):
"""A dummy class containing an cx gate unknown to the commutation checker's library."""
Expand Down Expand Up @@ -373,20 +389,7 @@ def test_serialization(self):
cc2.commute_nodes(dop1, dop2)
self.assertEqual(cc2.num_cached_entries(), 1)

@data(
RXGate,
RYGate,
RZGate,
PhaseGate,
CRXGate,
CRYGate,
CRZGate,
CPhaseGate,
RXXGate,
RYYGate,
RZZGate,
RZXGate,
)
@idata(ROTATION_GATES)
def test_cutoff_angles(self, gate_cls):
"""Check rotations with a small enough angle are cut off."""
max_power = 30
Expand All @@ -406,6 +409,27 @@ def test_cutoff_angles(self, gate_cls):
else:
self.assertFalse(scc.commute(generic_gate, [0, 1], [], gate, qargs, []))

@idata(ROTATION_GATES)
def test_rotation_mod_2pi(self, gate_cls):
"""Test the rotations modulo 2pi commute with any gate."""
generic_gate = HGate() # does not commute with any rotation gate
even = np.arange(-6, 7, 2)

with self.subTest(msg="even multiples"):
for multiple in even:
gate = gate_cls(multiple * np.pi)
self.assertTrue(
scc.commute(generic_gate, [0], [], gate, list(range(gate.num_qubits)), [])
)

odd = np.arange(-5, 6, 2)
with self.subTest(msg="odd multiples"):
for multiple in odd:
gate = gate_cls(multiple * np.pi)
self.assertFalse(
scc.commute(generic_gate, [0], [], gate, list(range(gate.num_qubits)), [])
)


if __name__ == "__main__":
unittest.main()

0 comments on commit c7ccbd4

Please sign in to comment.