Skip to content

[python] Fix OperatorSum.evaluate() adding a spurious zero-coefficient identity term - #5349

Open
udsy19 wants to merge 1 commit into
NVIDIA:mainfrom
udsy19:fix/operator-sum-evaluate-spurious-zero-term
Open

udsy19 wants to merge 1 commit into
NVIDIA:mainfrom
udsy19:fix/operator-sum-evaluate-spurious-zero-term

Conversation

@udsy19

@udsy19 udsy19 commented Sep 1, 2026

Copy link
Copy Markdown

Fixes #5348

Bug

_sum_transformation (python/cudaq/operators/manipulation.py:154-188) seeds its accumulator
with arithmetics.evaluate(ScalarOperator.const(0)) and adds every term to it, including the
first. For the default arithmetics used by OperatorSum.evaluate(), that first add is a plain
0 + term1, and the underlying C++ operator classes turn scalar + operator into an explicit
zero-coefficient identity term (degrees == []) instead of simplifying it away. So evaluating a
multi-term SpinOperator/BosonOperator/FermionOperator/MatrixOperator always grows one
extra term that acts on no degrees of freedom, inflating term_count by one every time. This is
not just cosmetic: python/cudaq/dynamics/evolution.py:303,608 calls .evaluate(**step_parameters)
on every user-supplied observable at every time step of cudaq.evolve().

Fix

Seed the accumulation with the first evaluated term instead of a scalar zero, and only fall back
to evaluating ScalarOperator.const(0) when the operator has no terms at all - so arithmetics.add
is never called with a scalar zero as either operand.

Verification

Not a regression (introduced with the class in da31e1b7a / #2817, untouched since except a
copyright-year bump - confirmed via git log -S/git log --follow). No existing test checks
term_count or per-term degrees after .evaluate().

Negative control: added test_evaluate_no_spurious_zero_term to
python/tests/operator/test_matrix_op.py, ran it against the production manipulation.py
before this fix (reverted to the upstream version) and after, using the CUDA-Q 0.15.1 wheel
(aca5853a7, byte-identical to this file on current main - zero commits touch
python/cudaq/operators between the wheel commit and main):

without the fix: assert 3 == 2 (1 failed)
with the fix:    1 passed

Also ran the full existing python/tests/operator/ suite (test_matrix_op.py,
test_spin_op.py, test_fermion_op.py, test_boson_op.py, test_scalar_op.py,
test_conversions.py) with the fix applied: 59 passed (one pre-existing, unrelated native
test_file_serialization crash deselected - reproduces identically with or without this
change, in unrelated spin-operator file-deserialization code).

Small, net-positive diff; touches only the shared accumulation helper and adds one regression
test.

Signed-off-by: Udaya Tejas udayatejas2004@gmail.com

_sum_transformation seeded its accumulation with
arithmetics.evaluate(ScalarOperator.const(0)) and added every term to
that, including the first. For the default evaluation arithmetics used
by OperatorSum.evaluate(), that resolves to a plain `0 + term`, and the
underlying C++ operator classes turn that into an explicit,
zero-coefficient identity term with no degrees rather than simplifying
it away. So evaluating a multi-term operator (e.g. an observable
re-evaluated at each time step in cudaq.evolve) always grew one extra
term, inflating term_count and yielding a term with an empty degrees
list.

Seed the accumulation with the first evaluated term instead, and only
fall back to evaluating a scalar zero when the operator has no terms
at all.

Signed-off-by: Udaya Tejas <udayatejas2004@gmail.com>
@copy-pr-bot

copy-pr-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added the python-lang Anything related to the Python CUDA Quantum language implementation label Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python-lang Anything related to the Python CUDA Quantum language implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OperatorSum.evaluate() adds a spurious zero-coefficient identity term for multi-term operators

1 participant