Skip to content
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

Support complex parameters #5192

Merged
merged 22 commits into from
Nov 24, 2020
Merged

Support complex parameters #5192

merged 22 commits into from
Nov 24, 2020

Conversation

Cryoris
Copy link
Contributor

@Cryoris Cryoris commented Oct 7, 2020

Summary

Add support for complex ParameterExpressions, closes #5130.

Details and comments

This is quite a fundamental change and might require some discussion.

Short demo:

>> p = Parameter('p')
>>> 1j * p
ParameterExpression(1.0*I*p)
>>> (1j * p + 0.2 - 5j).conjugate()
ParameterExpression(-1.0*I*conjugate(p) + 0.2 + 5.0*I)

Bound complex rotation angle fails:

>>> qc = QuantumCircuit(1)
>>> qc.ry(p, 0)
>>> qc.assign_parameters({p: 1j})
Traceback (most recent call last):
  ...
qiskit.circuit.exceptions.CircuitError: 'Bound parameter expression is complex in gate ry'

Complex parameter bound to complex value:

>>> qc = QuantumCircuit(1)
>>> qc.ry(1j * p, 0)
>>> qc.draw()
     ┌─────────────┐
q_0: ┤ RY(1.0*I*p) ├
     └─────────────┘
>>> qc.assign_parameters({p: 1j}).draw()
     ┌───────────────────────┐
q_0: ┤ RY(-1.00000000000000) ├
     └───────────────────────┘

Open questions

  • Is there a perfomance hit by the additional validation?
  • Do we want to have a real flag in the Parameters?

@ajavadia
Copy link
Member

ajavadia commented Oct 8, 2020

does this also address #5191?

@Cryoris
Copy link
Contributor Author

Cryoris commented Oct 8, 2020

Yeah, I think so, is that right @eggerdj? You can then do:

>> p = Parameter('p')
>>> 1j * p
ParameterExpression(1.0*I*p)

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.

Thanks @Cryoris for kicking this off. This looks good so far. Some thoughts:

  • IIRC, the initial motivation for _raise_if_passed_non_real_value was to ensure all values were real by the time they were sent to the device (so both calculations and inputs were kept real throughout). This is likely not a requirement anymore (and I believe pulse requires complex outputs, @lcapelluto can confirm). Individual instructions can still enforce requirements via validate_parameters as long as it is called at or after binding time.

  • This PR introduces complex expressions in three places: as valid binding values, during expression construction, and as resolved output values. Calling these out so they can be sufficiently tested.

  • We should add ParameterExpression.__complex__.

  • I don't know if we should have a flag for real/complex parameters. There some operations where it would be required, but none are supported at the moment (floor, mod, ordering/comparisons come to mind, maybe there are others?). I looked quickly for sympy's usage of is_real, and found a few cases where it is used as an assumption to apply some simplifications (but we in general don't want simplification of expressions). Curious to hear others' thoughts on this.

test/python/circuit/test_parameters.py Show resolved Hide resolved
test/python/circuit/test_parameters.py Show resolved Hide resolved
qiskit/circuit/gate.py Show resolved Hide resolved
qiskit/circuit/parameterexpression.py Outdated Show resolved Hide resolved
@ajavadia
Copy link
Member

I think we need a different approach here. Circuit parameters should always be real (they correspond to angles of rotation). But they could be used later in some non-real algebra. e.g. a matrix defining the parameterized gate can have complex entries, or a pulse implementing the parameterized gate can take that real parameter and multiply it by some complex number. However this does not change the fundamental fact that the parameters are real.

So can we separate the parameter from what we do to the parameter? We should be able to multiply parameters by complex numbers, but not define complex parameters.

@kdk kdk linked an issue Oct 12, 2020 that may be closed by this pull request
@kdk
Copy link
Member

kdk commented Oct 13, 2020

I think we need a different approach here. Circuit parameters should always be real (they correspond to angles of rotation). But they could be used later in some non-real algebra. e.g. a matrix defining the parameterized gate can have complex entries, or a pulse implementing the parameterized gate can take that real parameter and multiply it by some complex number. However this does not change the fundamental fact that the parameters are real.

Is this also true for their usage in pulse ( e.g. #5130 )?

@lcapelluto
Copy link
Contributor

lcapelluto commented Oct 13, 2020

For pulse, parameters can be real (I hadn't updated my issue lately). As long as I can use the expression 1j * p, it doesn't matter that the parameter value itself can only be real. This is my basic use case:

amp = Parameter('amp')
waveform = pulse.Gaussian(duration, sigma, 1j*amp)

Copy link
Contributor

@lcapelluto lcapelluto left a comment

Choose a reason for hiding this comment

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

Looking good!

qiskit/circuit/gate.py Show resolved Hide resolved
test/python/circuit/test_parameters.py Show resolved Hide resolved
qiskit/circuit/quantumcircuit.py Show resolved Hide resolved
@kdk kdk added the Changelog: New Feature Include in the "Added" section of the changelog label Nov 23, 2020
@kdk kdk added this to the 0.17 milestone Nov 23, 2020
@Cryoris Cryoris merged commit da66b1f into Qiskit:master Nov 24, 2020
@Cryoris Cryoris deleted the complex-params branch November 24, 2020 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the "Added" section of the changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support multiplication of Parameter with complex values Support for Parameters with complex values
4 participants