Skip to content

Pretty-printing for Statevec and DensityMatrix (closes #501)#524

Open
Vinny010 wants to merge 4 commits into
TeamGraphix:masterfrom
Vinny010:add-statevec-density-pretty-print
Open

Pretty-printing for Statevec and DensityMatrix (closes #501)#524
Vinny010 wants to merge 4 commits into
TeamGraphix:masterfrom
Vinny010:add-statevec-density-pretty-print

Conversation

@Vinny010
Copy link
Copy Markdown

@Vinny010 Vinny010 commented Jun 3, 2026

Closes #501.

Adds human-friendly rendering of amplitudes and states:

  • complex_to_str — renders common values exactly (1/4, √2/2, e^(iπ/3)) via a square-then-rationalize heuristic, reusing the existing angle_to_str for the exponential phase. Supports ASCII / Unicode / LaTeX.
  • statevec_to_str + Statevec.draw — ket notation, honouring the to_dict encoding parameter (e.g. √2/2|00⟩ + √2/2|01⟩).
  • density_matrix_to_str + DensityMatrix.draw — column-aligned grid (ASCII/Unicode) or LaTeX pmatrix.
  • Tests covering the issue examples plus edge cases (zero, negative, pure imaginary, LaTeX, decimal fallback, symbolic), with numpy-style docstrings.

Passes ruff check, ruff format, mypy --strict, and pytest locally (167 tests in the affected suites).

Design points I'd value feedback on:

  • draw() returns a str, consistent with the existing to_unicode / to_latex style.
  • The complex formatter prefers exponential form over cartesian when both magnitude and phase are recognized.

Happy to adjust either.

Developed with LLM assistance, reviewed and tested by me.

…x#501)

Add human-friendly rendering of quantum amplitudes and states:

- `complex_to_str` in `pretty_print.py` recognizes common values and
  renders them exactly instead of as floats: fractions (`1/4`), square
  roots (`√2/2`) and complex exponentials (`e^(iπ/3)`). Recognition uses a
  square-then-rationalize heuristic and reuses the existing `angle_to_str`
  for the exponential phase. Supports ASCII, Unicode and LaTeX output.
- `statevec_to_str` + `Statevec.draw` render a statevector in ket notation
  (e.g. `√2/2|00⟩ + √2/2|01⟩`), honouring the existing `encoding` parameter
  from `Statevec.to_dict`.
- `density_matrix_to_str` + `DensityMatrix.draw` render a density matrix as
  a column-aligned grid (ASCII/Unicode) or a LaTeX `pmatrix`.
- Tests covering the issue examples plus edge cases (zero, negative, pure
  imaginary, LaTeX, decimal fallback, symbolic), with numpy-style docs.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 4, 2026

Codecov Report

❌ Patch coverage is 94.91525% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.00%. Comparing base (fcdb8f4) to head (60b6020).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
graphix/pretty_print.py 94.73% 9 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #524      +/-   ##
==========================================
+ Coverage   88.85%   89.00%   +0.14%     
==========================================
  Files          49       49              
  Lines        7135     7311     +176     
==========================================
+ Hits         6340     6507     +167     
- Misses        795      804       +9     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Vinny010 and others added 2 commits June 4, 2026 10:12
Cover the exponential-with-radius, cartesian, complex-decimal-fallback and
LaTeX/ASCII imaginary branches of complex_to_str, the integer-times-root render
path, and the negative-term, parenthesized-coefficient and unit-negative
branches of Statevec.draw, addressing the patch-coverage gap reported on the PR.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Build the complex-amplitude statevec from a numpy array (numpy.complex128) rather
than a Python complex literal: Python's complex only gained __complex__ in 3.11,
so a bare complex is not a typing.SupportsComplex on 3.10 and is rejected by
Statevec. Also use a real amplitude for the unit-negative case.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Copy link
Copy Markdown
Collaborator

@thierry-martinez thierry-martinez 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 very much for your contribution!

Codecov has detected that some parts of your code are not tested.

As you may have noticed, PR #503 and PR #523 address the same issue (#501). We invite you to cross‑review each other's work: PR reviews are an inherent part of software development, just as important as writing code. Moreover, this review process will help you position your PR relative to the others, allowing us to determine which contribution best addresses the issue.

Comment thread graphix/pretty_print.py Outdated
"""Fallback formatting using rounded decimals."""
unit = _imaginary_unit(output)
if abs(z.imag) <= _DEFAULT_ATOL:
return f"{z.real:.4g}"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We should be able to configure the precision of the printed value.

Comment thread graphix/pretty_print.py Outdated
return outer, inner


def _recognize_real(x: float, max_denominator: int, atol: float) -> tuple[int, int, int] | None:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The name _recognize_real feels overly generic; would _recognize_sqrt be a better fit?

- Add a ``precision`` keyword argument to :func:`complex_to_str`,
  :func:`statevec_to_str`, :func:`density_matrix_to_str` and the matching
  :meth:`Statevec.draw` / :meth:`DensityMatrix.draw` methods to control the
  number of significant digits of the decimal fallback. The default value
  (``4``) preserves the previous behaviour, and a regression test exercises
  multiple precisions.
- Rename ``_recognize_real`` to ``_recognize_sqrt`` to better reflect the
  ``signed_num * sqrt(inner) / den`` form the helper returns (pure rationals
  are covered as ``inner == 1``); update the docstring accordingly.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@Vinny010
Copy link
Copy Markdown
Author

Vinny010 commented Jun 5, 2026

Thanks for the review, @thierry-martinez! Pushed eebb104 addressing both inline points:

  • Configurable precision — added a precision keyword argument to complex_to_str, statevec_to_str, density_matrix_to_str, and the matching Statevec.draw / DensityMatrix.draw methods. It controls the number of significant digits used by the decimal fallback. The default (4) preserves the previous behaviour. New regression test covering several precisions.
  • Rename — renamed _recognize_real to _recognize_sqrt. The helper recognizes a real number as signed_num * sqrt(inner) / den, and the rationals are covered as the special case inner == 1 — added a sentence to the docstring to make that explicit.

I'll have a look at #503 and #523 and follow up with comments there.

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.

Pretty-print for Statevec and DensityMatrix

2 participants