ProjectQ
ProjectQ copied to clipboard
Bizarre IndexError if attempt to measure a qubit after a Control block
Repro:
from projectq.ops import X, Measure
import projectq
import projectq.meta
eng = projectq.MainEngine()
q0 = eng.allocate_qubit()
with projectq.meta.Control(eng, q0):
X | q0
# eng.flush()
Measure | q0
print(int(q0))
This yields:
Traceback (most recent call last):
File "bell_state.py", line 18, in <module>
Measure | q0
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/ops/_gates.py", line 284, in __or__
apply_command(cmd)
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/ops/_command.py", line 58, in apply_command
engine.receive([cmd])
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/cengines/_main.py", line 266, in receive
self.send(command_list)
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/cengines/_main.py", line 288, in send
raise compact_exception # use verbose=True for more info
IndexError: list index out of range
raised in:
' File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/cengines/_optimize.py", line 136, in _optimize'
' if inv == self._l[idx][i + 1]:'
With verbose=True
:
Traceback (most recent call last):
File "bell_state.py", line 18, in <module>
Measure | q0
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/ops/_gates.py", line 284, in __or__
apply_command(cmd)
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/ops/_command.py", line 58, in apply_command
engine.receive([cmd])
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/cengines/_main.py", line 266, in receive
self.send(command_list)
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/cengines/_main.py", line 275, in send
self.next_engine.receive(command_list)
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/cengines/_tagremover.py", line 58, in receive
self.send([cmd])
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/cengines/_basics.py", line 185, in send
self.next_engine.receive(command_list)
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/cengines/_optimize.py", line 244, in receive
self._cache_cmd(cmd)
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/cengines/_optimize.py", line 224, in _cache_cmd
self._check_and_send()
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/cengines/_optimize.py", line 196, in _check_and_send
self._optimize(i)
File "/var/home/ryan/.virtualenvs/projectq/lib/python3.7/site-packages/projectq/cengines/_optimize.py", line 136, in _optimize
if inv == self._l[idx][i + 1]:
IndexError: list index out of range
Of course, eng.flush()
fixes the issue, but this should probably raise that relevant exception instead of the more obscure IndexError...
On that note, is there a reason why this doesn't work:
from projectq.ops import X, Measure
import projectq
import projectq.meta
eng = projectq.MainEngine()
q0 = eng.allocate_qubit()
X | q0
eng.flush()
Measure | q0
assert int(q0) == 1 # okay
# should flip q0 back to 0, since it being 1 should enter the control block
with projectq.meta.Control(eng, q0):
X | q0
eng.flush()
Measure | q0
assert int(q0) == 0 # fail
EDIT: I just realized my eng.flush()
's were before the Measure
statements in order to avoid the crash, but aren't they supposed to be after?
EDIT 2: The same crash can be reproduced via CNOT | (q0, q0)
.
eng.flush()
statements need to be put before accessing the result of some measurements.
Now, I am not sure having a CNOT
gate with identical control and target qubits makes a lot of sense, because by definition, the control target should not be modified after the application of the gate. Also, it is usually understood that 2-qubit gate get applied on two different qubits.
It is true, however, that ProjectQ currently does not checks whether control and target qubits are disjoints.
Yeah identical qubits in a CNOT isn't useful or even allowed by most frameworks, but crashing with an obscure IndexError isn't very helpful in that case either...
Yeah identical qubits in a CNOT isn't useful or even allowed by most frameworks, but crashing with an obscure IndexError isn't very helpful in that case either...
I agree! So I'll keep this issue open until we fix this (hopefully sometime soon)