Qiskit / qiskit-qasm3-import

Importer from OpenQASM 3 to Qiskit's QuantumCircuit
https://qiskit.github.io/qiskit-qasm3-import
Apache License 2.0
15 stars 7 forks source link

Equivalence of `u` gate in converted `QuantumCircuit` #12

Open TheGupta2012 opened 1 year ago

TheGupta2012 commented 1 year ago

I was trying to check the equality of circuits when converting from qasm2 and qasm3 strings. I was using the following qasm strings for the conversion -


qasm2 = """
 OPENQASM 2.0;
 include "qelib1.inc";
 qreg q[1];
 u(2.5256,3.8774,2.1604) q[0];"""

 qasm3 = """
 OPENQASM 3.0;
 include 'stdgates.inc';
 // generic single qubit gate
 gate u(theta,phi,lambda) q { u3(theta,phi,lambda) q; }
 qubit[1] q;
 u(2.5256,3.8774,2.1604) q[0];"""

and the following script to check circuit equivalence -


from qiskit import QuantumCircuit
from qiskit.qasm3 import loads 
qc1 = QuantumCircuit.from_qasm_str(qasm2)
qc2 = loads(qasm3)
print(qc1 == qc2)

This should produce a True output but I am getting False, even though on printing the data of circuits I get identical instructions -


In [26]: qc1.data
Out[26]: [CircuitInstruction(operation=Instruction(name='u', num_qubits=1, num_clbits=0, params=[2.5256, 3.8774, 2.1604]), qubits=(Qubit(QuantumRegister(1, 'q'), 0),), clbits=())]

In [27]: qc2.data
Out[27]: [CircuitInstruction(operation=Instruction(name='u', num_qubits=1, num_clbits=0, params=[2.5256, 3.8774, 2.1604]), qubits=(Qubit(QuantumRegister(1, 'q'), 0),), clbits=())]
jakelishman commented 1 year ago

There's a couple of things going on here. First, the repr method of Instruction misleading always writes Instruction(...) and ignores the type. As things happen, the OQ2 importer returns a library.UGate and the OQ3 importer returns an ad-hoc Gate instance. This happens because both importers treat gates in their corresponding standard library specially, and define a custom gate object whenever they're dealing with a gate declaration. The new OQ2 importer (qiskit.qasm2.loads) is more configurable, and can be told to use certain objects to represent certain symbols in the program. We're planning to rewrite the OQ3 importer completely (obsoleting this package) with similar configurability in the future.

The second main point is that the == method for circuits is a tricky beast. Quantum circuits represent executable programs, and there's an infinite number of ways of representing the exact same program in general. There's no reasonable normalisation/canonicalisation that we could do that would make == always detect equal programs, so the result is that there'll be a lot of false negatives.