Skip to content

Commit f022fd3

Browse files
committed
Use sparse matrix computation for non-Operator
1 parent 6aaf647 commit f022fd3

File tree

2 files changed

+27
-31
lines changed

2 files changed

+27
-31
lines changed

qiskit/algorithms/eigensolvers/numpy_eigensolver.py

+23-28
Original file line numberDiff line numberDiff line change
@@ -108,50 +108,45 @@ def _check_set_k(self, operator: BaseOperator | PauliSumOp) -> None:
108108
self._k = self._in_k
109109

110110
def _solve(self, operator: BaseOperator | PauliSumOp) -> None:
111-
if isinstance(operator, PauliSumOp):
112-
sp_mat = operator.to_spmatrix()
111+
if isinstance(operator, Operator):
112+
# Sparse SciPy matrix not supported, use dense NumPy computation.
113+
op_matrix = operator.data
114+
if op_matrix.all() == op_matrix.conj().T.all():
115+
eigval, eigvec = np.linalg.eigh(op_matrix)
116+
else:
117+
eigval, eigvec = np.linalg.eig(op_matrix)
118+
else:
119+
if isinstance(operator, PauliSumOp):
120+
op_matrix = operator.to_spmatrix()
121+
else:
122+
op_matrix = operator.to_matrix(sparse=True)
123+
113124
# If matrix is diagonal, the elements on the diagonal are the eigenvalues. Solve by sorting.
114-
if scisparse.csr_matrix(sp_mat.diagonal()).nnz == sp_mat.nnz:
115-
diag = sp_mat.diagonal()
125+
if scisparse.csr_matrix(op_matrix.diagonal()).nnz == op_matrix.nnz:
126+
diag = op_matrix.diagonal()
116127
indices = np.argsort(diag)[: self._k]
117128
eigval = diag[indices]
118-
eigvec = np.zeros((sp_mat.shape[0], self._k))
129+
eigvec = np.zeros((op_matrix.shape[0], self._k))
119130
for i, idx in enumerate(indices):
120131
eigvec[idx, i] = 1.0
121132
else:
122133
if self._k >= 2**operator.num_qubits - 1:
123134
logger.debug(
124135
"SciPy doesn't support to get all eigenvalues, using NumPy instead."
125136
)
126-
if operator.is_hermitian():
137+
if (op_matrix != op_matrix.H).nnz == 0:
127138
eigval, eigvec = np.linalg.eigh(operator.to_matrix())
128139
else:
129140
eigval, eigvec = np.linalg.eig(operator.to_matrix())
130141
else:
131-
if operator.is_hermitian():
132-
eigval, eigvec = scisparse.linalg.eigsh(sp_mat, k=self._k, which="SA")
142+
if (op_matrix != op_matrix.H).nnz == 0:
143+
eigval, eigvec = scisparse.linalg.eigsh(op_matrix, k=self._k, which="SA")
133144
else:
134-
eigval, eigvec = scisparse.linalg.eigs(sp_mat, k=self._k, which="SR")
135-
136-
indices = np.argsort(eigval)[: self._k]
137-
eigval = eigval[indices]
138-
eigvec = eigvec[:, indices]
139-
else:
140-
logger.debug("SciPy not supported, using NumPy instead.")
141-
142-
if isinstance(operator, Operator):
143-
op_matrix = operator.data
144-
else:
145-
op_matrix = operator.to_matrix()
146-
147-
if op_matrix.all() == op_matrix.conj().T.all():
148-
eigval, eigvec = np.linalg.eigh(op_matrix)
149-
else:
150-
eigval, eigvec = np.linalg.eig(op_matrix)
145+
eigval, eigvec = scisparse.linalg.eigs(op_matrix, k=self._k, which="SR")
151146

152-
indices = np.argsort(eigval)[: self._k]
153-
eigval = eigval[indices]
154-
eigvec = eigvec[:, indices]
147+
indices = np.argsort(eigval)[: self._k]
148+
eigval = eigval[indices]
149+
eigvec = eigvec[:, indices]
155150

156151
result = NumPyEigensolverResult()
157152
result.eigenvalues = eigval

releasenotes/notes/fix-numpy-eigensolver-sparse-pauli-op-b09a9ac8fb93fe4a.yaml

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ fixes:
44
Fixed an issue with
55
:class:`~qiskit.algorithms.eigensolvers.NumPyEigensolver` and by extension
66
:class:`~qiskit.algorithms.minimum_eigensolvers.NumPyMinimumEigensolver`
7-
where solving for :class:`~qiskit.operators.base_operator.BaseOperator`
8-
subclasses other than :class:`~qiskit.operators.Operator` would cause an
9-
error.
7+
where solving for
8+
:class:`~qiskit.quantum_info.operators.base_operator.BaseOperator`
9+
subclasses other than :class:`~qiskit.quantum_info.operators.Operator`
10+
would cause an error.

0 commit comments

Comments
 (0)