CUGate's params getter does not comply with circuit's assign_parameters
See original GitHub issueEnvironment
- Qiskit Terra version: 0a10008
- Python version: 3.8.10 64-bit
- Operating system: windows 10 64-bit
What is happening?
This issue is proposed based on the discussion under #7283, especially the insight of @jakelishman.
CUGate is the controlled version of UGate, a generic single-qubit rotation gate with 3 Euler angles. Most controlled gates have the same parameters as the base gate, but CUGate has an extra one: the global phase Ξ³. To cope with this, CUGate uses a @property decorator to define a getter for the property params. This getter function creates a new array and returns it. It leads to problems that following operations may be applied to this newly created array instead of the real parameters of the CUGate object. For example, that happens in the function QuantumCircuit.assign_parameters, which is demonstrated in the following section.
The failure of assign_parameters on CUGate leads to another problem. Currently, a line is missing below line 652 in qiskit/circuit/library/standard_gates/equivalence_library.py.
q = QuantumRegister(2, "q")
theta = Parameter("theta")
phi = Parameter("phi")
lam = Parameter("lam")
cu3_to_cu = QuantumCircuit(q)
cu3_to_cu.cu(theta, phi, lam, 0, 0, 1)
# should have another line:
# _sel.add_equivalence(CU3Gate(theta, phi, lam), cu3_to_cu)
If the add_equivalence function is added, the test test_equivalence_phase would report a TypeError exception. QuantumCircuit.assign_parameters is called during the test,
How can we reproduce the issue?
from qiskit.circuit import QuantumCircuit, Parameter
ps = [Parameter("t"), Parameter("p"), Parameter("l"), Parameter("g")]
qc = QuantumCircuit(2)
qc.cu(*ps, 0, 1)
qc.cu3(*ps[:3], 0, 1)
print(qc)
print(qc.assign_parameters(dict(zip(ps, [0.1, 0.2, 0.3, 0.4])), inplace=False))
The output is
q_0: βββββββ ββββββββββββββ ββββββ
βββββββ΄ββββββββββββββ΄ββββββ
q_1: β€ U(t,p,l,g) ββ€ U3(t,p,l) β
βββββββββββββββββββββββββββ
q_0: βββββββ βββββββββββββββββ βββββββββ
βββββββ΄βββββββββββββββββ΄βββββββββ
q_1: β€ U(t,p,l,g) ββ€ U3(0.1,0.2,0.3) β
βββββββββββββββββββββββββββββββββ
suggesting the assignment of CUGate is failed. Note that the parameters of the U3Gate have been assigned.
What should happen?
The second circuit should be
q_0: βββββββββββ βββββββββββββββββββββ βββββββββ
βββββββββββ΄βββββββββββββββββββββ΄βββββββββ
q_1: β€ U(0.1,0.2,0.3,0.4) ββ€ U3(0.1,0.2,0.3) β
βββββββββββββββββββββββββββββββββββββββββ
Any suggestions?
Maybe remove the Ξ³ parameter from CUGate. The global phase is a property of quantum circuits. It is not a property of other gates. Adding this parameter to CUGate makes it different from the general cases and requires special processing, e.g., here and here.
Issue Analytics
- State:
- Created 2 years ago
- Comments:7 (7 by maintainers)

Top Related StackOverflow Question
Yeah, itβs the same issue -
assign_parameters/bind_parametertries to mutate indices in theCUGate.paramsfield, but the gate has a getter that produces a new list, not the actual array. Julien at one point had a PR that addedassign_parametertoInstructioninstances so it could be overridden, but I donβt know what happened to that.Perhaps calling it βglobalβ phase is a bit misleading here (itβs the phase of the controlled gate), but yeah, the gamma parameter needs to stay for now. The main issue is [again π¦] that we donβt have a contract for what
Instruction.paramsshould contain, and how it should behave with respect to mutability.QuantumCircuitassumes that itβs a βtrueβ attribute, and tries to write to it as if it is guaranteed to be a list, but thatβs probably not something it can assume.The βbugβ could either be that
CUGatemust return a list-like object that backs all its parameters (in which case we need to do what Julien said), or other places in Terra need to stop assuming that they can mutate the object. They can write wholesale, perhaps (so theyβll trigger the setter method), but they canβt mutate. This second form is more safe, but it likely has some performance implications, because weβd need to be reconstructing several lists/tuples each time.