-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Fix CUGate parameter assignment issues #9118
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,7 @@ | |
import numpy | ||
from qiskit.circuit.controlledgate import ControlledGate | ||
from qiskit.circuit.gate import Gate | ||
from qiskit.circuit.parameterexpression import ParameterValueType | ||
from qiskit.circuit.parameterexpression import ParameterValueType, ParameterExpression | ||
from qiskit.circuit.quantumregister import QuantumRegister | ||
from qiskit.circuit.exceptions import CircuitError | ||
|
||
|
@@ -273,33 +273,25 @@ def __array__(self, dtype=None): | |
|
||
@property | ||
def params(self): | ||
"""Get parameters from base_gate. | ||
|
||
Returns: | ||
list: List of gate parameters. | ||
|
||
Raises: | ||
CircuitError: Controlled gate does not define a base gate | ||
""" | ||
if self.base_gate: | ||
# CU has one additional parameter to the U base gate | ||
return self.base_gate.params + self._params | ||
else: | ||
raise CircuitError("Controlled gate does not define base gate for extracting params") | ||
"""return CU params.""" | ||
return self._params | ||
|
||
@params.setter | ||
def params(self, parameters): | ||
"""Set base gate parameters. | ||
|
||
Args: | ||
parameters (list): The list of parameters to set. | ||
|
||
Raises: | ||
CircuitError: If controlled gate does not define a base gate. | ||
""" | ||
# CU has one additional parameter to the U base gate | ||
self._params = [parameters[-1]] | ||
"""Set CUGate params [theta,phi,lam,gamma] and base_gate(UGate) params [theta,phi,lam]""" | ||
self._params = [] | ||
for single_param in parameters: | ||
if isinstance(single_param, ParameterExpression): | ||
self._params.append(single_param) | ||
else: | ||
self._params.append(self.validate_parameter(single_param)) | ||
if self.base_gate: | ||
self.base_gate.params = parameters[:-1] | ||
else: | ||
raise CircuitError("Controlled gate does not define base gate for extracting params") | ||
|
||
def __deepcopy__(self, _memo=None): | ||
"""Include the parameters in the copy""" | ||
cpy = super().__deepcopy__(_memo=_memo) | ||
cpy.params = self.params.copy() | ||
return cpy | ||
Comment on lines
+292
to
+297
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm guessing the reason this is necessary is because the parameter assignment isn't actually writing out to the That said, because Qiskit makes such heavy use of In [1]: from qiskit.circuit import Parameter, QuantumCircuit
...: a, b, c, d = (Parameter(x) for x in "abcd")
...:
...: qc1 = QuantumCircuit(2)
...: qc1.cu(0.1, 0.2, 0.3, 0.4, 0, 1)
...:
...: qc2 = QuantumCircuit(2)
...: qc2.cu(a, b, c, d, 0, 1)
...: qc2.assign_parameters([0.1, 0.2, 0.3, 0.4], inplace=True)
...: qc1 == qc2 # because there's a secret deepcopy
Out[1]: True
In [2]: qc1.data[0] == qc2.data[0] # ... but _really_
Out[2]: False
In [3]: qc2.data[0].operation.params
Out[3]:
[ParameterExpression(0.1),
ParameterExpression(0.2),
ParameterExpression(0.3),
ParameterExpression(0.4)]
In [4]: qc2.data[0].operation.base_gate.params
Out[4]: [Parameter(a), Parameter(b), Parameter(c)] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think some of the complexity may stem from the I included An alternative was to add a setter method for |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
fixes: | ||
- | | ||
Changed the :meth:`~qiskit.CUGate.params` property and setter to handle the additional parameter | ||
gamma for the CUGate global_phase and to maintain the base gate, UGate, parameters | ||
Added the :meth:`~qiskit.CUGate.__deepcopy__` to copy the CUGate parameters | ||
Fixes `#7410 <https://github.com/Qiskit/qiskit-terra/issues/7410>`_. | ||
Added CU3 to CU equivalence to the equivalence library | ||
Fixes `#7326 <https://github.com/Qiskit/qiskit-terra/issues/7326>`_. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this
if
/else
might be unnecessary?Gate.validate_parameter
has handling forParameterExpression
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
if / else
logic came from the setterInstruction.params
; the method that was being inherited. I saw logic with and without the if / else and chose the one that seemed the lowest risk. Is it useful to keep here for the instantiation process of aGate
? I know validation happens during thebind_parameters
andassign_parameters
process but I did not see any validation during instantiation.I like the idea of adding the U4Gate since it would seem to complete the set.