-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Description
Environment
- Qiskit Terra version: 0.21.0
- Python version: 3.9.12
- Operating system: Windows 11 Home
What is happening?
Creating and evaluating a Trotter evolution circuit for certain operators raises an error. The error message indicates that the ParameterExpression
has unbound parameters, even though this is not the case.
This issue has similarities with #7507, but it's not the same. The proposed solution in there (forcing the parameter to a float in PauliEvolutionGate.validate_parameter
) does not work in this case.
How can we reproduce the issue?
from qiskit.circuit import Parameter
from qiskit.opflow import PauliTrotterEvolution, Suzuki
from qiskit.opflow import X, Y
operator = (0.5j * X^X^Y^X)
param = Parameter('θ')
ev_op = (1j*operator*param).exp_i()
exp_operator = (PauliTrotterEvolution().convert(ev_op))
circuit = exp_operator
bound_circuit = circuit.bind_parameters({param: -0.1})
bound_circuit.eval()
What should happen?
- The error message should be accurate. As is, it doesn't allow one to identify the problem, because the set of parameters is in fact empty (as the message itself shows).
bound_circuit
should be evaluated without errors.
Any suggestions?
The problem seems to arise in the _apply_operation
method of ParameterExpression
. When our (yet unbound) param
is multiplied by the numeric coefficient (1j * 0.5j
, simplified to 0.5 + 0j
), the values of the relevant local variables inside that method are as follows:
> other_expr # Numeric coefficient (class: complex)
(-0.5+0j)
> self_expr # Coefficient of the ParameterExpression (class: symengine.lib.symengine_wrapper.Symbol)
θ
> expr
(-0.5 + 0.0*I)*θ
Later when the parameter θ is bound to -0.1, the attribute _symbol_expr
associated with the ParameterExpression
is -0.1*(-0.5 + 0.0*I)
. Casting this to a float is what gives an error (RuntimeError: Not Implemented
). The error doesn't occur if _symbol_expr
is -0.1*(-0.5)
.
Naively, doing
if numpy.isreal(other_expr):
other_expr = numpy.real(other_expr)
in _apply_operation
fixes the issue.
Alternatively, the error doesn't occur if we change the code the reproduces the problem into
operator = (0.5 * X^X^Y^X)
param = Parameter('θ')
ev_op = (operator*param).exp_i()
i.e., if the coefficient is real to begin with. However, this seems a bit rigid, as we might want to define operators with imaginary coefficients.