1313)
1414from qiskit .quantum_info import Pauli
1515
16+
1617class TestPauliProductRotationMatrix :
1718 """Test that PauliProductRotation returns correct unitary matrices."""
1819
@@ -23,54 +24,62 @@ def test_single_qubit_x_rotation(self):
2324 mat = gate .to_matrix ()
2425
2526 # RX(theta) = cos(θ/2)*I - i*sin(θ/2)*X
26- expected = np .array ([
27- [np .cos (theta / 2 ), - 1j * np .sin (theta / 2 )],
28- [- 1j * np .sin (theta / 2 ), np .cos (theta / 2 )],
29- ])
30- np .testing .assert_allclose (mat , expected , atol = 1e-10 ,
31- err_msg = "PPR('X', θ) must match RX(θ)" )
27+ expected = np .array (
28+ [
29+ [np .cos (theta / 2 ), - 1j * np .sin (theta / 2 )],
30+ [- 1j * np .sin (theta / 2 ), np .cos (theta / 2 )],
31+ ]
32+ )
33+ np .testing .assert_allclose (
34+ mat , expected , atol = 1e-10 , err_msg = "PPR('X', θ) must match RX(θ)"
35+ )
3236
3337 def test_single_qubit_z_rotation (self ):
3438 """PPR with 'Z' should match RZ gate (up to global phase)."""
3539 theta = np .pi / 4
36- gate = PauliProductRotationGate (Pauli ("Z" ),theta )
40+ gate = PauliProductRotationGate (Pauli ("Z" ), theta )
3741 mat = gate .to_matrix ()
3842
3943 # exp(-i*θ/2*Z) = diag(exp(-iθ/2), exp(+iθ/2))
40- expected = np .diag ([
41- np .exp (- 1j * theta / 2 ),
42- np .exp (+ 1j * theta / 2 ),
43- ])
44- np .testing .assert_allclose (mat , expected , atol = 1e-10 ,
45- err_msg = "PPR('Z', θ) must match RZ(θ)" )
44+ expected = np .diag (
45+ [
46+ np .exp (- 1j * theta / 2 ),
47+ np .exp (+ 1j * theta / 2 ),
48+ ]
49+ )
50+ np .testing .assert_allclose (
51+ mat , expected , atol = 1e-10 , err_msg = "PPR('Z', θ) must match RZ(θ)"
52+ )
4653
4754 def test_two_qubit_zz (self ):
4855 """PPR 'ZZ' must be a 4×4 unitary."""
4956 theta = np .pi / 5
50- gate = PauliProductRotationGate (Pauli ("ZZ" ),theta )
57+ gate = PauliProductRotationGate (Pauli ("ZZ" ), theta )
5158 mat = gate .to_matrix ()
5259 assert mat .shape == (4 , 4 ), "ZZ gate must be 4×4"
5360
5461 # Must be unitary: U† U = I
5562 ident = mat .conj ().T @ mat
56- np .testing .assert_allclose (ident , np .eye (4 ), atol = 1e-10 ,
57- err_msg = "PPR('ZZ', θ) matrix must be unitary" )
63+ np .testing .assert_allclose (
64+ ident , np .eye (4 ), atol = 1e-10 , err_msg = "PPR('ZZ', θ) matrix must be unitary"
65+ )
5866
5967 def test_three_qubit_xyz (self ):
6068 """PPR 'XYZ' must be an 8×8 unitary."""
6169 theta = 0.7
62- gate = PauliProductRotationGate (Pauli ("XYZ" ),theta )
70+ gate = PauliProductRotationGate (Pauli ("XYZ" ), theta )
6371 mat = gate .to_matrix ()
6472 assert mat .shape == (8 , 8 ), "XYZ gate must be 8×8"
6573
6674 ident = mat .conj ().T @ mat
67- np .testing .assert_allclose (ident , np .eye (8 ), atol = 1e-10 ,
68- err_msg = "PPR('XYZ', θ) matrix must be unitary" )
75+ np .testing .assert_allclose (
76+ ident , np .eye (8 ), atol = 1e-10 , err_msg = "PPR('XYZ', θ) matrix must be unitary"
77+ )
6978
7079 def test_identity_pauli_is_global_phase (self ):
7180 """PPR with all-identity Pauli 'II' reduces to a global phase gate."""
7281 theta = np .pi / 6
73- gate = PauliProductRotationGate (Pauli ("II" ),theta )
82+ gate = PauliProductRotationGate (Pauli ("II" ), theta )
7483 mat = gate .to_matrix ()
7584
7685 # exp(-i*θ/2*I⊗I) = exp(-i*θ/2) * I4
@@ -79,14 +88,15 @@ def test_identity_pauli_is_global_phase(self):
7988
8089 def test_theta_zero_is_identity (self ):
8190 """At θ=0, PPR must be the identity (cos(0)=1, sin(0)=0)."""
82- gate = PauliProductRotationGate (Pauli ("XZ" ),0.0 )
91+ gate = PauliProductRotationGate (Pauli ("XZ" ), 0.0 )
8392 mat = gate .to_matrix ()
84- np .testing .assert_allclose (mat , np .eye (4 ), atol = 1e-10 ,
85- err_msg = "PPR at θ=0 must be identity" )
93+ np .testing .assert_allclose (
94+ mat , np .eye (4 ), atol = 1e-10 , err_msg = "PPR at θ=0 must be identity"
95+ )
8696
8797 def test_theta_2pi_is_negative_identity (self ):
8898 """At θ=2π, PPR = -I (a global phase of -1)."""
89- gate = PauliProductRotationGate (Pauli ("Z" ),2 * np .pi )
99+ gate = PauliProductRotationGate (Pauli ("Z" ), 2 * np .pi )
90100 mat = gate .to_matrix ()
91101 np .testing .assert_allclose (mat , - np .eye (2 ), atol = 1e-10 )
92102
@@ -95,7 +105,7 @@ def test_packed_instruction_try_matrix(self):
95105 from qiskit ._accelerate .circuit import CircuitData
96106
97107 theta = np .pi / 7
98- gate = PauliProductRotationGate (Pauli ("XX" ),theta )
108+ gate = PauliProductRotationGate (Pauli ("XX" ), theta )
99109 qc = QuantumCircuit (2 )
100110 qc .append (gate , [0 , 1 ])
101111
@@ -113,7 +123,7 @@ def test_matrix_consistent_with_simulation(self):
113123 from qiskit .quantum_info import Statevector
114124
115125 theta = np .pi / 3
116- gate = PauliProductRotationGate (Pauli ("ZZ" ),theta )
126+ gate = PauliProductRotationGate (Pauli ("ZZ" ), theta )
117127 qc = QuantumCircuit (2 )
118128 qc .h (0 )
119129 qc .cx (0 , 1 )
@@ -123,11 +133,21 @@ def test_matrix_consistent_with_simulation(self):
123133 mat = gate .to_matrix ()
124134 assert sv .is_valid (), "Statevector must remain normalized"
125135
126- @pytest .mark .parametrize ("pauli,n_qubits" , [
127- ("X" , 1 ), ("Y" , 1 ), ("Z" , 1 ),
128- ("XX" , 2 ), ("YY" , 2 ), ("ZZ" , 2 ), ("XY" , 2 ), ("YZ" , 2 ),
129- ("XXX" , 3 ), ("ZZZ" , 3 ),
130- ])
136+ @pytest .mark .parametrize (
137+ "pauli,n_qubits" ,
138+ [
139+ ("X" , 1 ),
140+ ("Y" , 1 ),
141+ ("Z" , 1 ),
142+ ("XX" , 2 ),
143+ ("YY" , 2 ),
144+ ("ZZ" , 2 ),
145+ ("XY" , 2 ),
146+ ("YZ" , 2 ),
147+ ("XXX" , 3 ),
148+ ("ZZZ" , 3 ),
149+ ],
150+ )
131151 def test_unitary_parametrized (self , pauli , n_qubits ):
132152 """All common Pauli strings must produce valid unitaries."""
133153 theta = 1.23
@@ -136,6 +156,8 @@ def test_unitary_parametrized(self, pauli, n_qubits):
136156 dim = 2 ** n_qubits
137157 assert mat .shape == (dim , dim )
138158 np .testing .assert_allclose (
139- mat .conj ().T @ mat , np .eye (dim ), atol = 1e-10 ,
140- err_msg = f"PPR('{ pauli } ') matrix not unitary"
141- )
159+ mat .conj ().T @ mat ,
160+ np .eye (dim ),
161+ atol = 1e-10 ,
162+ err_msg = f"PPR('{ pauli } ') matrix not unitary" ,
163+ )
0 commit comments