Skip to content

Conversation

@jk20342
Copy link
Contributor

@jk20342 jk20342 commented Nov 10, 2025

Context:

qml.pauli_decompose() currently requires manual conversion of scipy sparse matrices to dense arrays, which defeats the purpose of using sparse matrices for large systems (e.g., 16+ qubits).

Forum discussion: https://discuss.pennylane.ai/t/how-to-pauli-decompose-a-sparse-matrix/8436/8

Description of the Change:

Added automatic sparse matrix detection and conversion in qml.pauli_decompose(). Sparse matrices are converted to dense internally using .toarray().

Benefits:

  • Scipy sparse matrices can now be passed directly to qml.pauli_decompose()

Possible Drawbacks:

None - sparse matrices are converted to dense internally anyway.

Related GitHub Issues:

n/a

Updated the functions to support scipy sparse matrices by converting them to dense format internally. Added relevant documentation for handling sparse matrices in the decomposition functions.
Added tests for sparse matrix decomposition and related functionalities.
@github-actions github-actions bot added the external PRs opened by contributors outside the PennyLaneAI organization label Nov 10, 2025
Added entry for new feature allowing scipy sparse matrices to be passed directly to pauli_decompose. Updated contributors list with Jacob Kitchen.
Copy link
Contributor

@albi3ro albi3ro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for opening this PR @jk20342 .

Unfortunately, the goal of the feature request is to natively calculate the pauli decomposition without converting to a dense matrix. This would allow us to push the algorithm up to larger sizes as the issue requests. This may be a non-trivial task, as the current implementation uses things like math.array, math.stack, and other dense logic that would need to be completely rewritten.

@jk20342
Copy link
Contributor Author

jk20342 commented Nov 10, 2025

Thanks for opening this PR @jk20342 .

Unfortunately, the goal of the feature request is to natively calculate the pauli decomposition without converting to a dense matrix. This would allow us to push the algorithm up to larger sizes as the issue requests. This may be a non-trivial task, as the current implementation uses things like math.array, math.stack, and other dense logic that would need to be completely rewritten.

Ah thanks! going to convert this to a draft and continue working with new understanding of the problem

@jk20342 jk20342 marked this pull request as draft November 10, 2025 21:15
jk20342 and others added 8 commits November 10, 2025 16:17
Added sparse matrix support for generalized Pauli decomposition, enabling efficient handling of large sparse matrices without converting to dense format.
Add tests for sparse matrix decomposition scenarios including handling of empty matrices, non-Hermitian matrices, and matrices with duplicate entries.
Sparse matrices are now processed natively in pauli_decompose for efficient decomposition of large matrices.
@jk20342 jk20342 marked this pull request as ready for review November 12, 2025 02:18
@jk20342
Copy link
Contributor Author

jk20342 commented Nov 12, 2025

Hi @albi3ro I think i've implemented the desired functionality if you wouldnt mind taking a look thanks 😄

@jk20342 jk20342 requested a review from albi3ro November 12, 2025 21:27
Copy link
Contributor

@obliviateandsurrender obliviateandsurrender left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot @jk20342, this is really impressive work! Overall, it already looks great, just leaving a few minor suggestions for further improvements.

Comment on lines +109 to +111
* Scipy sparse matrices can now be passed directly to :func:`~pennylane.pauli_decompose` without
manual conversion to dense arrays. Sparse matrices are processed natively allowing efficient
decomposition of large sparse matrices that cannot fit in memory as dense arrays.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Scipy sparse matrices can now be passed directly to :func:`~pennylane.pauli_decompose` without
manual conversion to dense arrays. Sparse matrices are processed natively allowing efficient
decomposition of large sparse matrices that cannot fit in memory as dense arrays.
* The :func:`~pennylane.pauli_decompose` now supports decomposing scipy's sparse matrices,
allowing for efficient decomposition of large matrices that cannot fit in memory when written as
dense arrays.

from pennylane.math.utils import is_abstract
from pennylane.ops import Identity, LinearCombination, PauliX, PauliY, PauliZ, Prod, SProd, Sum
from pennylane.ops.qubit.matrix_ops import _walsh_hadamard_transform
import scipy.sparse as sp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may prefer importing it as sps, as we generally use sp for scipy.

Suggested change
import scipy.sparse as sp
import scipy.sparse as sps

Comment on lines +48 to +51
matrix (tensor_like[complex] or scipy.sparse matrix): any matrix M, the keyword argument ``padding=True``
should be provided if the dimension of M is not :math:`2^n\times 2^n`. Scipy sparse
matrices are also supported and are processed natively without converting to dense format,
enabling efficient decomposition of large sparse matrices.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
matrix (tensor_like[complex] or scipy.sparse matrix): any matrix M, the keyword argument ``padding=True``
should be provided if the dimension of M is not :math:`2^n\times 2^n`. Scipy sparse
matrices are also supported and are processed natively without converting to dense format,
enabling efficient decomposition of large sparse matrices.
matrix (tensor_like[complex] or scipy.sparse matrix): any matrix M given with a dense or sparse representation.
The keyword argument ``padding=True`` should be provided if the dimension of M is not :math:`2^n\times 2^n`.

Scipy sparse matrices are also supported:
>>> import scipy.sparse as sp
>>> sparse_matrix = sp.csr_matrix([[0, 1], [1, 0]])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should try to have a slightly more non-trivial example for the example here.

the ``pauli`` flag.
Args:
matrix (scipy.sparse matrix): Any sparse matrix. If its dimension is not
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
matrix (scipy.sparse matrix): Any sparse matrix. If its dimension is not
matrix (scipy.sparse.spmatrix | scipu.sparse.sparray): Any sparse matrix. If its dimension is not

if word not in coeffs_map:
continue
coeff = coeffs_map[word]
if abs(coeff) <= tolerance:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am slightly concerned about this static tolerance value. Do we really need it?

Comment on lines +391 to +393
H (tensor_like[complex] or scipy.sparse matrix): a Hermitian matrix of dimension :math:`2^n\times 2^n`.
Scipy sparse matrices are also supported and are processed natively without converting to dense format,
enabling efficient decomposition of large sparse matrices.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
H (tensor_like[complex] or scipy.sparse matrix): a Hermitian matrix of dimension :math:`2^n\times 2^n`.
Scipy sparse matrices are also supported and are processed natively without converting to dense format,
enabling efficient decomposition of large sparse matrices.
H (tensor_like[complex] | scipy.sparse.spmatrix): a Hermitian matrix of dimension :math:`2^n\times 2^n` with dense or sparse representation.

coefficients for each of the :math:`4^n` Pauli words are computed while accounting for the
phase from each ``PauliY`` term occurring in the word.
Scipy sparse matrices are also supported:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Scipy sparse matrices are also supported:
Scipy sparse matrices are also supported and processed natively without converting to
dense format, enabling efficient decomposition of large sparse matrices. For example:

>>> terms
[X(0)]
"""
sparse_matrix = sp.coo_matrix(matrix)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the coo_matrix the best choice?

Example:
>>> import pennylane as qml
>>> import scipy.sparse as sp
>>> sparse_matrix = sp.csr_matrix([[0, 1], [1, 0]])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use a non-trivial example here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external PRs opened by contributors outside the PennyLaneAI organization

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants