Skip to content

Deduplicate shared preamble in expectation-value sweeps#8123

Closed
yurekami wants to merge 1 commit into
quantumlib:mainfrom
yurekami:ghcontrib/4209-dedup-expectation-values
Closed

Deduplicate shared preamble in expectation-value sweeps#8123
yurekami wants to merge 1 commit into
quantumlib:mainfrom
yurekami:ghcontrib/4209-dedup-expectation-values

Conversation

@yurekami

@yurekami yurekami commented Jun 4, 2026

Copy link
Copy Markdown

Fixes #4209.

What

DensityMatrixSimulator.simulate_expectation_values_sweep and
Simulator.simulate_expectation_values_sweep_iter began with an identical preamble
(the one flagged by the # TODO(#4209) comment): reject terminal measurements unless
permitted, resolve the qubit order, build the qubit→index map, and wrap the observables
as cirq.PauliSums.

This factors that preamble into a protected helper _qubit_map_and_pauli_sums on
SimulatesExpectationValues (the base both simulators already inherit) and removes the
# TODO(#4209) marker.

Design context

Only the preamble is shared; the two methods' bodies are intentionally left as they are.
The base class documents "Prefer overriding simulate_expectation_values_sweep_iter", and
the sparse Simulator deliberately stays a lazy generator that streams over
simulate_sweep_iter and uses expectation_from_state_vector, while
DensityMatrixSimulator is eager and uses expectation_from_density_matrix. Collapsing the
two into one method would regress the sparse path's streaming behavior, so the helper covers
only the common setup. The helper returns the already-resolved QubitOrder so the qubit map
and the downstream simulate(...) call use the same ordering — no behavior change.

No public API change (the helper is protected); no serialization changes.

Scope / non-goals

  • Does not change the eager-vs-lazy structure of either method.
  • Does not touch the other Simulates* interfaces or the Clifford/MPS simulators (they
    don't override these methods).
  • No new public symbols.

Test

No new behavior is introduced, so the existing expectation-value tests act as the regression
net — density_matrix_simulator_test.py, sparse_simulator_test.py, and simulator_test.py
all pass (473 tests), and they already cover the numeric expectation values, the
terminal-measurement ValueError, and the permit_terminal_measurements flag, which
exercise every line of the new helper.

Factor the identical preamble of
DensityMatrixSimulator.simulate_expectation_values_sweep and
Simulator.simulate_expectation_values_sweep_iter into a protected
_qubit_map_and_pauli_sums helper on SimulatesExpectationValues, and remove
the # TODO(quantumlib#4209) marker. Only the shared setup (terminal-measurement guard,
qubit-order resolution, observable wrapping) is extracted; the eager and lazy
method bodies are unchanged.

Fixes quantumlib#4209
@yurekami
yurekami requested a review from a team as a code owner June 4, 2026 04:35
@yurekami
yurekami requested a review from shatterednirvana June 4, 2026 04:35
@github-actions github-actions Bot added the size: M 50< lines changed <250 label Jun 4, 2026
@codecov

codecov Bot commented Jun 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.60%. Comparing base (b29b6d4) to head (a234874).
⚠️ Report is 19 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8123      +/-   ##
==========================================
- Coverage   99.60%   99.60%   -0.01%     
==========================================
  Files        1118     1118              
  Lines      100957   100954       -3     
==========================================
- Hits       100557   100553       -4     
- Misses        400      401       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pavoljuhas pavoljuhas self-assigned this Jun 4, 2026
@pavoljuhas
pavoljuhas self-requested a review June 4, 2026 18:26
@pavoljuhas pavoljuhas added the priority/before-1.7 Finish before the Cirq 1.7 release label Jun 11, 2026

@pavoljuhas pavoljuhas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thank you for the PR. The primary goal of refactoring tasks like #4209 is to make the code more readable and maintainable. I feel it does not happen for the change here. As a rough approximation the total LOC is essentially unchanged when excluding comments and docstrings and notably increased in terms of raw counts. There is an extra new indirection to follow in the simulate_expectation_values_{iter,sweep} code.

Note these methods cannot be easily replaced with a common base-class method, because one needs to call expectation_from_state_vector whereas the other expectation_from_density_matrix and they also do a different thing to get the sequence of simulation results.

This is still useful to show that #4209 should be probably closed as wontfix; it was open long enough without much complaints.

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

Labels

priority/before-1.7 Finish before the Cirq 1.7 release size: M 50< lines changed <250

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deduplicate expectation value code in simulators

2 participants