quantumlib / Cirq

A Python framework for creating, editing, and invoking Noisy Intermediate Scale Quantum (NISQ) circuits.
Apache License 2.0
4.24k stars 1.01k forks source link

Avoid state vector normalization if it worsens the round offs #6556

Closed pavoljuhas closed 5 months ago

pavoljuhas commented 5 months ago

This fixes failure of

check/pytest -n0 cirq-core/cirq/circuits/circuit_test.py::test_final_state_vector

which happened because normalization of a state vector at np.complex64 precision can subtly increase the overall round-off error.

Follow up to #6522 and #6402

pavoljuhas commented 5 months ago

I have got consistent failures for the cirq-core/cirq/circuits/circuit_test.py::test_final_state_vector test on my Debian-based desktop which were bisected to #6522. For some reason these do not show in CI runs, but it is preferable to have passing tests in local environments too.

codecov[bot] commented 5 months ago

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Project coverage is 97.79%. Comparing base (1bec6b5) to head (43cb287). Report is 1 commits behind head on main.

:exclamation: Current head 43cb287 differs from pull request most recent head 754f40e. Consider uploading reports for the commit 754f40e to get more accurate results

Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #6556 +/- ## ======================================= Coverage 97.79% 97.79% ======================================= Files 1124 1124 Lines 95486 95489 +3 ======================================= + Hits 93376 93380 +4 + Misses 2110 2109 -1 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

pavoljuhas commented 5 months ago

maybe we should remove it normalization then?

The normalization does help for your original round-off example in #6402. I think the case where it worsen the outcome is for state vectors with few nonzero elements. Here is how test_final_state_vector fails on my desktop (the outcome may be different for other OS or CPU versions):

>>> x = np.exp(1j * np.pi/4, dtype=np.complex64)
>>> xn = x / np.linalg.norm(x)
>>> abs(x * x.conj() - 1)
5.960464477539063e-08
>>> abs(xn * xn.conj() - 1)
1.1920928955078125e-07

where the latter value for normalized xn is above the test tolerance.

With this PR the test passes and the round-off is better for #6402.