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

Efficiently check PauliSumOps for diagonality in CVaRMeasurement #7574

Merged
merged 4 commits into from
Feb 1, 2022

Conversation

Cryoris
Copy link
Contributor

@Cryoris Cryoris commented Jan 26, 2022

Summary

Fixes #7573.

Details and comments

See #7573.

@Cryoris Cryoris added stable backport potential The bug might be minimal and/or import enough to be port to stable Changelog: Bugfix Include in the "Fixed" section of the changelog labels Jan 26, 2022
@Cryoris Cryoris added this to the 0.19.2 milestone Jan 26, 2022
Copy link
Member

@jakelishman jakelishman left a comment

Choose a reason for hiding this comment

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

I didn't realise we had too-many-returns active in pylint, but it's not the end of the world. I can't tag them directly in the diff, but the first few lines can become

if isinstance(operator, PauliOp):
    return not np.any(operator.primitive.x)

and the last lines (if np.all(matrix == ...)) can just become

return np.all(matrix == ...)

That saves two return statements (and is generally just better style), so pylint will stop complaining.

A pre-existing problem, but I notice that SummedOp derives from ListOp, so any SummedOp that isn't short-circuited to True will be iterated through three times; once as a SummedOp, once as a ListOp and then once to build the matrix. The if isinstance(operator, ListOp) could become an elif branch of if isinstance(operator, SummedOp) to prevent that.

releasenotes/notes/cvar-paulisumop-fe48698236b77f9b.yaml Outdated Show resolved Hide resolved
Comment on lines 172 to 174
# assert global algorithm settings do not have massive calculations turned on
# (which is the default, but better to be sure in the test!)
algorithm_globals.massive = False
Copy link
Member

Choose a reason for hiding this comment

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

Modifying a global variable in the test has a knock-on effect on others, because the state leaks out - even if this is the default right now, you should check the previous value, do your test in a try-finally and reset it the variable to its previous value in the finally branch. If the default were ever to change, the correctness of the tests would become order-dependent, and we don't make any guarantees about that.

Copy link
Member

Choose a reason for hiding this comment

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

I would actually use self.addCleanup for this instead to have the unittest framework restore the previous value after the test runs regardless of whether passes or fails. Then you don't have to worry about dealing with the error case manually.

Copy link
Contributor Author

@Cryoris Cryoris Jan 26, 2022

Choose a reason for hiding this comment

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

I don't quite get how one would use addCleanup to reset the value. The only thing I would have come up with is

def restore_algorithm_globals_massive(self, value):
    algorithm_globals.massive = value

def test_cvar_on_paulisumop(self):
    self.addCleanup(self.restore_algorithm_globals, algorithm_globals.massive)
    
    # previous test here

Is that what you had in mind?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, that's more or less what I had in mind. I personally would probably have done something like:

self.addCleanUp(lambda x: algorithms_global.massive = x, algorithms_global.massive)
algorithm_globals.massive = False

but turning the lambda into a function works fine too. addCleanup takes a function and args to call it with and builds a LIFO queue to execute of all the addCleanups calls made during the test execution. In this case it's more straightforward though because you only have a single call and argument with a single function.

Copy link
Member

Choose a reason for hiding this comment

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

Another possibility is using unittest.mock.patch as a context manager to patch the value to false for the statements you care about:

with unittest.mock.patch("qiskit.utils.algorithms_global.massive", new=False):
    CVaRMeasurement(...)
    ...

test/python/opflow/test_cvar.py Outdated Show resolved Hide resolved
@coveralls
Copy link

coveralls commented Jan 26, 2022

Pull Request Test Coverage Report for Build 1778963336

  • 8 of 8 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.003%) to 83.157%

Totals Coverage Status
Change from base Build 1778928343: 0.003%
Covered Lines: 51909
Relevant Lines: 62423

💛 - Coveralls

- fix pylint in _is_diagonal
- use elif in _is_diagonal to avoid unnecessary iterations
- fix reno
- add assertion to test
@mergify mergify bot merged commit 47f2c7d into Qiskit:main Feb 1, 2022
mergify bot pushed a commit that referenced this pull request Feb 1, 2022
…t`` (#7574)

* fix cvar for paulisumop

* comments from code review

- fix pylint in _is_diagonal
- use elif in _is_diagonal to avoid unnecessary iterations
- fix reno
- add assertion to test

* cleanup test properly

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 47f2c7d)
mergify bot added a commit that referenced this pull request Feb 1, 2022
…t`` (#7574) (#7602)

* fix cvar for paulisumop

* comments from code review

- fix pylint in _is_diagonal
- use elif in _is_diagonal to avoid unnecessary iterations
- fix reno
- add assertion to test

* cleanup test properly

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 47f2c7d)

Co-authored-by: Julien Gacon <gaconju@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: Bugfix Include in the "Fixed" section of the changelog stable backport potential The bug might be minimal and/or import enough to be port to stable
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CVaRMeasurement does not check PauliSumOps efficiently for diagonality
4 participants