Skip to content

Conversation

Cryoris
Copy link
Contributor

@Cryoris Cryoris commented Jan 10, 2022

Summary

Fixes #7507.

Details and comments

The underlying issue here is that ParameterExpressions, after being fully bound, often remain ParameterExpressions instead of being cast to float/complex. This PR fixes it very high-level, but maybe we should put this fix already at the level of Instruction.validate_parameter.

Misses:

  • reno
  • test

@coveralls
Copy link

coveralls commented Jan 10, 2022

Pull Request Test Coverage Report for Build 3329512584

  • 5 of 6 (83.33%) changed or added relevant lines in 1 file are covered.
  • 2 unchanged lines in 1 file lost coverage.
  • Overall coverage decreased (-0.003%) to 84.404%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/synthesis/evolution/matrix_synthesis.py 5 6 83.33%
Files with Coverage Reduction New Missed Lines %
qiskit/extensions/quantum_initializer/squ.py 2 79.78%
Totals Coverage Status
Change from base Build 3327479795: -0.003%
Covered Lines: 61739
Relevant Lines: 73147

💛 - Coveralls

@Cryoris Cryoris changed the title [WIP] Cast fully bound ParameterExpression to float within the PauliEvolutionGate Cast fully bound ParameterExpression to float within the PauliEvolutionGate Jan 13, 2022
Copy link
Member

@kdk kdk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a case where we would expect the ParameterExpression to not be able to be cast to a float while having an empty parameters? The error message TypeError: ParameterExpression with unbound parameters (set()) cannot be cast to a float. makes me wonder if something is going wrong earlier in the process.

@jakelishman
Copy link
Member

@kdk: yes, if the parameter is complex. From attaching pdb to the traceback, the issue here is that somewhere in the process, the time is getting turned into 0 + 0.23*I, which can't be cast to float. You can see that Scipy actually does try to cast the whole array to float first, and it calls the correct methods in ParameterExpression, which should work:

In [10]: from qiskit.circuit import Parameter
    ...: import numpy as np
    ...:
    ...: t = Parameter("t")
    ...: t.bind({t: 0.25}), np.array([t.bind({t: 0.25})], dtype=float)
Out[10]: (ParameterExpression(0.25), array([0.25]))

@Cryoris
Copy link
Contributor Author

Cryoris commented Feb 18, 2022

Thanks for tracking that down! Another solution would be to leave validate_parameters as is and instead ensure that the time is a float inside the matrix synthesis. That would have the advantage that we can raise a specific error message so I changed it. But I'm also happy to revert if you think it should remain in validate_parameters.

@jakelishman
Copy link
Member

Using the regression test added in this PR, but modified for Qiskit 1.0:

from qiskit.circuit import Parameter, QuantumCircuit
from qiskit.quantum_info import Pauli, Operator
from qiskit.circuit.library import PauliEvolutionGate
from qiskit.synthesis import MatrixExponential

op = Pauli("X")
time = Parameter("t")
evo_gate = PauliEvolutionGate(op, time, synthesis=MatrixExponential())
circuit = QuantumCircuit(1)
circuit.append(evo_gate, [0])
bound = circuit.assign_parameters({time: 0.12})

ref = QuantumCircuit(1)
ref.rx(0.24, 0)

assert Operator(bound).equiv(ref)

this no longer fails, and #7507 is no longer reproducible either, so I'll close this as obsoleted. Feel free to reopen if there's more to be done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

qiskit.synthesis.MatrixExponential breaks if evolution time is a bound Parameter
4 participants