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

[BUG] Error Exporting QASM File: MidMeasureMP Operation Not Supported #6900

Open
1 task done
MattePalte opened this issue Jan 29, 2025 · 2 comments
Open
1 task done
Labels
bug 🐛 Something isn't working

Comments

@MattePalte
Copy link

Expected behavior

The expected behavior is that the circuit imported from QASM with a final measurement can be re-exported to QASM without any errors. Specifically, the measurement operation should be preserved and not converted to a mid-measure operation.

Actual behavior

The actual behavior is that when trying to re-export the circuit to QASM, a ValueError is raised stating that the operation MidMeasureMP is not supported by the QASM serializer. This is unexpected because the initial QASM file only contained a final measurement, and it is unclear why the measurement is being converted to a mid-measure operation.

Additional information

To reproduce the issue, run the following code.
The error is 100% reproducible and is not dependent on any specific hardware or environment. The issue appears to be with the way Pennylane handles measurement operations when importing and exporting circuits to and from QASM.
Let me know if you need more info

Source code

qasm_content = """
OPENQASM 2.0;
include "qelib1.inc";
qreg q[1];
creg c[1];
x q[0];
measure q[0] -> c[0];
"""
import pennylane as qml

circuit = qml.from_qasm(qasm_content)

print(qml.draw(circuit)())
# OUTPUT:
# 0: ──X──┤↗├─┤

# EXPORTING TO QASM
from pennylane.tape import make_qscript
qs = make_qscript(circuit)()
qasm_str_pennylane = qs.to_openqasm()
print(qasm_str_pennylane)

# OUTPUT:
# raises ValueError: Operation MidMeasureMP not supported by the QASM serializer

Tracebacks

``python
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File python3.10/site-packages/pennylane/tape/qscript.py:1178, in QuantumScript.to_openqasm(self, wires, rotations, measure_all, precision)
   1177 try:
-> 1178     gate = OPENQASM_GATES[op.name]
   1179 except KeyError as e:

KeyError: 'MidMeasureMP'

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
Cell In[44], line 3
      1 from pennylane.tape import make_qscript
      2 qs = make_qscript(circuit)()
----> 3 qasm_str_pennylane = qs.to_openqasm()
      4 print(qasm_str_pennylane)

File python3.10/site-packages/pennylane/tape/qscript.py:1180, in QuantumScript.to_openqasm(self, wires, rotations, measure_all, precision)
   1178     gate = OPENQASM_GATES[op.name]
   1179 except KeyError as e:
-> 1180     raise ValueError(f"Operation {op.name} not supported by the QASM serializer") from e
   1182 wire_labels = ",".join([f"q[{wires.index(w)}]" for w in op.wires.tolist()])
   1183 params = ""

ValueError: Operation MidMeasureMP not supported by the QASM serializer

System information

Name: PennyLane
Version: 0.38.0
Summary: PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
Home-page: https://github.com/PennyLaneAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: .../lib/python3.10/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, packaging, pennylane-lightning, requests, rustworkx, scipy, toml, typing-extensions
Required-by: PennyLane-qiskit, PennyLane_Lightning

Platform info:           Linux-5.15.0-130-generic-x86_64-with-glibc2.35
Python version:          3.10.14
Numpy version:           1.26.4
Scipy version:           1.14.1
Installed devices:
- qiskit.aer (PennyLane-qiskit-0.38.1)
- qiskit.basicaer (PennyLane-qiskit-0.38.1)
- qiskit.basicsim (PennyLane-qiskit-0.38.1)
- qiskit.remote (PennyLane-qiskit-0.38.1)
- default.clifford (PennyLane-0.38.0)
- default.gaussian (PennyLane-0.38.0)
- default.mixed (PennyLane-0.38.0)
- default.qubit (PennyLane-0.38.0)
- default.qubit.autograd (PennyLane-0.38.0)
- default.qubit.jax (PennyLane-0.38.0)
- default.qubit.legacy (PennyLane-0.38.0)
- default.qubit.tf (PennyLane-0.38.0)
- default.qubit.torch (PennyLane-0.38.0)
- default.qutrit (PennyLane-0.38.0)
- default.qutrit.mixed (PennyLane-0.38.0)
- default.tensor (PennyLane-0.38.0)
- null.qubit (PennyLane-0.38.0)
- lightning.qubit (PennyLane_Lightning-0.38.0)

Existing GitHub issues

  • I have searched existing GitHub issues to make sure the issue does not already exist.
@MattePalte MattePalte added the bug 🐛 Something isn't working label Jan 29, 2025
@MattePalte
Copy link
Author

Checking this test file tests/circuit_graph/test_qasm.py it seems that the final measurement is not among those operation that should be impossible to support in the QASM serializer, like DoubleExcitationPlus:

def test_unsupported_gate(self):

What about something like this to handle the conversion of MidMeasureMP to QASM measurement?

At this location:

for op in operations:

Apply this change:

for op in operations:
    # NEW Code ----------------------------------------------
    if op.name == "MidMeasureMP":
        # Convert MidMeasureMP to QASM measurement
        for wire in op.wires.tolist():
            qasm_str += f"measure q[{wires.index(wire)}] -> c[{wires.index(wire)}];\n"
        continue
    # ------------------------------------------------------

    try:
        gate = OPENQASM_GATES[op.name]
    except KeyError as e:
        raise ValueError(f"Operation {op.name} not supported by the QASM serializer") from e

    wire_labels = ",".join([f"q[{wires.index(w)}]" for w in op.wires.tolist()])
    params = ""

    if op.num_params > 0:
        # If the operation takes parameters, construct a string
        # with parameter values.
        if precision is not None:
            params = "(" + ",".join([f"{p:.{precision}}" for p in op.parameters]) + ")"
        else:
            # use default precision
            params = "(" + ",".join([str(p) for p in op.parameters]) + ")"

    qasm_str += f"{gate}{params} {wire_labels};\n"

Let me know it that could be a good idea to implement it to fix it. I can try to make a PR for that.

@albi3ro
Copy link
Contributor

albi3ro commented Jan 29, 2025

Thanks for opening this issue @MattePalte .

We would welcome an external contribution on this. If you have any questions, feel free to ask here, or open up a PR and start a conversation there.

Your provided code looks promising. I would note that the creg we currently create is for all the terminal measurements. We may want to create an additional classical register for the mid-circuit measurements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants