Open jiannanWang opened 7 months ago
@jiannanWang I learned That qpy works with QuantumCircuit Modules not with qiskit.circuit.library. So I checked the documents listed below and modify your code using
qc.cu(theta, phi, lam, gamma, control_qubit, target_qubit, label=None, ctrl_state=None)
supprted with QuantumCircuit and it works correctly with my code editor. here is the code..
from qiskit import QuantumCircuit
from qiskit import qpy
qc = QuantumCircuit(3, name='circuit')
qc.cu(1, 1, 1, 1, 1, 0)
with open('circuit.qpy', 'wb') as fd:
qpy.dump(qc, fd)
with open('circuit.qpy', 'rb') as fd:
new_qc = qpy.load(fd)[0]
Here is the documentation of Cu gate and qpy https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.library.CUGate https://docs.quantum.ibm.com/api/qiskit/qpy
I Hope It works with you as well.
Hope you are doing well! It's been a while since I submitted this issue. I wonder if there's any update? Thanks!
I revisited this issue and checked the stack track (copied below). From the traceback, it seems during loading, the qpy somehow loaded UGate instead of the CUGate. So the fourth parameter (gamma) of CUGate is passed to the fourth parameter (label) of UGate, which eventually causes this crash.
Traceback (most recent call last):
File "/mnt/test_crash.py", line 12, in <module>
qc = qpy.load(fd)[0] # TypeError: label expects a string or None
File "/root/anaconda3/envs/qiskit/lib/python3.10/site-packages/qiskit/qpy/interface.py", line 301, in load
loader(
File "/root/anaconda3/envs/qiskit/lib/python3.10/site-packages/qiskit/qpy/binary_io/circuits.py", line 1189, in read_circuit
_read_instruction(
File "/root/anaconda3/envs/qiskit/lib/python3.10/site-packages/qiskit/qpy/binary_io/circuits.py", line 273, in _read_instruction
inst_obj = _parse_custom_operation(
File "/root/anaconda3/envs/qiskit/lib/python3.10/site-packages/qiskit/qpy/binary_io/circuits.py", line 396, in _parse_custom_operation
base_gate = _read_instruction(
File "/root/anaconda3/envs/qiskit/lib/python3.10/site-packages/qiskit/qpy/binary_io/circuits.py", line 351, in _read_instruction
gate = gate_class(*params)
File "/root/anaconda3/envs/qiskit/lib/python3.10/site-packages/qiskit/circuit/library/standard_gates/u.py", line 81, in __init__
super().__init__("u", 1, [theta, phi, lam], label=label, duration=duration, unit=unit)
File "/root/anaconda3/envs/qiskit/lib/python3.10/site-packages/qiskit/circuit/gate.py", line 45, in __init__
super().__init__(name, num_qubits, 0, params, label=label, duration=duration, unit=unit)
File "/root/anaconda3/envs/qiskit/lib/python3.10/site-packages/qiskit/circuit/instruction.py", line 95, in __init__
raise TypeError("label expects a string or None")
TypeError: label expects a string or None
After experimenting with the code, the problem seems to boil down to the following. The code
gate = CUGate(1, 1, 1, 1)
print(f"{gate = }")
cgate = gate.control(1)
print(f"{cgate = }")
bgate = cgate.base_gate
print(f"{bgate = }")
outputs
gate = Instruction(name='cu', num_qubits=2, num_clbits=0, params=[1, 1, 1, 1])
cgate = Instruction(name='ccu', num_qubits=3, num_clbits=0, params=[1, 1, 1, 1])
bgate = Instruction(name='u', num_qubits=1, num_clbits=0, params=[1, 1, 1, 1])
That is, we now have a UGate with the wrong number of parameters. I believe this is due to the discrepancy in handling params for generic controlled gates vs. CUGates, see https://github.com/Qiskit/qiskit/blob/9157c04230943d5470e5bb6c31ce0f4c8dedecf6/qiskit/circuit/library/standard_gates/u.py#L148-L157
Having written this, I have no idea how to fix this, leaving the fix to the experts. :)
After experimenting with the code, the problem seems to boil down to the following. The code
gate = CUGate(1, 1, 1, 1) print(f"{gate = }") cgate = gate.control(1) print(f"{cgate = }") bgate = cgate.base_gate print(f"{bgate = }")
outputs
gate = Instruction(name='cu', num_qubits=2, num_clbits=0, params=[1, 1, 1, 1]) cgate = Instruction(name='ccu', num_qubits=3, num_clbits=0, params=[1, 1, 1, 1]) bgate = Instruction(name='u', num_qubits=1, num_clbits=0, params=[1, 1, 1, 1])
Considering this as an example, after creating the
cu
instruction, we create a controlled gateccu
line 240 by passing inoperation.params
= [1,1,1,1] (which is params ofcu
instruction above) andbase_gate = u
gate (which is the base gate ofcu
). During which we call the constructor ofInstruction
class and assignself.params = params
which causes the failure. IMO, we should first check whether or notself.params
is empty and then move forward The following code https://github.com/Qiskit/qiskit/blob/9157c04230943d5470e5bb6c31ce0f4c8dedecf6/qiskit/circuit/instruction.py#L108 should beif not self.params: self.params = params
With this change, the output of the above code snippet is
gate = Instruction(name='cu', num_qubits=2, num_clbits=0, params=[1, 1, 1, 1]) cgate = Instruction(name='ccu', num_qubits=3, num_clbits=0, params=[1, 1, 1]) bgate = Instruction(name='u', num_qubits=1, num_clbits=0, params=[1, 1, 1])
Environment
What is happening?
Running the below code results in TypeError: label expects a string or None. However, I use the default label which is None.
How can we reproduce the issue?
What should happen?
I expect the code to run without error.
Any suggestions?
No response