Fix #880: return simplified QubitOperator from symmetry_conserving_bravyi_kitaev - #1440
Fix #880: return simplified QubitOperator from symmetry_conserving_bravyi_kitaev#1440stark256-spec wants to merge 1 commit into
Conversation
…serving_bravyi_kitaev symmetry_conserving_bravyi_kitaev could return QubitOperators with un-simplified terms: remove_indices() shifts qubit indices and can map two qubits onto the same index, producing a term with multiple Paulis acting on one qubit (e.g. ((0, 'X'), (1, 'Y'), (1, 'X'))). Because those terms are written straight into the operator's .terms dict, they bypass the simplification normally done on construction. get_sparse_operator (via qubit_operator_sparse) assumes each qubit appears at most once per term, so it raised 'ValueError: axis 0 index 7 exceeds matrix dimension 4' on such operators. Rebuild the operator after remove_indices so every term is routed back through QubitOperator's simplification, restoring canonical one-Pauli-per-qubit form. Add a regression test using the reporter's reproducer that checks the terms are canonical and that the resulting sparse operator matches the explicitly-simplified operator. Closes quantumlib#880
|
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. |
There was a problem hiding this comment.
Code Review
This pull request addresses issue #880 by ensuring that symmetry_conserving_bravyi_kitaev returns a simplified QubitOperator in canonical form (with at most one Pauli operator per qubit). This is achieved by rebuilding the operator term-by-term, which triggers QubitOperator's internal simplification and prevents errors when calling get_sparse_operator. A regression test has also been added to verify this behavior. There are no review comments, so I have no additional feedback to provide.
Closes #880.
Problem
get_sparse_operatorraises on the operator produced bysymmetry_conserving_bravyi_kitaev:Root cause
symmetry_conserving_bravyi_kitaevfinishes by callingremove_indices, which shifts qubit indices. When two qubits are mapped onto the same new index, a term ends up with multiple Paulis acting on one qubit, e.g.:remove_indiceswrites these terms straight into the operator’s.termsdict, so they bypass the simplificationQubitOperatornormally performs on construction.qubit_operator_sparseassumes each qubit appears at most once per term (it grows the tensor product one factor per Pauli), so a repeated qubit makes the per-term matrix larger than then_qubitsHilbert space and the assembly raises.Fix
Rebuild the operator after
remove_indicesso every term is routed back throughQubitOperator’s simplification, restoring canonical one-Pauli-per-qubit form (e.g.((0, X), (1, Y), (1, X)) → ((0, X), (1, Z))). This keeps the operator mathematically identical — the existing eigenspectrum-based tests still pass — while satisfying the invariant thatQubitOperators are simplified, whichget_sparse_operatorand other consumers rely on.Tests
Added
test_output_is_simplified_qubit_operator(the reporter’s reproducer), asserting:get_sparse_operatorno longer raises;Verification (Python 3.12):
pytest remove_symmetry_qubits_test.py— 6 passed (5 existing + new regression).black --check(line-length 100),pylint --rcfile=.pylintrc(3.3.9), andmypyall clean on the changed files.