Skip to content

Commit 2dec214

Browse files
committed
Remove standalone PPR matrix test file as tests are moved to existing test suite
1 parent c163201 commit 2dec214

3 files changed

Lines changed: 120 additions & 101 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
features:
3+
- |
4+
Added Rust-side matrix support for ``PauliProductRotationGate`` by reusing
5+
the existing Pauli matrix construction logic from the Rust
6+
``SparsePauliOp`` implementation.

test/python/circuit/library/test_pauli_product_rotation.py

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
PauliEvolutionGate,
2525
PauliProductMeasurement,
2626
)
27-
from qiskit.quantum_info import Pauli, Operator, SparsePauliOp
27+
from qiskit.quantum_info import Pauli, Operator, SparsePauliOp, Statevector
2828
from qiskit.qpy import dump, load
2929
from qiskit.compiler import transpile
3030
from test import QiskitTestCase # pylint: disable=wrong-import-order
@@ -223,6 +223,119 @@ def test_matrix_conventions(self):
223223
evo = PauliEvolutionGate(pauli, time=angle / 2)
224224
self.assertTrue(np.allclose(evo.to_matrix(), ppr.to_matrix()))
225225

226+
def test_single_qubit_x_rotation_matrix(self):
227+
"""Test matrix support for a single-qubit X rotation."""
228+
theta = np.pi / 3
229+
gate = PauliProductRotationGate(Pauli("X"), theta)
230+
mat = np.asarray(Operator(gate).data)
231+
232+
expected = np.array(
233+
[
234+
[np.cos(theta / 2), -1j * np.sin(theta / 2)],
235+
[-1j * np.sin(theta / 2), np.cos(theta / 2)],
236+
],
237+
dtype=complex,
238+
)
239+
240+
self.assertEqual(mat.shape, (2, 2))
241+
self.assertTrue(np.allclose(mat, expected))
242+
243+
def test_single_qubit_z_rotation_matrix(self):
244+
"""Test matrix support for a single-qubit Z rotation."""
245+
theta = np.pi / 4
246+
gate = PauliProductRotationGate(Pauli("Z"), theta)
247+
mat = np.asarray(Operator(gate).data)
248+
249+
expected = np.array(
250+
[
251+
[np.exp(-1j * theta / 2), 0],
252+
[0, np.exp(1j * theta / 2)],
253+
],
254+
dtype=complex,
255+
)
256+
257+
self.assertEqual(mat.shape, (2, 2))
258+
self.assertTrue(np.allclose(mat, expected))
259+
260+
def test_two_qubit_zz_matrix(self):
261+
"""Test matrix support for a two-qubit ZZ rotation."""
262+
theta = np.pi / 5
263+
gate = PauliProductRotationGate(Pauli("ZZ"), theta)
264+
mat = np.asarray(Operator(gate).data)
265+
266+
self.assertEqual(mat.shape, (4, 4))
267+
self.assertTrue(np.allclose(mat.conj().T @ mat, np.eye(4)))
268+
269+
def test_three_qubit_xyz_matrix(self):
270+
"""Test matrix support for a three-qubit XYZ rotation."""
271+
theta = 0.7
272+
gate = PauliProductRotationGate(Pauli("XYZ"), theta)
273+
mat = np.asarray(Operator(gate).data)
274+
275+
self.assertEqual(mat.shape, (8, 8))
276+
self.assertTrue(np.allclose(mat.conj().T @ mat, np.eye(8)))
277+
278+
def test_identity_pauli_is_global_phase(self):
279+
"""Test that an all-identity Pauli only contributes a global phase."""
280+
theta = np.pi / 6
281+
gate = PauliProductRotationGate(Pauli("II"), theta)
282+
mat = np.asarray(Operator(gate).data)
283+
expected = np.exp(-1j * theta / 2) * np.eye(4)
284+
285+
self.assertTrue(np.allclose(mat, expected))
286+
287+
def test_theta_zero_is_identity(self):
288+
"""Test that zero angle gives the identity."""
289+
gate = PauliProductRotationGate(Pauli("XZ"), 0.0)
290+
mat = np.asarray(Operator(gate).data)
291+
292+
self.assertTrue(np.allclose(mat, np.eye(4)))
293+
294+
def test_theta_2pi_is_negative_identity(self):
295+
"""Test that a 2π rotation gives -I up to global phase."""
296+
gate = PauliProductRotationGate(Pauli("Z"), 2 * np.pi)
297+
mat = np.asarray(Operator(gate).data)
298+
299+
self.assertTrue(np.allclose(mat, -np.eye(2)))
300+
301+
def test_matrix_consistent_with_simulation(self):
302+
"""Test matrix action is consistent with statevector simulation."""
303+
theta = np.pi / 3
304+
gate = PauliProductRotationGate(Pauli("ZZ"), theta)
305+
306+
qc = QuantumCircuit(2)
307+
qc.append(gate, [0, 1])
308+
309+
psi0 = Statevector.from_label("00")
310+
evolved = psi0.evolve(qc)
311+
mat = np.asarray(Operator(gate).data)
312+
expected = Statevector(mat @ psi0.data)
313+
314+
self.assertTrue(np.allclose(evolved.data, expected.data))
315+
316+
@data(
317+
("X", 1),
318+
("Y", 1),
319+
("Z", 1),
320+
("XX", 2),
321+
("YY", 2),
322+
("ZZ", 2),
323+
("XY", 2),
324+
("YZ", 2),
325+
("XXX", 3),
326+
("ZZZ", 3),
327+
)
328+
def test_matrix_unitary_for_common_paulis(self, case):
329+
"""Test matrix support for common Pauli strings."""
330+
pauli, n_qubits = case
331+
theta = 1.23
332+
333+
gate = PauliProductRotationGate(Pauli(pauli), theta)
334+
mat = np.asarray(Operator(gate).data)
335+
336+
self.assertEqual(mat.shape, (2**n_qubits, 2**n_qubits))
337+
self.assertTrue(np.allclose(mat.conj().T @ mat, np.eye(2**n_qubits)))
338+
226339
@data(0, 1, 2)
227340
def test_control(self, num_ctrl_qubits):
228341
"""Check calling the control method."""

test/python/circuit/test_pauli_product_rotation_matrix.py

Lines changed: 0 additions & 100 deletions
This file was deleted.

0 commit comments

Comments
 (0)