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

Pauli X, Y, Z measurement instructions #9269

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

pedrorrivero
Copy link
Member

@pedrorrivero pedrorrivero commented Dec 8, 2022

Summary

This PR introduces MeasureX, MeasureY, and MeasureZ instructions with the corresponding measure_x, measure_y, and measure_z methods in QuantumCircuit.

Details and comments

The Measure instruction is used as the parent class for all three new instructions, and an optional basis class attribute is added. Otherwise it is left untouched for backwards compatibility.

Ideally, I would suggest progressively moving away from Measure and towards MeasureZ (we can always keep the QuantumCircuit.measure method as an alias), keeping the former exclusively as a common parent (abstract) class. Suggestions on how to proceed with this —if possible— would be greatly appreciated.

@qiskit-bot
Copy link
Collaborator

Thank you for opening a new pull request.

Before your PR can be merged it will first need to pass continuous integration tests and be reviewed. Sometimes the review process can be slow, so please be patient.

While you're waiting, please feel free to review other open PRs. While only a subset of people are authorized to approve pull requests for merging, everyone is encouraged to review open pull requests. Doing reviews helps reduce the burden on the core team and helps make the project's code better for everyone.

One or more of the the following people are requested to review this:

Comment on lines -385 to +391
directives = ["measure"]
if not getattr(operation, "_directive", False) and operation.name not in directives:
directives = []
if (
not getattr(operation, "_directive", False)
and not isinstance(operation, Measure)
and operation.name not in directives
):
Copy link
Member Author

Choose a reason for hiding this comment

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

After introducing the isinstance check to harness subclassing, directives became empty. Should it be removed? If kept, I would suggest turning it into a set instead of a list.

@coveralls
Copy link

coveralls commented Dec 9, 2022

Pull Request Test Coverage Report for Build 3669879986

  • 44 of 70 (62.86%) changed or added relevant lines in 10 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.02%) to 84.533%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/visualization/circuit/latex.py 3 5 60.0%
qiskit/visualization/circuit/matplotlib.py 1 3 33.33%
qiskit/circuit/quantumcircuit.py 4 7 57.14%
qiskit/visualization/circuit/text.py 7 10 70.0%
qiskit/circuit/measure.py 17 33 51.52%
Totals Coverage Status
Change from base Build 3658575673: -0.02%
Covered Lines: 63594
Relevant Lines: 75230

💛 - Coveralls

@yaelbh
Copy link
Contributor

yaelbh commented Dec 11, 2022

@pedrorrivero Thanks for resuming #7716. I recommend to carefully read the discussion there and in #5311. In particular, there has been a question about the RemoveFinalMeasurements pass manager. What's its expected behavior for MeasureX and MeasureY, and is it the actual behavior implemented in the code?

@nonhermitian
Copy link
Contributor

nonhermitian commented Dec 11, 2022

I am also curious how this works with the ResetAfterMeasureSimplification pass that is extremely important to use on IBM Quantum systems for dynamic circuits? Does one have to run this before decomposing to basis gates to get the expected result?

Also, is there a pass that removes the extra gates after the measurement if they come at the end of a circuit?

@pedrorrivero
Copy link
Member Author

pedrorrivero commented Dec 11, 2022

Hi @yaelbh and @nonhermitian ! Thanks so much for your comments.

I have not implemented that yet, left it for last to have more time to think, but this is what I am planning:

  1. RemoveFinalMeasurements will operate by checking isinstance(..., Measure), leveraging the parent-child relationship that I set up, and therefore removing these new instructions as well (as @1ucian0 requested).
  2. If the gate is decomposed before applying RemoveFinalMeasurements, the latter becomes a no-op due to the extra gates added after measuring to return to the computational basis (i.e. except for MeasureZ). This may not be ideal, but feels like a tradeoff for users to make. I will take a look at ResetAfterMeasureSimplification @nonhermitian , there currently is not a pass that removes the extra gates after the measurement if they come at the end of a circuit, would it be required for this PR?
  3. @ikkoham suggested an option where one could keep the basis rotation and remove the final measurements. This is not implemented here, but it would be good for another PR. My suggestion would be to extend the the functionality of remove_final_measurements so that that it accepts an optional keep_basis_rotation kwarg. Depending on how we address [2], this could be achieved by decomposing, removing the extra gates, and removing final measurements.
  4. As for the discussion on calibration, I like this idea a lot. As a matter of fact, my original inspiration for this PR came from considering adding these gates to the basis set and letting the hardware handle base rotations in the most efficient way possible —abstracting it out for the users. This could be particularly beneficial for the combination Sdg•H in MeasureY. Alternatively, it could be handled at compile time. If certain backend does not support them in the basis set, it could always be handled via decomposition. This falls outside the scope of this PR however, @nkanazawa1989 @ajavadia.
  5. This implementation seems more versatile than to "build a mechanism in Aer that detects Pauli measurement instructions", which was the suggested alternative.

Thoughts anyone? Thanks!

Copy link
Member

@jakelishman jakelishman left a comment

Choose a reason for hiding this comment

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

I am keen to see X and Y measurements implemented somehow in Qiskit - it certainly seems like a generally useful feature. Thanks for picking up the thread of work again.

I'm concerned with introducing inheritance to the data model, though - in this situation it could be acceptable, but I'm not certain. It could be that OO hierarchy isn't the best fit possible - it definitely isn't for other quantum operations. Aside from those given in the PR, I can think of a couple of other potential advantages of subclassing though, but it's a bit long for me to type out on my phone.

I'd like to be involved in more discussion on this once I'm back from holiday in January - I can't really give a full review or think things through completely right now.

On Paul's point: in general, we should assume that most non-Z measurements will be decomposed/basis-translated before ResetSimplification and RemoveFinalMeasurements run; it's certainly the case right now, and while that could change, I can imagine other cases where Measure might appear in compound instructions that we'd want to handle well. I think it would be completely acceptable (and clearer) to handle that in a follow-up PR, though.

\\endxy
}
\\POS ="i",
"i"+UR;"i"+UL **\\dir{-};"i"+DL **\\dir{-};"i"+DR **\\dir{-};"i"+UR **\\dir{-},
Copy link
Member

Choose a reason for hiding this comment

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

(On my phone so I can't select properly.)

This looks like qcircuit code. That's GPL licensed, so we legally cannot include it, or code derived from it, in Qiskit. We need to be really careful when copying code blocks like this - attribution is not generally sufficient. It's legally tricky for us now even if you try and write your own implementation, because it's hard to be certain that it wouldn't be a derived work.

Perhaps we can use their \measure macro somehow?

Copy link
Member Author

@pedrorrivero pedrorrivero Dec 11, 2022

Choose a reason for hiding this comment

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

Ah! Good catch, I have definitely derived it from their code.

I did try to use their macro but it proved to be very challenging (it builds an image and you lose the reference points after wrapping it up) so I dropped down to base xypic code and recreated part of what they where doing adding the extra pieces. I have reached out to them to see if I can contribute this to their package.

Not sure how to address this otherwise. I'll think about it, thanks for bringing this up.

Copy link
Member Author

Choose a reason for hiding this comment

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

I opened a PR to contribute this piece of code to qcircuit

import warnings

from qiskit.circuit.instruction import Instruction
from qiskit.circuit.exceptions import CircuitError


# Measure class kept for backwards compatibility, and repurposed
# as a common parent class for all measurement instructions.
class Measure(Instruction):
Copy link
Member

Choose a reason for hiding this comment

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

It's possible that we could accept an inheritance relationship here, but I don't think it's for certain the correct way of doing things, over (for example) a set of flags defined Instruction or Operation. This particular inheritance is definitely not safe, though - Measure is, and needs to remain, a measure in the Z basis, so MeasureX isn't an instance of it. There's also the false abstraction here that the base class is only abstract as far as a single-qubit Pauli-basis measurement, which isn't the most general type.

Aside from those abstraction/false-hierarchy issues, another thing to consider with inheritance is that we would need to work out how external / further subclasses of BaseMeasure (or whatever) would be safely serialised/deserialised by QPY - this PR adds an inheritance structure to instructions that is deliberately avoided in our data model elsewhere. This has some wide-ranging implications that I'm too "on holiday" to think through properly right now (sorry).

Copy link
Member Author

Choose a reason for hiding this comment

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

I see 🤔 let's pick this up again once you come back then! Thanks for the detailed explanation

@nonhermitian
Copy link
Contributor

I would also add that this code might be hardware specific. Ie there might be hardware that can natively measure in more than one basis. At present, this is a hypothetical and/or I didn't bother to do my homework, but if that situation ever arises, then this code doesn't cover that.

@pedrorrivero
Copy link
Member Author

Thanks @nonhermitian, I am not sure I follow though 🤔

If some hardware shows up in the future that can handle (say) MeasureX directly, what would be preventing it from not decomposing the gate and simply performing it? Isn't this effectively another flavor of what I was discussing in [4] related to calibration?

@pedrorrivero
Copy link
Member Author

pedrorrivero commented Dec 11, 2022

Per @jakelishman's comments, it may be better to follow this data model instead.

Open to comments/suggestions!

pauli_measurements

@nonhermitian
Copy link
Contributor

Perhaps it does. However, I am not sure what happens to a decomposition over eg measure_x, measure_z, and measure. Also where does the measurement info go? Hopefully not basis gates as we have abused that notion enough. Perhaps it is handled in backend v2, but I have not played with that.

@jrj-d
Copy link

jrj-d commented Mar 4, 2023

Hi everyone! Thanks for the work on this PR and the insightful discussions. I work at Alice & Bob, a company developing cat qubits. MeasureX is an instruction that we support natively, so I'm eager to see it included in Qiskit.
I worte a message mainly to say that harware supporting measurement in other bases does exist :)
I'm not familiar with the internals of Qiskit yet, but I'll dig into it and contribute to the discussions.

(On top of this PR, we'll also need support for measurements in other bases in qiskit-aer, so that we can attach a specific noise to MeasureX for simulation purposes. I'll try to contribute there as well. But I understand this is unrelated to this PR.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add x and y measurements
8 participants