Description
Environment
- Qiskit version: 1.0.0
- Python version: 3.11.7
- Operating system: macOS 14.4.1
What is happening?
A controlled UGate with a parametrized angle k and with 4 (or more) controls throws an error.
Such controlled parametrized gates are useful for constructing certain custom trial states for vqe.
How can we reproduce the issue?
from qiskit import *
from qiskit import QuantumRegister
from qiskit import QuantumCircuit
from qiskit.circuit.library import UGate
from qiskit.circuit import Parameter
k=Parameter("k")
q=QuantumRegister(5)
qc = QuantumCircuit(q)
ccU = UGate(k,0,0).control(4)
qc.append(ccU,[0,1,2,3,4])```
TypeError Traceback (most recent call last)
Cell In[3], line 10
8 q=QuantumRegister(5)
9 qc = QuantumCircuit(q)
---> 10 ccU = UGate(k,0,0).control(4)
11 qc.append(ccU,[0,1,2,3,4])
File ~/Library/Python/3.12/lib/python/site-packages/qiskit/circuit/library/standard_gates/u.py:130, in UGate.control(self, num_ctrl_qubits, label, ctrl_state, annotated)
128 gate.base_gate.label = self.label
129 else:
--> 130 gate = super().control(
131 num_ctrl_qubits=num_ctrl_qubits,
132 label=label,
133 ctrl_state=ctrl_state,
134 an
6527
notated=annotated,
135 )
136 return gate
File ~/Library/Python/3.12/lib/python/site-packages/qiskit/circuit/gate.py:121, in Gate.control(self, num_ctrl_qubits, label, ctrl_state, annotated)
117 if not annotated:
118 # pylint: disable=cyclic-import
119 from .add_control import add_control
--> 121 return add_control(self, num_ctrl_qubits, label, ctrl_state)
123 else:
124 return AnnotatedOperation(
125 self, ControlModifier(num_ctrl_qubits=num_ctrl_qubits, ctrl_state=ctrl_state)
126 )
File ~/Library/Python/3.12/lib/python/site-packages/qiskit/circuit/add_control.py:61, in add_control(operation, num_ctrl_qubits, label, ctrl_state)
58 if isinstance(operation, UnitaryGate):
59 # attempt decomposition
60 operation._define()
---> 61 cgate = control(operation, num_ctrl_qubits=num_ctrl_qubits, label=label, ctrl_state=ctrl_state)
62 if operation.label is not None:
63 cgate.base_gate = cgate.base_gate.to_mutable()
File ~/Library/Python/3.12/lib/python/site-packages/qiskit/circuit/add_control.py:187, in control(operation, num_ctrl_qubits, label, ctrl_state)
183 controlled_circ.mcrx(
184 theta, q_control, q_target[bit_indices[qargs[0]]], use_basis_gates=True
185 )
186 elif phi == 0 and lamb == 0:
--> 187 controlled_circ.mcry(
188 theta,
189 q_control,
190 q_target[bit_indices[qargs[0]]],
191 q_ancillae,
192 use_basis_gates=True,
193 )
194 elif theta == 0 and phi == 0:
195 controlled_circ.mcp(lamb, q_control, q_target[bit_indices[qargs[0]]])
File ~/Library/Python/3.12/lib/python/site-packages/qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py:331, in mcry(self, theta, q_controls, q_target, q_ancillae, mode, use_basis_gates)
320 _apply_mcu_graycode(
321 self,
322 theta_step,
(...)
327 use_basis_gates=use_basis_gates,
328 )
329 else:
330 cgate = _mcsu2_real_diagonal(
--> 331 RYGate(theta).to_matrix(),
332 num_controls=len(control_qubits),
333 use_basis_gates=use_basis_gates,
334 )
335 self.compose(cgate, control_qubits + [target_qubit], inplace=True)
336 else:
File ~/Library/Python/3.12/lib/python/site-packages/qiskit/circuit/gate.py:62, in Gate.to_matrix(self)
52 """Return a Numpy.array for the gate unitary matrix.
53
54 Returns:
(...)
59 exception will be raised when this base class method is called.
60 """
61 if hasattr(self, "array"):
---> 62 return self.array(dtype=complex)
63 raise CircuitError(f"to_matrix not defined for this {type(self)}")
File ~/Library/Python/3.12/lib/python/site-packages/qiskit/circuit/library/standard_gates/ry.py:124, in RYGate.array(self, dtype)
122 def array(self, dtype=None):
123 """Return a numpy.array for the RY gate."""
--> 124 cos = math.cos(self.params[0] / 2)
125 sin = math.sin(self.params[0] / 2)
126 return numpy.array([[cos, -sin], [sin, cos]], dtype=dtype)
File ~/Library/Python/3.12/lib/python/site-packages/qiskit/circuit/parameterexpression.py:415, in ParameterExpression.float(self)
413 except (TypeError, RuntimeError) as exc:
414 if self.parameters:
--> 415 raise TypeError(
416 "ParameterExpression with unbound parameters ({}) "
417 "cannot be cast to a float.".format(self.parameters)
418 ) from None
419 # In symengine, if an expression was complex at any time, its type is likely to have
420 # stayed "complex" even when the imaginary part symbolically (i.e. exactly)
421 # cancelled out. Sympy tends to more aggressively recognise these as symbolically
422 # real. This second attempt at a cast is a way of unifying the behaviour to the
423 # more expected form for our users.
424 cval = complex(self)
TypeError: ParameterExpression with unbound parameters (dict_keys([Parameter(k)])) cannot be cast to a float.```
What should happen?
If the number of controls is less than 4, then no error is thrown:
ccU = UGate(k,0,0).control(3)
qc.append(ccU,[0,1,2,3])```
<qiskit.circuit.instructionset.InstructionSet at 0x107709330>```
Similar behavior is expected for 4 or more controls.
Any suggestions?
Thanks for your help.
CC:@diemilio