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 measurement gate #41

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft

Add measurement gate #41

wants to merge 5 commits into from

Conversation

stavros11
Copy link
Member

Fixed #30 by adding a single-qubit measurement gate. As discussed registers are dropped and will be only available in qibo (not in core and the backends). As a result, I simplified a bit the MeasurementOutcomes object.

I also dropped MeasurementResult. We may need to bring part of it back when we implement collapse, however I’ll leave that for when we handle that, not in the current PR. For now, only non-collapse measurements at the end of the circuit are supported.

I will add some tests including measurements.

src/circuit.rs Outdated Show resolved Hide resolved
Comment on lines +152 to +162
pub fn measured_elements(&self) -> Vec<usize> {
self.gates.iter().enumerate()
.filter_map(|(gid, gate)| {
if let Gate::One(One::M) = gate {
Some(self.elements(gid)[0])
} else {
None
}
})
.collect()
}
Copy link
Member

Choose a reason for hiding this comment

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

Do we really need this function? What about mid-circuit measurements? (collapsing and not)

Copy link
Member Author

Choose a reason for hiding this comment

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

Do we really need this function?

I think we need a way to tell which qubits are measured. Currently qibo Circuit is carrying a list for this https://github.com/qiboteam/qibo/blob/049ad8d3f75653323a50fe7b78d2ba14f772f763/src/qibo/models/circuit.py#L183

I guess I could also filter in the backend, but I thought this will be relevant for all backends.

What about mid-circuit measurements? (collapsing and not)

First, are there mid-circuit measurements that are not collapsing? I think in qibo, only collapse measurements are allowed mid-circuit. Do we want to extend this?

Either way, this PR will not work for such mid-circuit measurements. I am assuming (but not verifying) that all measurements come at the end of the wire. These are the only measurements relevant for MeasurementOutcomes/CircuitResult in qibo. When we add support for mid-circuit measurements, this function may need to change, but I am not sure yet how collapse will be handled (if we need a different gate, or we can use the same M).

Copy link
Member

Choose a reason for hiding this comment

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

Collapse is definitely going to be different from non-collapsing measurement. But I wonder whether we need a non-collapsing final measurements anyhow:

  • hardware will only support collapsing measurements
  • tensor networks will not support measurements at all
  • state vector simulation will compute the whole state vector, so measuring at the end could well be an operation fully separate from the execution

So, final measurements could be completely decoupled from execution, and part of the state vector (/density matrix) manipulation library.

Instead, mid-circuit measurements (even non-collapsing) should be applied during execution, so they require to be specified within the circuit.
If we do not support mid-circuit non-collapsing, we may even consider not adding non-collapsing measurements at all in qibo-core. Isn't it?

Copy link
Member Author

@stavros11 stavros11 Jul 2, 2024

Choose a reason for hiding this comment

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

Instead, mid-circuit measurements (even non-collapsing) should be applied during execution, so they require to be specified within the circuit. If we do not support mid-circuit non-collapsing, we may even consider not adding non-collapsing measurements at all in qibo-core. Isn't it?

Indeed, that's why I think that we don't need any other measurement gate in qibo-core other than M. We would only need two gates if we support mid-circuit non-collapsing measurement, but is there any argument to support this if it cannot be done on hardware (I am actually not sure about that)? Note that in simulation this can also be done by chaining multiple circuits, or using the State callback to sample intermediate states.

So, final measurements could be completely decoupled from execution, and part of the state vector (/density matrix) manipulation library.

Other than this function, which I can easily move somewhere else, they are decoupled from execution. Everything measurement related happens in result.py which is in some sense the state manipulation file. However, I think the state objects need to be in qibo-core because they are the output of execution, so they are not fully decoupled. The backends need to use them if we want to standardize return types.

But I wonder whether we need a non-collapsing final measurements

Do you mean that we should not add measurements at all at the end of the qibo-core circuit?

I think the main issue if we treat M as collapse measurement (which seems to be the case), is that if it is at the end of the wire, collapsing in simulation would just waste information. Therefore, final measurements are useless for simulation, however we still need them for hardware (to know where to play readout pulses).

Copy link
Member

Choose a reason for hiding this comment

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

Note that in simulation this can also be done by chaining multiple circuits, or using the State callback to sample intermediate states.

This is the main argument: in practice it would be callback gate (possibly a specialization of State, that will only save the samples, and not the full state).

However, I think the state objects need to be in qibo-core because they are the output of execution, so they are not fully decoupled. The backends need to use them if we want to standardize return types.

So, we are essentially using them to trace part of the final state vector before returning. Isn't it?

Do you mean that we should not add measurements at all at the end of the qibo-core circuit?

We could always return the full state vector, and that's it. In that case, we wouldn't need non-collapsing measurements at all.

I think the main issue if we treat M as collapse measurement (which seems to be the case), is that if it is at the end of the wire, collapsing in simulation would just waste information. Therefore, final measurements are useless for simulation, however we still need them for hardware (to know where to play readout pulses).

We could treat M only as a collapsing measurement, and ignore it in simulation. Or we can have both M and MC, and use M to throw away information before returning from the backend (though this would only be useful on cloud, and whenever you're forced to download/copy the full state vector - and it could be even specified as a separate parameter of the execution).

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for the recap!

I'd be in for 2., also because I'm not sure about what is the -. It will make the behavior crystal clear, and we save the representation of a bunch of not allowed circuits. If any callback-like inspection is needed, we'll support the callbacks anyhow.

But I'd like to understand better the -: to me, if one doesn't want to lose information, should simply avoid pushing any collapsing measurement, and just compute the unitary.

Copy link
Member Author

Choose a reason for hiding this comment

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

But I'd like to understand better the -: to me, if one doesn't want to lose information, should simply avoid pushing any collapsing measurement, and just compute the unitary.

In qibo if you do

c = Circuit(1)
c.add(gates.H(0))
c.add(gates.M(0))
result = c(nshots=1000)

you will get a CircuitResult object that contains the state vector (in this case |0>+|1> normalized) but also can be used to get samples/frequencies on the measured qubits.

If we collapse during M, then we lose the state vector, as it will be either |0> or |1>. In fact, since we asked for 1000 shots it will be a list of some |0>s and some |1>s or just not well-defined (depending on what we decide).

For qibo-core purposes, solution 2 sounds good, but some care may be needed on the qibo side, if we want to maintain the current behavior.

I will try to update this PR to the new direction (M always collapse), however for that there may be some overlap with #32. We may need to partially address how to store measured shots if we want to use them to condition other gates, but if possible I would avoid going to deep in this first iteration, as this is not much a priority.

Copy link
Member

@alecandido alecandido Jul 2, 2024

Choose a reason for hiding this comment

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

If we collapse during M, then we lose the state vector

Yes, this I understand. But the option would be to just omit the measurement from the circuit. In that case, there would be no ambiguity, and you could get the state vector, which you could sample.

I would ask for @igres26 advice whether this is acceptable. For sure, it would be breaking in Qibo, but it will be properly documented.

We could even support the old behavior, but it will require some more work on the Qibo side.

I will try to update this PR to the new direction (M always collapse), however for that there may be some overlap with #32. We may need to partially address how to store measured shots if we want to use them to condition other gates, but if possible I would avoid going to deep in this first iteration, as this is not much a priority.

No problem in partially addressing #32 as well, since we decided that we almost don't need to represent #30.
However, it's fine to put your threshold wherever you feel best. If the PR will be smaller, it's only better, and we can continue in further ones.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this I understand. But the option would be to just omit the measurement from the circuit. In that case, there would be no ambiguity, and you could get the state vector, which you could sample.

If you mean the user would have to omit the measurement (we change the current behavior), this is a bit against one of our previous goals in qibo, which was to make simulation and hardware execution as symmetric as possible. In practice, the goal is to support something like:

c = Circuit(1)
c.add(gates.H(0))
c.add(gates.M(0))

qibo.set_backend("numpy")
sim_result = c(nshots=1000)

qibo.set_backend("qibolab", platform=...)
hw_result = c(nshots=1000)

and then you can do .samples() or .frequencies() in both results, but sim_result also contains the whole state for exact calculation of probabilities, etc..

If now the user has to manually drop the measurement for simulation, this symmetry is no longer there.

We could even support the old behavior, but it will require some more work on the Qibo side.

This is possible and would solve the above problem, but it would have some side-effects. In particular, the translation of qibo Circuit to qibo_core Circuit will be different depending on the operation. If we want to use a simulation backend on a circuit with non-collapse measurements, we would have to ignore measurements in the translation. If we use a hardware backend we do not ignore. If we want to draw, we also don't ignore, etc.. I do not see any issue with this, so it could be an acceptable solution.

Copy link
Member

Choose a reason for hiding this comment

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

It is possible to do it even at the level of the backend: state vectors backends, in non-repeated mode, could just drop the measurements during execution.

So, there would be only collapsing, and they are simply ignored when you do not collapse.

@stavros11
Copy link
Member Author

stavros11 commented Jul 4, 2024

If we go with a single collapse M in qibo_core, I am no longer convinced that we need any CircuitResult-like objects here. We could still reconstruct them in qibo to keep the current interface, but they won't be available in the backends.

In particular:

Execution type No measurements With measurements
State vector simulation array (*) dict: {gid: samples}
Density matrix simulation array (**) array + dict: {gid: samples}
Hardware None (or raise error) dict: {gid: samples}

(*) repeated execution is needed for nshots > 1,
(**) this is the only complicate case where a custom result object could be handy, but it could also just be a tuple.

@alecandido could you add tensor networks or other potential execution types to the table and confirm that array and dict are sufficient to cover all the different return cases? (in terms of not losing information)

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.

Measurement gate
2 participants