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 Register Reordering causes Unwanted/Subtle Semantic Changes #1652

Open
MattePalte opened this issue Nov 4, 2024 · 1 comment
Open
Assignees

Comments

@MattePalte
Copy link

Expected behavior

The output of Pytket when reading the QASM and exporting it again should preserve the semantics, maintaining the original register positions. This behavior is consistent with other platforms like Qiskit, PennyLane, and BQSKit.

Actual behavior

Pytket reorders the register positions (probably in alphabetical order), causing the program to change when compared to the imported one. This reordering affects the semantics of the circuit.

Additional information

This issue is reproducible 100% of the time. It is crucial to maintain the original order of registers for the composability of circuits expressed in QASM. Arbitrary reordering of registers can create problems when integrating subcircuits.

Source code

Run the following code to reproduce the issue:

from pytket.qasm import circuit_to_qasm_str
from pytket.qasm import circuit_from_qasm_str
qasm_str = """
include "qelib1.inc";
qreg cin[1];
qreg a[2];
qreg b[2];
cx a[0],b[0];
"""

circuit = circuit_from_qasm_str(qasm_str)
qasm_str_reordered_by_pytket = circuit_to_qasm_str(circuit)
print(qasm_str_reordered_by_pytket)

# OPENQASM 2.0;
# include "qelib1.inc";
# qreg a[2];
# qreg b[2];
# qreg cin[1];
# cx a[0],b[0];

Below a possible end-user usage of this function where the difference could be observed:

# add one X gate at the register in position 1
from qiskit import QuantumCircuit
from qiskit.qasm2 import loads
qc_input = QuantumCircuit(5)
qc_input.x(1)

# original circuit
circuit_a = loads(qasm_str)

# imported via pytket - registers reordered
circuit_b = loads(qasm_str_reordered_by_pytket)

# original circuit
qc_w_input_original = circuit_a.compose(
    qc_input, front=True)
print(qc_w_input_original)

# imported circuit
qc_w_input_buggy = circuit_b.compose(
    qc_input, front=True)
print(qc_w_input_buggy)

# compare the statevectors
sv_w_input_original = Statevector.from_instruction(qc_w_input_original)
probabilities_w_input_original = sv_w_input_original.probabilities_dict()
print("Probabilities W Input Original: ", probabilities_w_input_original)

sv_w_input_buggy = Statevector.from_instruction(qc_w_input_buggy)
probabilities_w_input_buggy = sv_w_input_buggy.probabilities_dict()
print("Probabilities W Input - After PyTket Reordering: ", probabilities_w_input_buggy)

Output:

cin: ──────────
     ┌───┐
a_0: ┤ X ├──■──
     └───┘  │
a_1: ───────┼──
          ┌─┴─┐
b_0: ─────┤ X ├
          └───┘
b_1: ──────────


a_0: ───────■──
     ┌───┐  │
a_1: ┤ X ├──┼──
     └───┘┌─┴─┐
b_0: ─────┤ X ├
          └───┘
b_1: ──────────

cin: ──────────

Probabilities W Input Original:  {'01010': 1.0}
Probabilities W Input - After PyTket Reordering:  {'00010': 1.0}

As observed, the probabilities are different, indicating that the circuit has changed after being imported and exported by Pytket. This is common when a user wants to optimize a circuit using Pytket and then export it back to QASM.

System

import qiskit
import pytket
print(f"Qiskit version: {qiskit.__version__}")
print(f"Pytket version: {pytket.__version__}")

Output:

Qiskit version: 1.2.0
Pytket version: 1.31.1
@cqc-melf
Copy link
Contributor

Hi @MattePalte ,
Thank you for reporting this.
It is a bit tricky for us to solve this at the moment and it will probably take some time for us to address this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants