Skip to content

evolved_operator_terms quantizes every coefficient to 1e-12, destroying precision at the API's own default atol #189

Description

@robertodr

🤖 AI text below 🤖

What

MonomialPropagator<NumModes>::evolved_operator_terms quantizes every decoded coefficient to 12
decimal places before returning it.

cpp/monoprop/detail/monomial_propagator/MonomialPropagatorImpl.h:1069-1073

// Round to drop anti-hermitian numerical noise (Majorana un-applies the Hermitian phase).
const auto decoded = algebra_decode_coeff<NumModes>(basis_, coeff, mono);
const std::complex<double> rounded(std::round(decoded.real() * 1e12) / 1e12,
                                   std::round(decoded.imag() * 1e12) / 1e12);
terms.emplace_back(bitset_to_indices<NumModes>(mono), rounded);

Why this is a problem

The "anti-hermitian numerical noise" the comment describes cannot arise:

  • Majorana: decode_coeff multiplies by hermitian_coefficient<NumModes>(maj)
    (cpp/monoprop/algebra/MajoranaAlgebra.h), which returns an element of POWERS_OF_I — components
    are exactly 0.0 and ±1.0.
  • Pauli: decode_pauli_coeff returns {coeff, 0.0} outright.

coeff is a real double, so in both cases the complex multiply is exact in IEEE-754 and the
component that should be zero already is an exact zero. There is nothing to scrub.

What the rounding does do is quantize to 1e-12 absolute. evolved_operator is exposed to Python
with a default atol=1e-12
(MajoranaPropagator.evolved_operator / PauliPropagator.evolved_operator), so it deliberately
admits terms whose magnitude the rounding then reduces to one or two significant digits:

true coefficient returned
1.23456789012345e-3 1.23456789e-3 (9 s.f.)
4.7213456789e-10 4.72e-10 (3 s.f.)
8.31e-12 8e-12 (1 s.f.)

So the API's own default tolerance selects exactly the range where the rounding is most destructive.

Suggested fix

Return decoded unchanged and drop the rounded temporary.

If a noise scrub is still wanted for defensiveness, snap only the component that is required to be
zero, relative to the magnitude of the other one — do not quantize both components absolutely.

Verification

  • Existing coverage: tests/test_nonfermi.py, tests/test_majorana.py, tests/test_pauli.py,
    tests/test_monoprop_smoke.py (line 149 calls evolved_operator(parameters, 1e-12)). These compare
    with isclose(atol=1e-12), so removing the rounding should leave them green.
  • Add a regression test: build a case with an evolved coefficient around 1e-10 and assert
    evolved_operator(..., atol=1e-12) returns it to full double precision. This fails today.

Found by a code-reading review of the repository at 29a8050. No build tree was available, so the
analysis is from source inspection and should be confirmed against a build.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions