Skip to content

Add draw method to Operator class #10271

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

Merged
merged 15 commits into from
Aug 4, 2023
Merged

Conversation

diemilio
Copy link
Contributor

@diemilio diemilio commented Jun 13, 2023

Summary

Fix #10154

Details and comments

Add a draw method for the Operator class. This PR covers the text, latex_source and latex, whose behavior is equivalent to that of the Statevector and DensityMatrix classes.

@diemilio diemilio requested review from a team, nonhermitian and ikkoham as code owners June 13, 2023 11:31
@qiskit-bot qiskit-bot added the Community PR PRs from contributors that are not 'members' of the Qiskit repo label Jun 13, 2023
@qiskit-bot
Copy link
Collaborator

Thank you for opening a new pull request.

Before your PR can be merged it will first need to pass continuous integration tests and be reviewed. Sometimes the review process can be slow, so please be patient.

While you're waiting, please feel free to review other open PRs. While only a subset of people are authorized to approve pull requests for merging, everyone is encouraged to review open pull requests. Doing reviews helps reduce the burden on the core team and helps make the project's code better for everyone.

One or more of the the following people are requested to review this:

@diemilio
Copy link
Contributor Author

Hi @jakelishman,

Thanks so much for your feedback yesterday. I am opening the PR as you recommended. I think my only concern is what I mentioned here regarding testing:

The tests for the draw method in the Statevector and DensityMatrix classes do not have any assertions (see here, and here). They just call each of the drawers. I did the same for the Operator class, but not sure if this needs to be fixed.

Copy link
Contributor

@ikkoham ikkoham left a comment

Choose a reason for hiding this comment

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

Thanks. I left some comments about the code.

output = default_output

if output == "repr":
return "self.__repr__()"
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return "self.__repr__()"
return self.__repr__()

Is this correct?

Copy link
Contributor Author

@diemilio diemilio Jun 15, 2023

Choose a reason for hiding this comment

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

@ikkoham, sorry, this is definitely a mistake 😓. I will fix it. I think this shows that the tests definitely need to be fixed as I mentioned in this comment. Do you have any suggestions for what to test for? Also, do you know how we could test the latex option? I wanted to follow what had been done for the Statevector and DensityMatrix drawers, but I think those tests also need to be fixed.

Copy link
Contributor

Choose a reason for hiding this comment

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

hmm... testing latex is difficult. Sorry. I do not have good idea.


else:
raise ValueError(
"""'{}' is not a valid option for drawing {} objects. Please choose from:
Copy link
Contributor

Choose a reason for hiding this comment

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

f-string is better than format

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good! I will change it. I was trying to match the code of what's done for states, which uses format.

@coveralls
Copy link

coveralls commented Jun 19, 2023

Pull Request Test Coverage Report for Build 5728161174

  • 16 of 28 (57.14%) changed or added relevant lines in 2 files are covered.
  • 8 unchanged lines in 3 files lost coverage.
  • Overall coverage increased (+0.01%) to 85.91%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/visualization/state_visualization.py 2 7 28.57%
qiskit/quantum_info/operators/operator.py 14 21 66.67%
Files with Coverage Reduction New Missed Lines %
qiskit/visualization/state_visualization.py 1 56.95%
qiskit/pulse/library/waveform.py 3 93.75%
crates/qasm2/src/lex.rs 4 92.15%
Totals Coverage Status
Change from base Build 5727764372: 0.01%
Covered Lines: 73098
Relevant Lines: 85087

💛 - Coveralls

@diemilio
Copy link
Contributor Author

diemilio commented Jul 5, 2023

Hi @ikkoham. Do you have any other comments/changes regarding this PR? Happy to take care of anything that might be missing.

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.

Thanks for looking at this Diego, and sorry I left it so long. I only had a couple of minor things, mostly about how to fix the build.

Comment on lines 1410 to 1414
if set(state.dims()) == {2}:
if isinstance(state, (Statevector, DensityMatrix)) and set(state.dims()) == {2}:
dims = False
else:
dims = True
Copy link
Member

Choose a reason for hiding this comment

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

The same logical suppression here would be in the Operator is a square multi-qubit operator, i.e. len(op.dims_l) == len(op.dims_r) and set(op.dims_l) == set(op.dims_r) == {2} (or whatever the syntax is for getting the left- and right-dimensions).

Comment on lines 1435 to 1441
dimstr += f"dims={self.state._op_shape.dims_l()}"
if isinstance(self.state, (Statevector, DensityMatrix)):
dimstr += f"dims={self.state._op_shape.dims_l()}"
elif isinstance(self.state, Operator):
dimstr += f"input_dims={self.state.input_dims()}, "
dimstr += f"output_dims={self.state.output_dims()}"

Copy link
Member

Choose a reason for hiding this comment

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

I always get a little nervous when I see unhandled else branches like this, because if the interface were to expand in the future, we'd silently do nothing. Maybe just drop the isinstance(self.state, Operator) check and make it an unconditional else? That way at least, if the interface expands in the future, we'll at least either do something sensible, or raise an error - both are better than silently doing nothing.

Comment on lines 4 to 6
The :class:`Operator` class now has ``.draw()`` methods allowing it to be displayed as
a text matrix, IPython Latex object or Latex source. The default draw type still is the
ASCII `__repr__` of the operator.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
The :class:`Operator` class now has ``.draw()`` methods allowing it to be displayed as
a text matrix, IPython Latex object or Latex source. The default draw type still is the
ASCII `__repr__` of the operator.
The :class:`Operator` class now has a :meth:`~.Operator.draw` method allowing it to be displayed as
a text matrix, IPython LaTeX object or LaTeX source. The default draw type still is the
ASCII ``__repr__`` of the operator.

Comment on lines 8 to 12
.. jupyter-execute::

from qiskit.quantum_info import Operator
op = Operator.from_label('XH')
op.draw('latex')
Copy link
Member

Choose a reason for hiding this comment

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

We don't use jupyter-execute in the docs, which is why the build is failing (we found it to be too unreliable and too slow). In this case, I think it's probably ok just to skip the example.

Comment on lines +684 to +694
def test_drawings(self):
"""Test draw method"""
qc1 = QFT(5)
op = Operator.from_circuit(qc1)
with self.subTest(msg="str(operator)"):
str(op)
for drawtype in ["repr", "text", "latex_source"]:
with self.subTest(msg=f"draw('{drawtype}')"):
op.draw(drawtype)
with self.subTest(msg=" draw('latex')"):
op.draw("latex")
Copy link
Member

Choose a reason for hiding this comment

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

I see that this test is the same as for Statevector and DensityMatrix, so it's probably best to leave it as you've written it (i.e. just assert that no errors are raised), though if there were something sensible we could sensibly assert about the output, that wouldn't hurt.

@diemilio
Copy link
Contributor Author

diemilio commented Aug 3, 2023

Thank you so much for taking the time to look into this, @jakelishman. I made all the changes you recommended, but please let me know if you feel there is anything missing.

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.

Looks good to me now, thanks for the updates and sorry it took so long to get final review / merge!

@jakelishman jakelishman added Changelog: New Feature Include in the "Added" section of the changelog mod: quantum info Related to the Quantum Info module (States & Operators) mod: visualization qiskit.visualization labels Aug 4, 2023
@jakelishman jakelishman added this to the 0.45.0 milestone Aug 4, 2023
@jakelishman jakelishman added this pull request to the merge queue Aug 4, 2023
@diemilio
Copy link
Contributor Author

diemilio commented Aug 4, 2023

No prob. Thank you @jakelishman for the feedback.

Merged via the queue into Qiskit:main with commit d7f02a6 Aug 4, 2023
SameerD-phys pushed a commit to SameerD-phys/qiskit-terra that referenced this pull request Sep 7, 2023
* add draw method to Operator class

* add _ipython_display_ to operator class

* (fix) check type of state in TextMatrix to allow the use of Operators

* add Operator drawer tests

* eblack, elint changes

* add reno

* (fix) replace repr output, change ValueError to f-string

* (fix) remove duplicate 'latex' option in test_operator

* fix lint, build errors

* add condition to TextMatrix to hide dims for qubit operator

* (fix) remove elif statement in TextMatrix to avoid unhandled else branch
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 Community PR PRs from contributors that are not 'members' of the Qiskit repo mod: quantum info Related to the Quantum Info module (States & Operators) mod: visualization qiskit.visualization
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

Add .draw() method to quantum_info.Operator class
5 participants