Skip to content

Commit 8ab5099

Browse files
t-imamichiking-p3nguin
authored andcommitted
Performance improvement of SparsePauliOp.to_matrix (Qiskit#9620)
* optimize SparsePauliOp.to_matrix * optimize dense * proper vectorize * update copyright year * small opt * update a comment
1 parent 1b53069 commit 8ab5099

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

qiskit/quantum_info/operators/symplectic/base_pauli.py

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This code is part of Qiskit.
22
#
3-
# (C) Copyright IBM 2017, 2020
3+
# (C) Copyright IBM 2017, 2023
44
#
55
# This code is licensed under the Apache License, Version 2.0. You may
66
# obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -26,6 +26,10 @@
2626
from qiskit.quantum_info.operators.mixins import AdjointMixin, MultiplyMixin
2727

2828

29+
# utility for _to_matrix
30+
_PARITY = np.array([-1 if bin(i).count("1") % 2 else 1 for i in range(256)], dtype=complex)
31+
32+
2933
class BasePauli(BaseOperator, AdjointMixin, MultiplyMixin):
3034
r"""Symplectic representation of a list of N-qubit Paulis.
3135
@@ -392,7 +396,7 @@ def _from_array(z, x, phase=0):
392396

393397
@staticmethod
394398
def _to_matrix(z, x, phase=0, group_phase=False, sparse=False):
395-
"""Return the matrix matrix from symplectic representation.
399+
"""Return the matrix from symplectic representation.
396400
397401
The Pauli is defined as :math:`P = (-i)^{phase + z.x} * Z^z.x^x`
398402
where ``array = [x, z]``.
@@ -430,7 +434,19 @@ def _to_matrix(z, x, phase=0, group_phase=False, sparse=False):
430434
coeff = (-1j) ** phase
431435
else:
432436
coeff = 1
433-
data = np.array([coeff * (-1) ** (bin(i).count("1") % 2) for i in z_indices & indptr])
437+
438+
# Compute parities of `z_indices & indptr`, i.e.,
439+
# np.array([(-1) ** bin(i).count("1") for i in z_indices & indptr])
440+
vec_u64 = z_indices & indptr
441+
mat_u8 = np.zeros((vec_u64.size, 8), dtype=np.uint8)
442+
for i in range(8):
443+
mat_u8[:, i] = vec_u64 & 255
444+
vec_u64 >>= 8
445+
if np.all(vec_u64 == 0):
446+
break
447+
parity = _PARITY[np.bitwise_xor.reduce(mat_u8, axis=1)]
448+
449+
data = coeff * parity
434450
if sparse:
435451
# Return sparse matrix
436452
from scipy.sparse import csr_matrix
@@ -439,8 +455,7 @@ def _to_matrix(z, x, phase=0, group_phase=False, sparse=False):
439455

440456
# Build dense matrix using csr format
441457
mat = np.zeros((dim, dim), dtype=complex)
442-
for i in range(dim):
443-
mat[i][indices[indptr[i] : indptr[i + 1]]] = data[indptr[i] : indptr[i + 1]]
458+
mat[range(dim), indices[:dim]] = data[:dim]
444459
return mat
445460

446461
@staticmethod

test/python/quantum_info/operators/symplectic/test_sparse_pauli_op.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This code is part of Qiskit.
22
#
3-
# (C) Copyright IBM 2017, 2020.
3+
# (C) Copyright IBM 2017, 2023.
44
#
55
# This code is licensed under the Apache License, Version 2.0. You may
66
# obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -236,6 +236,20 @@ def test_to_matrix(self):
236236
for coeff, label in zip(coeffs, labels):
237237
target += coeff * pauli_mat(label)
238238
np.testing.assert_array_equal(spp_op.to_matrix(), target)
239+
np.testing.assert_array_equal(spp_op.to_matrix(sparse=True).toarray(), target)
240+
241+
def test_to_matrix_large(self):
242+
"""Test to_matrix method with a large number of qubits."""
243+
reps = 5
244+
labels = ["XI" * reps, "YZ" * reps, "YY" * reps, "ZZ" * reps]
245+
coeffs = [-3, 4.4j, 0.2 - 0.1j, 66.12]
246+
spp_op = SparsePauliOp(labels, coeffs)
247+
size = 1 << 2 * reps
248+
target = np.zeros((size, size), dtype=complex)
249+
for coeff, label in zip(coeffs, labels):
250+
target += coeff * pauli_mat(label)
251+
np.testing.assert_array_equal(spp_op.to_matrix(), target)
252+
np.testing.assert_array_equal(spp_op.to_matrix(sparse=True).toarray(), target)
239253

240254
def test_to_matrix_parameters(self):
241255
"""Test to_matrix method for parameterized SparsePauliOp."""

0 commit comments

Comments
 (0)