Fix dropped state collapse in FreeQuantumState.measure_multiple#355
Open
HasanTasdiq wants to merge 12 commits into
Open
Fix dropped state collapse in FreeQuantumState.measure_multiple#355HasanTasdiq wants to merge 12 commits into
HasanTasdiq wants to merge 12 commits into
Conversation
Bumps the uv group with 1 update in the / directory: [mistune](https://github.com/lepture/mistune). Updates `mistune` from 3.1.4 to 3.2.1 - [Release notes](https://github.com/lepture/mistune/releases) - [Changelog](https://github.com/lepture/mistune/blob/main/docs/changes.rst) - [Commits](lepture/mistune@v3.1.4...v3.2.1) --- updated-dependencies: - dependency-name: mistune dependency-version: 3.2.1 dependency-type: indirect dependency-group: uv ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps the uv group with 1 update in the / directory: [jupyter-server](https://github.com/jupyter-server/jupyter_server). Updates `jupyter-server` from 2.17.0 to 2.18.0 - [Release notes](https://github.com/jupyter-server/jupyter_server/releases) - [Changelog](https://github.com/jupyter-server/jupyter_server/blob/main/CHANGELOG.md) - [Commits](jupyter-server/jupyter_server@v2.17.0...v2.18.0) --- updated-dependencies: - dependency-name: jupyter-server dependency-version: 2.18.0 dependency-type: indirect dependency-group: uv ... Signed-off-by: dependabot[bot] <support@github.com>
…bot/uv/uv-6dae2e92a4 Bump jupyter-server from 2.17.0 to 2.18.0 in the uv group across 1 directory
…bot/uv/uv-3f08418977 Bump mistune from 3.1.4 to 3.2.1 in the uv group across 1 directory
…337-dependabot/uv/uv-3f08418977 Revert "Bump mistune from 3.1.4 to 3.2.1 in the uv group across 1 directory"
…338-dependabot/uv/uv-6dae2e92a4 Revert "Bump jupyter-server from 2.17.0 to 2.18.0 in the uv group across 1 directory"
After projecting onto the chosen basis vector, measure_multiple wrote the
post-measurement state to attributes that FreeQuantumState does not have:
for state in entangled_list:
state.quantum_state = new_state # should be .state
state.entangled_photons = entangled_list # should be .entangled_states
FreeQuantumState stores its vector in `state` and its partners in
`entangled_states` (see the single-qubit `measure` method). Writing to the
wrong names silently created unused attributes and left the actual quantum
state uncollapsed: the entangled photons kept their pre-measurement
superposition after measure_multiple.
Assign the collapsed vector to `state` and update `entangled_states`,
mirroring the single-qubit `measure` method. Adds a regression test that
checks the state collapses to the measured basis vector.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hayekr
reviewed
May 22, 2026
Collaborator
hayekr
left a comment
There was a problem hiding this comment.
Thank you for your contribution. Please see my suggestions before we merge this to RnD.
| state.entangled_photons = entangled_list | ||
| # project to new state, then reassign quantum state and entangled list | ||
| new_state = tuple(new_states[res]) | ||
| for qs in entangled_list: |
Collaborator
There was a problem hiding this comment.
please call this quantum_state. Avoid abbreviations when able.
| assert tuple(photon1.quantum_state.state) == expected, "state did not collapse to measured basis vector" | ||
| # both photons must keep sharing the same collapsed state object | ||
| assert photon1.quantum_state.state is photon2.quantum_state.state | ||
|
|
Collaborator
There was a problem hiding this comment.
It would be good to add assertions preventing these invalid class attributes from being used.
assert not hasattr(photon1.quantum_state, "quantum_state")
assert not hasattr(photon1.quantum_state, "entangled_photons")
assert not hasattr(photon2.quantum_state, "quantum_state")
assert not hasattr(photon2.quantum_state, "entangled_photons")
| # both photons must keep sharing the same collapsed state object | ||
| assert photon1.quantum_state.state is photon2.quantum_state.state | ||
|
|
||
|
|
Collaborator
There was a problem hiding this comment.
You check that state is shared but we should also check that entanglement_states is also shared
assert photon1.quantum_state.entangled_states is photon2.quantum_state.entangled_states
hayekr
requested changes
May 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
FreeQuantumState.measure_multiple(sequence/kernel/quantum_state.py) computes the post-measurement state correctly but then assigns it to attributes that do not exist onFreeQuantumState:FreeQuantumStatestores its vector inself.stateand its entangled partners inself.entangled_states(see the single-qubitmeasuremethod, which doess.state = new_state). Writing toquantum_state/entangled_photonssilently creates unused attributes and leaves the real state uncollapsed: aftermeasure_multiple, the entangledFreeQuantumStateobjects keep their pre-measurement superposition.Demonstration
Two qubits each in
|+>, combined, then measured in the computational basis:This is reached in practice by
Photon.measure_multiple, used byPolarizationBSMandTimeBinBSM. The returned indexres(which drives detector firing) is correct, so detector outcomes are unaffected; but the measured photons' tracked state is left wrong, which is incorrect for any consumer that inspects photon state after a multi-qubit measurement.Fix
Assign the collapsed vector to the real fields, mirroring the single-qubit
measuremethod:Test plan
test_measure_multiple_collapses_state, which combines two|+>photons, measures in the computational basis, and asserts the shared state collapses to the measured basis vector (and stays shared).test_measure_multipleand other photon/kernel tests still pass.🤖 Generated with Claude Code