Skip to content

Fix #853: improve formatter for pretty-printing musical score diagrams #1658

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

jbolns
Copy link

@jbolns jbolns commented Jun 2, 2025

The changes in this PR enable pretty print of musical score diagrams.

The changes in qualtran\drawing\_show_funcs.py aim to be enable pretty formatting in a way that is independent from internal logic (to allow for changes) but flexible (to easily adapt to any changes):

  • MSD data is captured on the way to the diagram
  • Inspected, re-shuffled, evaluated, and simplified using incremental RegEx and SymPy steps
  • Re-inserted for final rendered.

If the internal logic changes and labels change (I estimate minimally to moderately), the approach can be adapted by modifying the foundational RegEx capture of symbols and/or the locals for simpify.

&

PR also include a small change to qualtran\bloqs\rotations\quantum_variable_rotation.py. Perhaps I missed something when I set things up since I am submitting this PR as part of unitaryHack and there is limited time to get familiar with the codebase. That said, the offset was causing errors.

Closes #853

Maybe.

Ps. I tend to use more space and comments, but I tried my best to stick to the style in the target files. Happy to expand.

@mhucka mhucka requested review from mpharrigan and tanujkhattar June 3, 2025 23:01
@mhucka mhucka changed the title pretty msds v1 Fix #853: improve formatter for pretty-printing musical score diagrams Jun 3, 2025
@mhucka mhucka added the unitaryhack Candidates for unitaryHACK 2025 label Jun 3, 2025
@@ -191,6 +191,7 @@ def build_composite_bloq(self, bb: 'BloqBuilder', **soqs: 'SoquetT') -> Dict[str
if self.cost_dtype.signed:
out[0] = bb.add(ZPowGate(exponent=1, eps=eps), q=out[0])
offset = 1 + self.cost_dtype.num_frac - self.num_frac_rotations
offset = offset if isinstance(offset, int) else 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

what is the reason for this change? (add a comment?)

Copy link
Author

Choose a reason for hiding this comment

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

I noted this in the issue as a concern/question.

The instructions in the issue do not lead to completion. There is an indexing error in one of the iterations in the loop below this line I added.

qvr_zpow = QvrZPow(Register('x', QFxp(12, 6, False)), gamma = sympy.Symbol('Y'))
show_bloq(qvr_zpow, 'dtype')
show_bloq(qvr_zpow.decompose_bloq(), 'musical_score')

Perhaps I'm missing a step or something. Else, it is a pre-existing bug that might be related to the small angle rotations changes in 38db1af

In the next commit, this line will move to inside the loop to minimise its involvement to only when strictly necessary.

for i in range(num_rotations):
    power_of_two = i - self.num_frac_rotations
    exp = (2**power_of_two) * self.gamma * 2
    offset = offset if isinstance(offset, int) else 1  # offset -> 1 if not int to avoid indexing errors  #HERE
    out[-(i + offset)] = bb.add(ZPowGate(exponent=exp, eps=eps), q=out[-(i + offset)])
return {self.cost_reg.name: bb.join(out, self.cost_dtype)}

However, this is only to ensure things proceed as needed for testing of the feature in this issue.

If the instructions to produce the foundational diagram were incomplete, please let me know.

If it is a bug, it should be checked separately.

@@ -142,3 +145,81 @@ def show_bloq_via_qpic(bloq: 'Bloq', width: int = 1000, height: int = 400):

IPython.display.display(Image(output_file_path, width=width, height=height))
os.remove(output_file_path)


def pretty_format_msd(msd: MusicalScoreData) -> MusicalScoreData:
Copy link
Collaborator

Choose a reason for hiding this comment

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

this function should live in musical_score.py

Copy link
Author

Choose a reason for hiding this comment

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

Moving it. I can also use a smaller function for each soq rather than the entire msd.
Will show in next commit.
Will also add a test in the corresponding file (now possible since its a soq-level function).


def pretty_format_msd(msd: MusicalScoreData) -> MusicalScoreData:
"""
Beautifies MSD to enable pretty diagrams
Copy link
Collaborator

Choose a reason for hiding this comment

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

explain what transformations are done

Copy link
Author

Choose a reason for hiding this comment

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

Will do. Shows in next commit.

Comment on lines 193 to 204
lbl_raw = soq_item.symb.text
lbl_no_symbols, symbol = symbols_to_identity(lbl_raw)
gate, base, exponent = sum([p.split("**", 1) for p in lbl_no_symbols.split("^")], [])

if len(base.split("*", 1)) > 1:
mult_str, base = base.rsplit("*", 1)
mult = sympy.sympify(mult_str, evaluate=True)

exponent = sympy.sympify(exponent, locals=simpify_locals, evaluate=True)
expression = str(base) + "**" + str(exponent)
expression = sympy.sympify(expression, locals=simpify_locals, evaluate=True)
new_lbl = str(gate) + "^" + symbol + "*" + str(expression * mult)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure what this code aims to do, but it seems rather brittle. Why are we replacing parts of the label with the character "1"?

Copy link
Author

Choose a reason for hiding this comment

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

Right, yes! You are completely right.

So, any errors fallback to the original label, which ensures completion, but I can make it more robust in the next commit.

More importantly, the mathematical concern is undeniably valid.

It's clear I took the diagram examples in the issue too literally, perhaps assuming there was some quantum magic happening somewhere that escaped me.

Thinking about it as a standard symbolic equation, there seems to be a need to define a preference:

  • semi-pretty labels: some simplification is possible if Abs(Y) is not evaluated with some sort of substitution (which would affect other Y values), but the pretty version won't be entirely pretty. (better than nothing I guess)
  • arbitrary replacement: pi, 2*pi, some random value? (no likey, not symbolic anymore)
  • user-input placeholder: user chooses what value to use for evaluation (same)
  • a panel of diagrams: several rotation angles rendered as a panel of diagrams rather than a single panel diagram (quite a deviation from original concept so I'm hoping there is another approach I'm not considering but, somewhat applicable).

I'll work a little on the next commit but it would be cool if you could tell me your views on the matter and potential alternatives not considered, to avoid the need for many additional commits.

Copy link
Author

Choose a reason for hiding this comment

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

Actually, after running a few tests if seems the combination of factors is such that only very very very small angles would lead to a difference, in which case, might as well use pi to evaluate the Abs value in the expression. Will explain thoroughly in comments.

@jbolns jbolns requested a review from mpharrigan June 4, 2025 20:35
@jbolns
Copy link
Author

jbolns commented Jun 4, 2025

@mpharrigan
I might be coming across a bit brisk. Apologies. I'd never done hackathons and apparently it gets to my head. 😃
Nonetheless, I value the feedback thus far and the importance of good code. High quality outcome > fast outcome.

@ACE07-Sev
Copy link

ACE07-Sev commented Jun 7, 2025

@jbolns Run ./check/format-incremental --apply to fix your formatting issues. Should only change the 4 files that are complaining.

Also, if you don't have it set up locally, I suggest using wsl and running all the CIs locally so that when the maintainers run the CI, you'd know it's gonna pass and move directly to merge or further notes.

@jbolns
Copy link
Author

jbolns commented Jun 7, 2025

Done, @ACE07-Sev.
Thanks for the heads up. Totally missed that one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
unitaryhack Candidates for unitaryHACK 2025
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a pretty formatter for rotation angles so we can have nicer musical score diagrams
4 participants