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

add support for Parameters to SparseLabelOp #891

Merged
merged 26 commits into from
Nov 1, 2022

Conversation

kevinsung
Copy link
Contributor

@kevinsung kevinsung commented Oct 16, 2022

Summary

Part of #828

Details and comments

Also fixes #892

@coveralls
Copy link

coveralls commented Oct 17, 2022

Pull Request Test Coverage Report for Build 3364057348

  • 47 of 47 (100.0%) changed or added relevant lines in 3 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.03%) to 85.823%

Totals Coverage Status
Change from base Build 3362454253: 0.03%
Covered Lines: 17441
Relevant Lines: 20322

💛 - Coveralls

Copy link
Member

@mrossinek mrossinek left a comment

Choose a reason for hiding this comment

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

Thank you, Kevin!

Besides these minor comments just a question: did you happen to also look into how the PolynomialTensor class can handle Parameter objects? In theory, this should be possible and I had done some rough testing a while back but not looked into it in more detail.

We can add support for that as part of another PR and a separate tracking issue, but I wanted to ask first, whether you had already looked into this 👍

@mrossinek mrossinek added this to the 0.5.0 milestone Oct 17, 2022
@kevinsung
Copy link
Contributor Author

did you happen to also look into how the PolynomialTensor class can handle Parameter objects? In theory, this should be possible and I had done some rough testing a while back but not looked into it in more detail.

I did not look into it in much detail. Let's leave that as a separate issue and separate PR. I think using Parameters with PolynomialTensor is a very niche use case so it is not a high priority. PolynomialTensor is mainly useful for linear algebra operations, and those would not be possible if it had Parameters.

@mrossinek
Copy link
Member

I think using Parameters with PolynomialTensor is a very niche use case so it is not a high priority. PolynomialTensor is mainly useful for linear algebra operations, and those would not be possible if it had Parameters.

Quite on the contrary. Enabling parameterized PolynomialTensor objects could indeed be very powerful.
Plus, linear algebra would also not be a problem, since the Parameter objects do support numerics just fine (otherwise this would also not work for the SparseLabelOp).

One example where a parameterized PolynomialTensor would be useful is the refactoring of the ooVQE algorithm, which applies parameterized orbital rotations.

Just a proof of concept:

import numpy as np

from qiskit.circuit import Parameter
from qiskit_nature.second_q.operators import FermionicOp, PolynomialTensor

a = Parameter("a")
b = Parameter("b")

mata = np.eye(2, dtype=object)
mata[0, 0] = a
matb = np.zeros((2, 2), dtype=object)
matb[0, 1] = b
matb[1, 0] = -b

pt_a = PolynomialTensor({"+-": mata})
pt_b = PolynomialTensor({"+-": matb})
print(pt_a + pt_b)
print(pt_a @ pt_b)
op = FermionicOp.from_polynomial_tensor(pt_a + pt_b)
print(op)
op = FermionicOp.from_polynomial_tensor(pt_a @ pt_b)
print(op)

Outputs (omitting zero-terms because chop needs a little work):

Polynomial Tensor
 "+-":
[[ParameterExpression(a) ParameterExpression(b)]
 [ParameterExpression(-1.0*b) 1]]
Polynomial Tensor
 "+-+-":
[[[[ParameterExpression(0) ParameterExpression(a*b)]
   [ParameterExpression(-1.0*a*b) ParameterExpression(0)]]

  [[0 ParameterExpression(0)]
   [ParameterExpression(0) 0]]]


 [[[0 ParameterExpression(0)]
   [ParameterExpression(0) 0]]

  [[0 ParameterExpression(b)]
   [ParameterExpression(-1.0*b) 0]]]]
Fermionic Operator
number spin orbitals=2, number terms=4
  a * ( +_0 -_0 )
+ b * ( +_0 -_1 )
+ -1.0*b * ( +_1 -_0 )
+ 1 * ( +_1 -_1 )
Fermionic Operator
number spin orbitals=2, number terms=4
a*b * ( +_0 -_0 +_0 -_1 )
+ -1.0*a*b * ( +_0 -_0 +_1 -_0 )
+ b * ( +_1 -_1 +_0 -_1 )
+ -1.0*b * ( +_1 -_1 +_1 -_0 )

@kevinsung
Copy link
Contributor Author

By linear algebra I meant eigenvalue decompositions and the like, not just matrix multiplication. Isn't that needed for computing orbital rotations?

@mrossinek
Copy link
Member

By linear algebra I meant eigenvalue decompositions and the like, not just matrix multiplication. Isn't that needed for computing orbital rotations?

Those would not work, yes. The way that the orbital rotations are done there, I do not think its needed. Although this may not hold generally speaking.

Copy link
Member

@mrossinek mrossinek left a comment

Choose a reason for hiding this comment

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

Other than this, this LGTM 👍

@kevinsung
Copy link
Contributor Author

I think this is broken because of a bug introduced by #893. See https://github.com/Qiskit/qiskit-nature/pull/893/files#r998269022.

Copy link
Member

@mrossinek mrossinek left a comment

Choose a reason for hiding this comment

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

Just one last clarification, other than that this is good to go 👍

mrossinek
mrossinek previously approved these changes Oct 19, 2022
Copy link
Member

@mrossinek mrossinek left a comment

Choose a reason for hiding this comment

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

Thanks, Kevin!

@woodsp-ibm
Copy link
Member

This is a more general question. What do we expect of such parameterized operators. If I look at a parameterized quantum circuit I have methods to get parameters and also to bind values etc. Might I want this at this level - I see that you've done similar to SparsePauliOp but I guess I could ask the same question of that too.

@kevinsung
Copy link
Contributor Author

kevinsung commented Oct 24, 2022

Ok, I've added the method. Also, in order to support assigning parameters in place, I changed the type of the internal data container from Mapping to dict.

Copy link
Member

@mrossinek mrossinek left a comment

Choose a reason for hiding this comment

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

Also, in order to support assigning parameters in place, I changed the type of the internal data container from Mapping to dict.

I do not understand why you think this is necessary. The public API can report Mapping just fine. The fact that we use a dict internally for storage does not affect this.

@kevinsung
Copy link
Contributor Author

I do not understand why you think this is necessary. The public API can report Mapping just fine. The fact that we use a dict internally for storage does not affect this.

When copy=False, previously the type of the internal storage object could be Mapping rather than dict. This precludes in-place operations because Mapping does not support item assignment. I updated the internal storage to always be dict. But if the input to __init__ is Mapping then we can't support copy=False. So I changed the input type to also be dict.

@mrossinek
Copy link
Member

Alright I have also discussed with @woodsp-ibm offline. We would like to do the following:

  • use Mapping for all public-facing API which is aligned with the immutable operator idea and allows users to specifically provide immutable data if they want to further enforce this
  • when inplace=True is requested by the user (which we want to support to avoid additional copies if a user so desires), proceed with an isinstance(..., MutableMapping) check. If this check fails, raise a TypeError. Otherwise proceed normally since the user specifically requested inplace=True

@kevinsung
Copy link
Contributor Author

In accordance with our offline discussion, I've reverted the change from Mapping to dict and removed the inplace argument to assign_parameters. We will make SparsePauliOp mutable in the future; this is tracked at #917.

Copy link
Member

@mrossinek mrossinek left a comment

Choose a reason for hiding this comment

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

Just some minor comments. Other than this, this is looking good 👍

mrossinek
mrossinek previously approved these changes Oct 28, 2022
Copy link
Member

@mrossinek mrossinek left a comment

Choose a reason for hiding this comment

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

This LGTM 👍

@kevinsung
Copy link
Contributor Author

Is there anything else? If not I'll go ahead and fix the merge conflicts.

@woodsp-ibm
Copy link
Member

Is there anything else?

Not from me, let's get the conflict sorted then.

Copy link
Member

@mrossinek mrossinek left a comment

Choose a reason for hiding this comment

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

LGTM, thanks Kevin!

@mrossinek mrossinek merged commit 2adee9e into qiskit-community:main Nov 1, 2022
@kevinsung kevinsung deleted the qiskit-nature-parameters branch November 1, 2022 11:48
@mrossinek mrossinek mentioned this pull request Nov 1, 2022
4 tasks
Anthony-Gandon pushed a commit to Anthony-Gandon/qiskit-nature that referenced this pull request May 25, 2023
* add support for Parameters to SparseLabelOp

* fix isinstance for python < 3.10

* improve docs

* chop zero Parameter

* Update test/second_q/operators/test_sparse_label_op.py

Co-authored-by: Max Rossmannek <[email protected]>

* fix test

* add is_parameterized and check it for unsupported operations

* add assign_parameters

* fix chop doc

* lint

* add parameters method

* use dict instead of Mapping for data

* return self instead of None for inplace

* Revert "use dict instead of Mapping for data"

This reverts commit 3480c79.

* remove inplace option for assign_parameters

* address comments

* Update qiskit_nature/second_q/operators/sparse_label_op.py

* fix equiv

Co-authored-by: Max Rossmannek <[email protected]>
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.

SparseLabelOp.chop makes pure imaginary coefficients real Support parameterized operators
4 participants