Open IlanIwumbwe opened 1 week ago
I think this is here: https://github.com/quantumlib/Cirq/blob/d74e0dce73adf45f15b873bf28236ef355d960ce/cirq-core/cirq/sim/simulator.py#L986-L992
This is the code that splits the circuit into a unitary ("predicate/matching") prefix and a non-unitary suffix, so that the result of the unitary prefix can be cached and reused for each repetition, so that only the non-unitary part has to be run subsequently.
It looks like the code places the empty classical controlled circuit in the prefix, since it has no qubits, so it'll get executed before the measurement (which goes in the suffix). I can't remember offhand why that's two separate if
blocks. Seems like
if not predicate(op) or not qs.isdisjoint(blocked_qubits):
general_part.append(op)
blocked_qubits |= qs
else:
matching_part.append(op)
would be more succinct and fix the error?
However, to be thorough, the function should be revised to take measurement keys into account just like qubits: once an op with a measurement key M has been allocated to the suffix ("general_part"), any subsequent op with the same measurement key M should also go into the suffix. So just set up a "blocked_measurement_keys" set and check those too e.g. if not predicate(op) or not qs.isdisjoint(blocked_qubits) or not keys.isdisjoint(blocked_keys)
. The normal simulator uses is_unitary
as predicate
, but other simulators use other predicates, so the same bug might happen in other simulators unless the measurement keys are explicitly taken into account.
I see, that makes sense.
I was going to say an even easier fix would be to ensure anything that touches a measurement key should go in the suffix. But it turns out that's actually not always the case: in principle, a classical simulator should put everything in the prefix. The only circuits it can handle are deterministic anyway, so samplers should simulate the circuit once and just return the same result N times rather than re-running the simulation. (Currently it's not implemented that way; one would have to override _can_be_in_run_prefix
on ClassicalSimulator
to return True
always. Granted, nobody is running classical simulations with large repeat counts, but still, it's an easy improvement).
So, long story short, this should be fixed the "right" way by explicitly taking measurement keys into account, as described above.
Benny and I found this bug
Description of the issue Controlled empty subroutine causes
ValueError
on simulatorHow to reproduce the issue
Uncommenting the
Y
gate within the subroutine makes this work. Although users may not do something like this, it would probably be nice if this was treated like an identity instead.Cirq version You can get the cirq version by printing
cirq.__version__
. From the command line: 1.4.1