pyquil icon indicating copy to clipboard operation
pyquil copied to clipboard

IndexError in _extract_bitstrings when measuring the same qubit twice on a QPU

Open appleby opened this issue 6 years ago • 0 comments

Pre-Report Checklist

  • [ ] I am running the latest versions of pyQuil and the Forest SDK
  • [x] I checked to make sure that this bug has not already been reported

Issue Description

When running on a QPU, measuring the same qubit 2-or-more times results in an IndexError in pyquil.api._qpu._extract_bitstrings.

Measuring the same qubit multiple times is admittedly a slightly odd thing to do, since QPU programs are restricted to protoquil, i.e. all MEASURE instructions must come at the end of the program with no gates interleaved.

I only noticed this while staring at the implementation of _extract_bitstrings in order to port it to a lisp project that needs something similar.

The crux of the issue is that we compile a list of ro_sources for the program, and then use that in _extract_bitstrings to munge the results returned by the QPU into the expected shape. The docstring for _extract_bitstrings describes ro_sources like so:

:param ro_sources: Specification of the ro_sources, cf
:py:func:`pyquil.api._compiler._collect_classical_memory_write_locations`.
It is a list whose value ``(q, m)`` at index ``addr`` records that the ``m``-th 
measurement of qubit ``q`` was measured into ``ro`` address ``addr``. 
A value of `None` means nothing was measured into ``ro`` address ``addr``.

but then in the body of _extract_bitstrings we find

            qubit, meas_idx = src
            buf = buffers[f"q{qubit}"]
            if buf.ndim == 1:
                buf = buf.reshape((num_shots, 1))
            bitstrings[:, col_idx] = buf[:, meas_idx]

so when buf.ndim == 1, buf is reshaped into (num_shots, 1), but if qubit was measured more than once, meas_idx might be > 0 resulting in IndexError.

For example, for the program given below, ro_sources will be [(0, 0), (0, 1)], but buffers["q0"] will be a 1-element array.

How to Reproduce

Run the following snipped on a QPU

Code Snippet

from pyquil import Program, get_qc

qc = get_qc('Aspen-4-2Q-G')
p = Program('''DECLARE ro BIT[2]
H 0
MEASURE 0 ro[0]
MEASURE 0 ro[1]
''')
exe = qc.compile(p, protoquil=True)
qc.run(exe)

Error Output

(venv) [ON QPU] [forest@8431-qmi ~]$ python repeated_ro.py
Traceback (most recent call last):
  File "repeated_ro.py", line 12, in <module>
    print(qc.run(exe))
  File "/home/forest/.virtualenvs/venv/lib/python3.6/site-packages/pyquil/api/_error_reporting.py", line 251, in wrapper
    val = func(*args, **kwargs)
  File "/home/forest/.virtualenvs/venv/lib/python3.6/site-packages/pyquil/api/_quantum_computer.py", line 137, in run
    return self.qam.run().wait().read_memory(region_name="ro")
  File "/home/forest/.virtualenvs/venv/lib/python3.6/site-packages/pyquil/api/_error_reporting.py", line 251, in wrapper
    val = func(*args, **kwargs)
  File "/home/forest/.virtualenvs/venv/lib/python3.6/site-packages/pyquil/api/_qpu.py", line 228, in run
    bitstrings = _extract_bitstrings(ro_sources, results)
  File "/home/forest/.virtualenvs/venv/lib/python3.6/site-packages/pyquil/api/_qpu.py", line 71, in _extract_bitstrings
    bitstrings[:, col_idx] = buf[:, meas_idx]
IndexError: index 1 is out of bounds for axis 1 with size 1

Environment Context

Operating System: QMI

Python Version (python -V): 3.6.8

Quilc Version (quilc --version): 1.16.1

QVM Version (qvm --version): 1.15.3

Python Environment Details (pip freeze or conda list):

antlr4-python3-runtime==4.7.2
attrs==19.3.0
backcall==0.1.0
bleach==3.1.0
certifi==2019.11.28
chardet==3.0.4
cycler==0.10.0
decorator==4.4.1
defusedxml==0.6.0
entrypoints==0.3
idna==2.8
immutables==0.6
importlib-metadata==1.5.0
ipykernel==5.1.4
ipython==7.11.1
ipython-genutils==0.2.0
jedi==0.16.0
Jinja2==2.11.0
json5==0.8.5
jsonschema==3.2.0
jupyter-client==5.3.4
jupyter-core==4.6.1
jupyterlab==1.2.6
jupyterlab-server==1.0.6
kiwisolver==1.1.0
MarkupSafe==1.1.1
matplotlib==3.1.2
mistune==0.8.4
msgpack==0.6.2
nbconvert==5.6.1
nbformat==5.0.4
networkx==2.4
notebook==6.0.3
numpy==1.18.1
pandas==1.0.0
pandocfilters==1.4.2
parso==0.6.0
pexpect==4.8.0
pickleshare==0.7.5
prometheus-client==0.7.1
prompt-toolkit==3.0.3
ptyprocess==0.6.0
Pygments==2.5.2
pyparsing==2.4.6
pyquil==2.17.0
pyrsistent==0.15.7
python-dateutil==2.8.1
python-rapidjson==0.9.1
pytz==2019.3
pyzmq==18.1.1
requests==2.22.0
rpcq==3.0.0
ruamel.yaml==0.16.7
ruamel.yaml.clib==0.2.0
scipy==1.4.1
seaborn==0.10.0
Send2Trash==1.5.0
six==1.14.0
terminado==0.8.3
testpath==0.4.4
tornado==6.0.3
tqdm==4.42.0
traitlets==4.3.3
urllib3==1.25.8
wcwidth==0.1.8
webencodings==0.5.1
zipp==2.1.0

appleby avatar Mar 12 '20 23:03 appleby