Skip to content

Handle unsimplified QubitOperator sparse terms#1350

Open
marko1olo wants to merge 1 commit into
quantumlib:mainfrom
marko1olo:fix-qubit-sparse-unsimplified
Open

Handle unsimplified QubitOperator sparse terms#1350
marko1olo wants to merge 1 commit into
quantumlib:mainfrom
marko1olo:fix-qubit-sparse-unsimplified

Conversation

@marko1olo

Copy link
Copy Markdown

Fixes #880.

Summary

  • simplify QubitOperator terms inside sparse conversion before building Kronecker factors
  • apply the same simplification to get_linear_qubit_operator_diagonal()
  • add regressions for repeated same-qubit Pauli factors and the symmetry_conserving_bravyi_kitaev reproducer from the issue

Tests

  • PYTHONPATH=C:\hades\oss\openfermion-880\src C:\hades\oss\openfermion\.venv\Scripts\python.exe -m pytest -p no:cacheprovider src\openfermion\linalg\sparse_tools_test.py::SparseOperatorTest::test_qubit_operator_sparse_simplifies_repeated_qubit_factors src\openfermion\linalg\sparse_tools_test.py::SparseOperatorTest::test_get_sparse_operator_with_unsimplified_symmetry_conserving_bk src\openfermion\linalg\sparse_tools_test.py::SparseOperatorTest::test_get_linear_qubit_operator_diagonal_simplifies_repeated_qubit_factors -q
  • PYTHONPATH=C:\hades\oss\openfermion-880\src C:\hades\oss\openfermion\.venv\Scripts\python.exe -m pytest -p no:cacheprovider src\openfermion\linalg\sparse_tools_test.py -q
  • PYTHONPATH=C:\hades\oss\openfermion-880\src C:\hades\oss\openfermion\.venv\Scripts\python.exe -m pytest -p no:cacheprovider src\openfermion\transforms\opconversions\remove_symmetry_qubits_test.py -q
  • C:\hades\oss\openfermion\.venv\Scripts\python.exe -m black --check --diff src\openfermion\linalg\sparse_tools.py
  • C:\hades\oss\openfermion\.venv\Scripts\python.exe -m black --check --diff src\openfermion\linalg\sparse_tools_test.py
  • PYTHONPYCACHEPREFIX=C:\tmp\pycache-openfermion-880 C:\hades\oss\openfermion\.venv\Scripts\python.exe -m compileall -q src\openfermion\linalg\sparse_tools.py src\openfermion\linalg\sparse_tools_test.py
  • git diff --check

@google-cla

google-cla Bot commented Jun 8, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a helper function _iter_simplified_qubit_operator_terms to ensure that QubitOperator terms are simplified (resolving repeated qubit factors) when generating sparse operators or calculating diagonals. Unit tests have been added to verify this behavior. The reviewer noted that calling _simplify on every term introduces a significant performance overhead for large operators and suggested an optimization to bypass _simplify when terms are already simplified.

Comment on lines +196 to +200
def _iter_simplified_qubit_operator_terms(qubit_operator):
"""Yield terms after applying QubitOperator's Pauli simplification."""
for qubit_term, coefficient in qubit_operator.terms.items():
coefficient, qubit_term = qubit_operator._simplify(qubit_term, coefficient)
yield qubit_term, coefficient

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Calling _simplify on every term of the QubitOperator introduces a significant performance overhead (due to sorting, dictionary lookups, and tuple allocations), especially for large operators with tens of thousands of terms. Since the vast majority of QubitOperator instances are already simplified, we can optimize this by first checking if the term is already simplified (i.e., indices are strictly increasing and there are no identity 'I' operators). If it is already simplified, we can yield it directly and bypass _simplify entirely.

def _iter_simplified_qubit_operator_terms(qubit_operator):
    """Yield terms after applying QubitOperator's Pauli simplification."""
    for qubit_term, coefficient in qubit_operator.terms.items():
        is_simplified = True
        prev_index = -1
        for index, action in qubit_term:
            if action == 'I' or index <= prev_index:
                is_simplified = False
                break
            prev_index = index

        if is_simplified:
            yield qubit_term, coefficient
        else:
            coefficient, qubit_term = qubit_operator._simplify(qubit_term, coefficient)
            yield qubit_term, coefficient

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

get_sparse_operator fails on non-simplified QubitOperators

1 participant