Add support for sparse measurements #544
Draft
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.
Motivation
Measurements of
PauliOperatorson annqubit state are currently either performed by checking the commutation relation between each row and the wholenqubitPauliOperator, or for single qubit measurements using the specialized functionsprojectX!, ... This specialized algorithm is great. However, since stabilizer measurements usually contain more than one qubit, a version optimized for more generalized sparsePauliOperatorscould be useful.While the code for single qubit measurement can (more or less) easily be generalized to two qubits, the memory layout of the tableau makes this sparse checking less efficient.
Implementation
This PR tries to find a balance between efficiently using the memory layout of the tableau and sparsely computing commutation.
This is done by only computing the
xor(in thecommfunction) forUInt64s in the tableau row that contain the sparsely selected qubits. This results in sparse scenarios where the qubits are close together (meaning packed into the sameUInt64) to be very fast. For more uniformly distributed qubit selections, the speed-up is not as significant, or even non-existent. Nevertheless, for very large system sizes, measurements with a few qubits (e.g. 3 or 4) qubits are still faster this way. Especially, two-qubit parity checks.However, right now, this requires computing the indices of the
UInt64s in which the qubits are packed, which does allocate. Maybe there is a better way to do this.TODO
There is still some cleanup to be done. As well as documentation and testing. However, I thought I'd share this idea already to get feedback if you are even interested in integrating this. I'm very open to any criticism and ideas to improve my code, as well as happy to work on this more.
I could also try to implement a two qubit parity measurement specialized function (analogous to the singe qubit functions), that would probably beat this one, if that is something you are interested in.
Benchmark
I did some rudimentary benchmarking. Attached you can find a plot of the results for a system of
2048qubits. The time is in seconds.The base case represents the
nqubitPauliOperator, measured using the existingproject!function.The best case represents the results for densely packed spares measurements.
The worst case for uniformly (maybe not the best way of doing this) distributed measurements.
I'm not sure what causes the jumps in the worst case.
