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

QASM Exporter does not Define cs gate #306

Open
MattePalte opened this issue Dec 18, 2024 · 1 comment
Open

QASM Exporter does not Define cs gate #306

MattePalte opened this issue Dec 18, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@MattePalte
Copy link

Expected Behavior

The quantum circuit should be successfully converted from Qiskit to BQSKit, exported to QASM, and re-imported using Qiskit’s QASM parser without errors. The circuit should maintain its integrity throughout the process.

Actual Behavior

The exported QASM file fails to be re-imported into Qiskit, raising a QASM2ParseError with the message "<input>:4,0: 'cs' is not defined in this scope". This indicates that the custom gate cs defined in the original QASM file is not recognized during the re-import process.

Additional Information

The issue appears to be related to the handling of custom gate definitions during the export/import process. The original QASM file explicitly defines the cs gate, but the exported QASM file from BQSKit does not retain this definition, leading to a parse error during re-import. The issue reproduces 100% of the time when following the provided steps.

Source Code

#!/usr/bin/env python
# coding: utf-8

from bqskit.ext import qiskit_to_bqskit
from qiskit import qasm2

qasm_file = """
OPENQASM 2.0;
include "qelib1.inc";
gate cs q0,q1 { p(pi/4) q0; cx q0,q1; p(-pi/4) q1; cx q0,q1; p(pi/4) q1; }
qreg q[5];
cs q[4],q[0];
"""

# Load the QASM into a Qiskit circuit
qc = qasm2.loads(
    qasm_file, custom_instructions=qasm2.LEGACY_CUSTOM_INSTRUCTIONS)
qc.draw()

# OUTPUT:
#      ┌─────┐
# q_0: ┤1    ├
#      │     │
# q_1: ┤     ├
#      │     │
# q_2: ┤  Cs ├
#      │     │
# q_3: ┤     ├
#      │     │
# q_4: ┤0    ├
#      └─────┘

# Convert Qiskit circuit to BQSKit circuit
bqskit_circuit = qiskit_to_bqskit(qc)
print("BQSKit Circuit:")
print(bqskit_circuit)

# Export the BQSKit circuit to QASM
bqskit_qasm_path = "bqskit_circuit.qasm"
bqskit_circuit.save(bqskit_qasm_path)
print(f"BQSKit QASM file saved at: {bqskit_qasm_path}")

# OUTPUT:
# BQSKit Circuit:
# Circuit(5)[CSGate@(4, 0)]
# BQSKit QASM file saved at: bqskit_circuit.qasm
# OPENQASM 2.0;
# include "qelib1.inc";
# qreg q[5];
# cs q[4], q[0];


# Read the exported QASM file and attempt to re-import into Qiskit
with open(bqskit_qasm_path, 'r') as file:
    bqskit_qasm = file.read()
    qc_read = qasm2.loads(
        bqskit_qasm, custom_instructions=qasm2.LEGACY_CUSTOM_INSTRUCTIONS)

Tracebacks

# OUTPUT:
# QASM2ParseError                           Traceback (most recent call last)
# ...
# QASM2ParseError: "<input>:4,0: 'cs' is not defined in this scope"

This traceback suggests that the custom gate cs is not included or properly handled in the exported QASM file.

Complete trace:

QASM2ParseError                           Traceback (most recent call last)
Cell In[15], line 16
     14 with open(bqskit_qasm_path, 'r') as file:
     15     bqskit_qasm = file.read()
---> 16     qc_read = qasm2.loads(bqskit_qasm, custom_instructions=qasm2.LEGACY_CUSTOM_INSTRUCTIONS)

File ~/python3.10/site-packages/qiskit/qasm2/__init__.py:587, in loads(string, include_path, custom_instructions, custom_classical, strict)
    571 """Parse an OpenQASM 2 program from a string into a :class:`.QuantumCircuit`.
    572
    573 Args:
   (...)
    584     A circuit object representing the same OpenQASM 2 program.
    585 """
    586 custom_instructions = list(custom_instructions)
--> 587 return _parse.from_bytecode(
    588     _qasm2.bytecode_from_string(
    589         string,
    590         [_normalize_path(path) for path in include_path],
    591         [
    592             _qasm2.CustomInstruction(x.name, x.num_params, x.num_qubits, x.builtin)
    593             for x in custom_instructions
    594         ],
    595         tuple(custom_classical),
    596         strict,
    597     ),
    598     custom_instructions,
    599 )

File ~/python3.10/site-packages/qiskit/qasm2/parse.py:243, in from_bytecode(bytecode, custom_instructions)
    240 # Pull this out as an explicit iterator so we can manually advance the loop in `DeclareGate`
    241 # contexts easily.
    242 bc = iter(bytecode)
--> 243 for op in bc:
    244     # We have to check `op.opcode` so many times, it's worth pulling out the extra attribute
    245     # access.  We should check the opcodes in order of their likelihood to be in the OQ2 program
    246     # for speed.  Gate applications are by far the most common for long programs.  This function
    247     # is deliberately long and does not use hashmaps or function lookups for speed in
    248     # Python-space.
    249     opcode = op.opcode
    250     # `OpCode` is an `enum` in Rust, but its instances don't have the same singleton property as
    251     # Python `enum.Enum` objects.

QASM2ParseError: "<input>:4,0: 'cs' is not defined in this scope"

Let me know if you need any further help or information from my side.
Thanks in advance

@edyounis
Copy link
Member

BQSKit should handle this fine. Can you try loading the qasm directly into BQSKit?

@edyounis edyounis added the bug Something isn't working label Feb 11, 2025
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