-
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
Support Dict[str, OperatorBase] for aux_operators (fix #6772) #6870
Changes from 1 commit
ef51d8b
23d0b31
11ef00e
7eb96e1
9be9006
4e09082
ccf1dc5
6824351
23cfa63
98a127f
e5dfae3
68895c9
808a193
fed1a7d
2b3a6d2
c4b4679
32e608b
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 |
---|---|---|
|
@@ -40,12 +40,15 @@ def setUp(self): | |
|
||
aux_op1 = PauliSumOp.from_list([("II", 2.0)]) | ||
aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5), ("XX", -0.5)]) | ||
self.aux_ops = [aux_op1, aux_op2] | ||
self.aux_ops_list = [aux_op1, aux_op2] | ||
self.aux_ops_dict = {"aux_op1": aux_op1, "aux_op2": aux_op2} | ||
|
||
def test_cme(self): | ||
"""Basic test""" | ||
algo = NumPyMinimumEigensolver() | ||
result = algo.compute_minimum_eigenvalue(operator=self.qubit_op, aux_operators=self.aux_ops) | ||
result = algo.compute_minimum_eigenvalue( | ||
operator=self.qubit_op, aux_operators=self.aux_ops_list | ||
) | ||
self.assertAlmostEqual(result.eigenvalue, -1.85727503 + 0j) | ||
self.assertEqual(len(result.aux_operator_eigenvalues), 2) | ||
np.testing.assert_array_almost_equal(result.aux_operator_eigenvalues[0], [2, 0]) | ||
|
@@ -60,7 +63,9 @@ def test_cme_reuse(self): | |
self.assertIsNone(result.aux_operator_eigenvalues) | ||
|
||
# Add aux_operators and go again | ||
result = algo.compute_minimum_eigenvalue(operator=self.qubit_op, aux_operators=self.aux_ops) | ||
result = algo.compute_minimum_eigenvalue( | ||
operator=self.qubit_op, aux_operators=self.aux_ops_list | ||
) | ||
self.assertAlmostEqual(result.eigenvalue, -1.85727503 + 0j) | ||
self.assertEqual(len(result.aux_operator_eigenvalues), 2) | ||
np.testing.assert_array_almost_equal(result.aux_operator_eigenvalues[0], [2, 0]) | ||
|
@@ -72,14 +77,16 @@ def test_cme_reuse(self): | |
self.assertIsNone(result.aux_operator_eigenvalues) | ||
|
||
# Set aux_operators and go again | ||
result = algo.compute_minimum_eigenvalue(operator=self.qubit_op, aux_operators=self.aux_ops) | ||
result = algo.compute_minimum_eigenvalue( | ||
operator=self.qubit_op, aux_operators=self.aux_ops_list | ||
) | ||
self.assertAlmostEqual(result.eigenvalue, -1.85727503 + 0j) | ||
self.assertEqual(len(result.aux_operator_eigenvalues), 2) | ||
np.testing.assert_array_almost_equal(result.aux_operator_eigenvalues[0], [2, 0]) | ||
np.testing.assert_array_almost_equal(result.aux_operator_eigenvalues[1], [0, 0]) | ||
|
||
# Finally just set one of aux_operators and main operator, remove aux_operators | ||
result = algo.compute_minimum_eigenvalue(operator=self.aux_ops[0], aux_operators=[]) | ||
result = algo.compute_minimum_eigenvalue(operator=self.aux_ops_list[0], aux_operators=[]) | ||
self.assertAlmostEqual(result.eigenvalue, 2 + 0j) | ||
self.assertIsNone(result.aux_operator_eigenvalues) | ||
|
||
|
@@ -92,7 +99,9 @@ def criterion(x, v, a_v): | |
return v >= -0.5 | ||
|
||
algo = NumPyMinimumEigensolver(filter_criterion=criterion) | ||
result = algo.compute_minimum_eigenvalue(operator=self.qubit_op, aux_operators=self.aux_ops) | ||
result = algo.compute_minimum_eigenvalue( | ||
operator=self.qubit_op, aux_operators=self.aux_ops_list | ||
) | ||
self.assertAlmostEqual(result.eigenvalue, -0.22491125 + 0j) | ||
self.assertEqual(len(result.aux_operator_eigenvalues), 2) | ||
np.testing.assert_array_almost_equal(result.aux_operator_eigenvalues[0], [2, 0]) | ||
|
@@ -107,7 +116,9 @@ def criterion(x, v, a_v): | |
return False | ||
|
||
algo = NumPyMinimumEigensolver(filter_criterion=criterion) | ||
result = algo.compute_minimum_eigenvalue(operator=self.qubit_op, aux_operators=self.aux_ops) | ||
result = algo.compute_minimum_eigenvalue( | ||
operator=self.qubit_op, aux_operators=self.aux_ops_list | ||
) | ||
self.assertEqual(result.eigenvalue, None) | ||
self.assertEqual(result.eigenstate, None) | ||
self.assertEqual(result.aux_operator_eigenvalues, None) | ||
|
@@ -119,6 +130,31 @@ def test_cme_1q(self, op): | |
result = algo.compute_minimum_eigenvalue(operator=op) | ||
self.assertAlmostEqual(result.eigenvalue, -1) | ||
|
||
def test_cme_aux_ops_dict(self): | ||
"""Test dictionary compatibility of aux_operators""" | ||
# Start with an empty dictionary | ||
algo = NumPyMinimumEigensolver() | ||
result = algo.compute_minimum_eigenvalue(operator=self.qubit_op, aux_operators={}) | ||
self.assertAlmostEqual(result.eigenvalue, -1.85727503 + 0j) | ||
self.assertIsNone(result.aux_operator_eigenvalues) | ||
|
||
# Add aux_operators dictionary and go again | ||
result = algo.compute_minimum_eigenvalue( | ||
operator=self.qubit_op, aux_operators=self.aux_ops_dict | ||
) | ||
self.assertAlmostEqual(result.eigenvalue, -1.85727503 + 0j) | ||
self.assertEqual(len(result.aux_operator_eigenvalues), 2) | ||
np.testing.assert_array_almost_equal(result.aux_operator_eigenvalues["aux_op1"], [2, 0]) | ||
np.testing.assert_array_almost_equal(result.aux_operator_eigenvalues["aux_op2"], [0, 0]) | ||
|
||
# Add None and zero operators and go again | ||
extra_ops = {"None_op": None, "zero_op": 0, **self.aux_ops_dict} | ||
result = algo.compute_minimum_eigenvalue(operator=self.qubit_op, aux_operators=extra_ops) | ||
self.assertAlmostEqual(result.eigenvalue, -1.85727503 + 0j) | ||
self.assertEqual(len(result.aux_operator_eigenvalues), 2) | ||
np.testing.assert_array_almost_equal(result.aux_operator_eigenvalues["aux_op1"], [2, 0]) | ||
np.testing.assert_array_almost_equal(result.aux_operator_eigenvalues["aux_op2"], [0, 0]) | ||
|
||
|
||
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. @mrossinek I've only added a test for the NumPyMinimumEigenSolver since I did not feel comfortable with adding one for the VQE due to the probabilistic nature. Does this suffice? 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. As a comment we have the algorithm_globals random seed, plus there are simulator and transpiler seeds. You can see these set on a number of tests where random functions are involved to allow the tests to be reproducible. And for VQE the statevector simulation can be used too to get the ideal outcome. 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 we also need some tests for VQE because it does not reuse the entire code from the NumPyMinimumEigensolver. Steve mentioned above how you can avoid issues with the random nature of the tests. |
||
if __name__ == "__main__": | ||
unittest.main() |
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.
Would it be valid to restrict the dictionary key to a
str
, or does it have to beAny
? If users want to use the VQE runtime and pass the aux ops as dictionary, it'll have to be serializable which is not guaranteed if the key can be anything.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.
Speaking for the purposes of the Qiskit Nature applications I believe
str
should be sufficient 👍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.
It was discussed earlier #6870 (comment) but the topic of serialization did not arise. It seemed more flexible not to have to constrain key type; of course for serialization in the runtime one could come up with a set of uniques strings and map them on input/output to whatever keys were defined locally by the user - more work of course. I guess it would be easier to go from str to Any down the road if people object to the limitation so if for now str facilitates the runtime I guess we can go with that.
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.
Thanks! I had forgotten about our previous discussion...
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.
@CisterMoke could you please address this suggestion and change
Any
tostr
for the typehint inListOrDict
everywhere?After that I believe we should be able to proceed with merging this 👍
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.
Hi, sorry for the late update! I had kind of forgotten about this pull request at this point 😅