Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add StateMeasurement.process_density_matrix method #5628

Open
Alex-Preciado opened this issue May 2, 2024 · 5 comments · May be fixed by #5830
Open

Add StateMeasurement.process_density_matrix method #5628

Alex-Preciado opened this issue May 2, 2024 · 5 comments · May be fixed by #5830
Labels
enhancement ✨ New feature or request

Comments

@Alex-Preciado
Copy link
Contributor

Alex-Preciado commented May 2, 2024

Important Note

⚠️ This issue is part of an internal assignment and not meant for external contributors.

Context

Currently, measurements in PennyLane must define how to calculate the resulting number from "terminal" information, such as state, samples, or counts. For example, we have already implemented and required a StateMeasurement.process_state(state, wire_order) method. See the module documentation on measurements for more detailed information here.

But this method is specific to statevector-based simulators. To expand this framework to density-matrix based simulators like default.mixed, we need to add an additional method.

Implementation Details

This task is to add a new method to StateMeasurement:

class StateMeasurement(MeasurementProcess):

    def process_density_matrix(self, density_matrix, wire_order: Wires):
        raise NotImplementedError

And implement it for ProbabilityMP (bonus points for an implementation for StateMP, DensityMatrixMP)

Relevant functions include:

Additional Requirements

A completed PR would:

  • Include a docstring for the new StateMeasurement.process_density_matrix method
  • Include a changelog entry at doc/releases/changelog-dev.md. Make sure to include your name in the list of contributors at the bottom!
  • Add tests to tests/measurements/test_measurements.py, tests/measurements/test_state.py, and tests/measurements/test_probs.py
  • Pass all existing tests including black and pylint checks
@Alex-Preciado Alex-Preciado added the enhancement ✨ New feature or request label May 2, 2024
@JerryChen97
Copy link

Hi @Alex-Preciado , thank you for the detailed issue description. I've begun addressing this issue and would like to confirm my understanding of the methods process_density_matrix across ProbabilityMP, StateMP and DensityMatrixMP.

  1. ProbabilityMP Focuses on computing the final probability distribution from a density matrix or reduced density matrix by extracting the diagonal elements.
  2. StateMP Deals with pure states by returning the full (or reduced?) density matrix, depending on the specified wires.
  3. DensityMatrixMP is simliar to StateMP but but specifically tailored for handling the reduced density matrix, emphasizing mixed state representations.
    I also have a question about the class hierarchy in state.py, where StateMeasurement is the base class, with StateMP extending it, and DensityMatrixMP further extending StateMP. Given that density matrices generally represent a more generalized form of quantum states, with pure states being a special case, I'm curious about the design choice here. Is there a specific practical convenience or other consideration behind this hierarchy in PennyLane that I might not be aware of?

@JerryChen97
Copy link

Hi @Alex-Preciado , thank you for the detailed issue description. I've begun addressing this issue and would like to confirm my understanding of the methods process_density_matrix across ProbabilityMP, StateMP and DensityMatrixMP.

  1. ProbabilityMP Focuses on computing the final probability distribution from a density matrix or reduced density matrix by extracting the diagonal elements.
  2. StateMP Deals with pure states by returning the full (or reduced?) density matrix, depending on the specified wires.
  3. DensityMatrixMP is simliar to StateMP but but specifically tailored for handling the reduced density matrix, emphasizing mixed state representations.
    I also have a question about the class hierarchy in state.py, where StateMeasurement is the base class, with StateMP extending it, and DensityMatrixMP further extending StateMP. Given that density matrices generally represent a more generalized form of quantum states, with pure states being a special case, I'm curious about the design choice here. Is there a specific practical convenience or other consideration behind this hierarchy in PennyLane that I might not be aware of?

P.S. after double checking the state.py I feel StateMP.process_density_matrix should be like taking in a density matrix, checking if it is rank 1 and then produce the corresponding pure statevec

@Alex-Preciado
Copy link
Contributor Author

Thank you so much @JerryChen97!! @albi3ro from our team will offer some guidance very soon.

@albi3ro
Copy link
Contributor

albi3ro commented Jun 11, 2024

Thanks for the question @JerryChen97 .

Firstly, StateMP.process_density_matrix . We can go from state vector to density matrix, but not the other way around. We should just raise a ValueError there.

We have two "postprocessing" measurement interfaces, SampleMeasurement and StateMeasurement. These indicate what kinds of values the measurement can be calculated from. For example, DensityMatrixMP is only a StateMeasurement, as it can be analytically calculated from a state vector, but we don't have a way of calculating it from raw samples or counts. On the other hand, CountsMP is strictly a SampleMeasurement. We can't calculate it from a state vector, but we can calculate it from raw samples or another counts dictionary. Some measurements, like ExpectationMP or ProbabilityMP are both, and work in both finite shot and analytic mode.

SampleMeasurement currently has process_samples and process_counts methods. StateMeasurement has a process_state method and is gaining a process_density_matrix method.

As for the difference between StateMP and DensityMatrixMP, that inheritance structure is a bit of a historical remnant. At some point in the past, we represented the state vector by a StateMP with no wires, and a density matrix by a StateMP with wires. Some of our functions could also accept either a 1D state vector or a 2D density matrix. This caused issues with parameter broadcasting. Is a 4x4 array a density matrix or a state vector with a broadcast dimension of 4?

Due to these complications, we began separating state vector logic from density matrix logic. In most places in pennylane, we now treat state vectors and density matrices as distinct objects. To perform this separation smoothly and avoid breaking legacy code, we made the new DensityMatrixMP inherit from StateMP. Older devices that check things like if isinstance(mp, StateMP) and mp.wires will still be True with the newer DensityMatrixMP class.

Hope all that information helps :)

@JerryChen97
Copy link

Thanks for the question @JerryChen97 .

Firstly, StateMP.process_density_matrix . We can go from state vector to density matrix, but not the other way around. We should just raise a ValueError there.

We have two "postprocessing" measurement interfaces, SampleMeasurement and StateMeasurement. These indicate what kinds of values the measurement can be calculated from. For example, DensityMatrixMP is only a StateMeasurement, as it can be analytically calculated from a state vector, but we don't have a way of calculating it from raw samples or counts. On the other hand, CountsMP is strictly a SampleMeasurement. We can't calculate it from a state vector, but we can calculate it from raw samples or another counts dictionary. Some measurements, like ExpectationMP or ProbabilityMP are both, and work in both finite shot and analytic mode.

SampleMeasurement currently has process_samples and process_counts methods. StateMeasurement has a process_state method and is gaining a process_density_matrix method.

As for the difference between StateMP and DensityMatrixMP, that inheritance structure is a bit of a historical remnant. At some point in the past, we represented the state vector by a StateMP with no wires, and a density matrix by a StateMP with wires. Some of our functions could also accept either a 1D state vector or a 2D density matrix. This caused issues with parameter broadcasting. Is a 4x4 array a density matrix or a state vector with a broadcast dimension of 4?

Due to these complications, we began separating state vector logic from density matrix logic. In most places in pennylane, we now treat state vectors and density matrices as distinct objects. To perform this separation smoothly and avoid breaking legacy code, we made the new DensityMatrixMP inherit from StateMP. Older devices that check things like if isinstance(mp, StateMP) and mp.wires will still be True with the newer DensityMatrixMP class.

Hope all that information helps :)

Thank you so much! This is very much clear to me now; I also sensed the implied distinct treatments between StateMP and DensityMatrixMP though they seemed to have some inheritance from the outside.

Now I will block the StateMP.process_density_matrix with ValueError as suggested

@JerryChen97 JerryChen97 linked a pull request Jun 11, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement ✨ New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants