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

Demo about implementing Shor's algorithm with Catalyst #1010

Open
wants to merge 55 commits into
base: master
Choose a base branch
from

Conversation

glassnotes
Copy link
Contributor

@glassnotes glassnotes commented Jan 7, 2024

Title: JIT compiling Shor's algorithm with PennyLane and Catalyst

Summary: Over the past year, PennyLane has been integrated with Catalyst, allowing for quantum just-in-time compilation of classical and quantum code together. This demo leverages that integration to implement a version of Shor's factoring algorithm that is just-in-time compiled from end-to-end, classical control structure and all.

Relevant references: See within

Possible Drawbacks: As it stands, it's quite long (especially for the amount of actual output); I am not sure about the ending.

Related GitHub Issues: N/A


If you are writing a demonstration, please answer these questions to facilitate the marketing process.

  • GOALS — Why are we working on this now?

Highlight PennyLane and Catalyst integration, and expose challenges (and opportunities) in scaling up quantum compilation pipelines.

  • AUDIENCE — Who is this for?

Primarily people researchers and developers focused on quantum compilation.

  • KEYWORDS — What words should be included in the marketing post?

quantum compilation; quantum circuits; quantum algorithms; Shor's algorithm

  • Which of the following types of documentation is most similar to your file?
    (more details here)
  • Tutorial
  • Demo
  • How-to

Comment on lines 102 to 103
# TODO: explain how the modular exponentiation circuits work (not sure yet how to
# best include these, because some are quite large)
Copy link
Contributor

Choose a reason for hiding this comment

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

If you don't want to go into too much detail here, there is an option to upload a .py and simply import the operator. However, I think it would be worth a small tutorial in the future. People would love it!

Comment on lines 26 to 28
a positive step in this direction. In this demonstration we will show how
Catalyst enables an implementation of Shor's factoring algorithm that is
just-in-time compiled from end-to-end, classical control structure and all.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should recommend to the reader something about just-in-time since I think it is super important here and it is not a known term in quantum computing: "If you still don't know what this Jit thing is and the potential it has, I invite you to take a look to ..." or similar

# The quantum part
# ^^^^^^^^^^^^^^^^
#
# TODO: explain how the modular exponentiation circuits work (not sure yet how to
Copy link
Contributor

Choose a reason for hiding this comment

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

Update: pennylane now has qml.ModExp. So we can probably save the explanation here 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I saw! Are they qjit compatible? There is a fair amount of customization in my implementation so I will probably still provide brief explanations, and the circuits, but only what's needed.

Copy link
Contributor

Choose a reason for hiding this comment

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

It should be, let me know if you have any problems :)

Copy link
Member

Choose a reason for hiding this comment

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

Curious if this ended up working!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I haven't tried - I stayed with my own implementations because there are "higher-level" optimizations being applied (like removing entire QFTs, etc.).

@glassnotes glassnotes marked this pull request as ready for review February 7, 2025 22:56
@glassnotes
Copy link
Contributor Author

Marking as ready-for-review to test the build (it worked locally). I'll tag people once a full first draft of all the text and code is finished.

Copy link

github-actions bot commented Feb 8, 2025

Thank you for opening this pull request.

You can find the built site at this link.

Deployment Info:

  • Pull Request ID: 1010
  • Deployment SHA: 004f37810a3fe3cf4a7474a72af78c13f1967d9d
    (The Deployment SHA refers to the latest commit hash the docs were built from)

Note: It may take several minutes for updates to this pull request to be reflected on the deployed site.

Comment on lines 85 to 91
# - First, we randomly select a candidate integer, :math:`a`, between 2 and
# :math:`N-1` (before proceeding, we double check that we did not get lucky and randomly select one of the true factors)
# - Using our chosen a, we proceed to the quantum part of the algorithm: order-finding.
# Quantum circuits are generated, and the circuit is executed on a device. The results
# are used to make a guess for a non-trivial square root.
# - If the square root is non-trivial, we test whether we found the factors. Otherwise, we try again
# with more shots. Eventually, we try with a different value of a.
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
# - First, we randomly select a candidate integer, :math:`a`, between 2 and
# :math:`N-1` (before proceeding, we double check that we did not get lucky and randomly select one of the true factors)
# - Using our chosen a, we proceed to the quantum part of the algorithm: order-finding.
# Quantum circuits are generated, and the circuit is executed on a device. The results
# are used to make a guess for a non-trivial square root.
# - If the square root is non-trivial, we test whether we found the factors. Otherwise, we try again
# with more shots. Eventually, we try with a different value of a.
# - First, we randomly select a candidate integer, :math:`a`, between 2 and
# :math:`N-1` (before proceeding, we double check that we did not get lucky and randomly select one of the true factors)
# - Using our chosen a, we proceed to the quantum part of the algorithm: order-finding.
# Quantum circuits are generated, and the circuit is executed on a device. The results
# are used to make a guess for a non-trivial square root.
# - If the square root is non-trivial, we test whether we found the factors. Otherwise, we try again
# with more shots. Eventually, we try with a different value of a.

@glassnotes glassnotes changed the title [WIP] Demo about implementing Shor's algorithm with Catalyst Demo about implementing Shor's algorithm with Catalyst Feb 11, 2025
Copy link
Contributor Author

@glassnotes glassnotes left a comment

Choose a reason for hiding this comment

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

@KetpuntoG @josh146 @dime10 At long last, here is a first draft for review. It's a long one, so please feel free to tag whoever has some bandwidth. I left some comments within. Two other top-level things:

  • Most of the 90000 lines of this PR is SVG. The actual demo is ~1100
  • The webpage does not seem to fully build. I can find the demo from the front, but most of the links give me XML access denied errors. I don't know if that's expected.

"previewImages": [
{
"type": "thumbnail",
"uri": "/_static/demo_thumbnails/regular_demo_thumbnails/thumbnail_variationally_quantum_linear_solver.png"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just grabbed the thumbnail of another demo for now; many we can use a picture of one of the circuits, or a stylized picture of "N = p q" and a circuit?

.. meta::
:property="og:description": JIT compile Shor's algorithm from end-to-end with PennyLane and Catalyst.

:property="og:image": https://pennylane.ai/qml/_static/demonstration_assets//fano.png
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will need to be updated with new image.

# that function. The next time that function is executed, the compiled version
# can be reused, provided the structure of the inputs hasn't changed.
#
# .. figure:: ../_static/demonstration_assets/shor_catalyst/compilation_comparison.png
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it'd be nice to include a graphic here, but consider this a placeholder (it's just a screenshot from a talk). Any suggestions?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this graphic fits quite nicely actually :)

# QJIT compiling Shor's algorithm
# -------------------------------
#
# Quantum subroutines
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This section is really long and detailed, but it also really helped my understanding to work through the circuits. Suggestions for trimming are welcome

Copy link
Contributor

Choose a reason for hiding this comment

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

I will admit, at some point when I was deep into the explanation of the fourier addition and the subsequent optimization section, I started checking out trying to reason about all these circuits 😵‍💫 😅

The thing is, for someone looking to understand every piece of the algorithm this is actually an incredible resource! For a high-level read of the demo on the other hand it's possible to get lost in there.

Maybe we could have an appendix that explains how Fourier addition works, and the optimizations available there? In the main text we could then highlight two of the important optimizations like pre-computing the powers of a, and the one estimation wire trick, which are already pretty neat :)

return num_to_return, denom_to_return


def phase_to_order(phase, max_denominator):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dime10 is the author of a few of these functions - what's the best way to provide attribution?

N, pow_a, [control_wire, target_wires[n - i - 1]], aux_wires[:-1], aux_wires[-1]
)

qml.adjoint(QFT)(wires=aux_wires[:-1])
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Functions like this one are the reason I'm not using PennyLane's modular arithmetic. They are heavily optimized to remove things like "outer" QFTs that are redundant, and they also implement the optimizations discussed in the circuit section.

# Performance and validation
# ^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# We will now verify that QJIT compilation is happening properly. We will run
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggestions welcome for what to show here. I'm hesitant to include the scaling plots (I prefer to save those for a more formal presentation). I also have not included resource counts because (as mentioned in the conclusion) actual quantum circuit optimization is not applied, so they look huge. Getting the resources also require an implementation in regular PennyLane so qml.specs can be called.

plt.scatter(range(len(times)), times, c=[ex[0] for ex in execution_times])
plt.xticks(range(0, len(times), 2), labels=labels, rotation=80)
plt.xlabel("N, a")
plt.ylabel("Runtime (s)");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can't figure out how to suppress the text output of the plot. Adding a semicolon does not help. Also, would be great to get some feedback on clarity of the plot and whether it is effective in capturing the main points

Copy link
Contributor

Choose a reason for hiding this comment

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

This plot does show the lack of recompilation for different as and even Ns, but I think what might be missing is demonstrating why that is valuable to the user 🤔
What about comparing to the non-jitted version where re-computing and processing new circuits for each a takes a lot of time?

Copy link
Contributor

Choose a reason for hiding this comment

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

I can't figure out how to suppress the text output of the plot.

Have you tried this version?

Suggested change
plt.ylabel("Runtime (s)");
plt.ylabel("Runtime (s)")
plt.show()

# can automatically determine how subroutines can be simplified based on
# classical information or on the input quantum superposition would be valuable
# to develop, as they would enable co-optimization of the classical and quantum
# parts of workflows.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggestions welcome. Honestly this was so long in the making that I was at a loss for what to write here 😅

Copy link
Contributor

Choose a reason for hiding this comment

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

I remember you mentioning how great it was to be able to implement optimizations that are dependent on a without any extra cost, maybe that is something we could highlight in the conclusion? :)

The fact that you can make all these really specific, a-dependent optimizations in the circuit, and it just works after the first run because of jit, is seriously amazing

Copy link
Contributor

@dime10 dime10 left a comment

Choose a reason for hiding this comment

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

First of all, this is an incredible demo!! I'm amazed how well you explain and show the different pieces going in to this, must have been a lot work 😍 The introduction is also really nice :)

Comment on lines +74 to +77
# Over the past year, PennyLane has been integrated with `Catalyst
# <https://docs.pennylane.ai/projects/catalyst/en/latest/index.html>`_, allowing
# for quantum just-in-time compilation of classical and quantum code
# together. This demo leverages that integration to implement a version of
Copy link
Contributor

Choose a reason for hiding this comment

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

This statement confuses me a little bit, hasn't Catalyst been working with PennyLane ever since its release? Obviously features and usability have improved etc., but what did you want to express here?

Comment on lines +79 to +80
# classical control structure and all. Even better, that compilation happens
# only once per distinct bit-width of the integers being factored.
Copy link
Contributor

Choose a reason for hiding this comment

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

😆 It's a good thing we're finally implementing qubit-number-independent compilation, which should make this sentence even more impactful.

Comment on lines +92 to +93
# new program in assembly code; an assembler turns that into a
# machine-executable program that is provided inputs and run
Copy link
Contributor

Choose a reason for hiding this comment

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

The sentence ending in "... turns that into a program that is provided inputs and run[s?]" reads a bit odd to me, any chance we could rephrase it? :)

Comment on lines +1008 to +1010
# To run the algorithm, we must randomly choose ``a``. In principle, we could
# randomly generate ``a`` within the function above. However, this cannot
# currently be QJITted. Passing ``n_bits`` as a static argument is also to work
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh does this not work? Generating random numbers is possible with JAX, the main difference to numpy is that the PRNG state is explicit rather than implicit. We also use them in the MSD demo: https://docs.pennylane.ai/projects/catalyst/en/stable/demos/magic_distillation_demo.html#T-Type-Magic-States

from jax import random


def factor_with_shor(N, n_shots=100):
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm hesitant about the term shots here, since they could be confused with the concept of PennyLane/device shots. Should we just call these trials or similar?

Comment on lines +1103 to +1104
# particularly valuable for large :math:`N`, where compilation time may become
# long.
Copy link
Contributor

Choose a reason for hiding this comment

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

Was this saying that the JIT compilation time is long for large N or that "traditional" (e.g. PennyLane) circuit construction and processing becomes very expensive?
I think when I measured it the increase in JIT compilation time was relatively flat now.

Suggested change
# particularly valuable for large :math:`N`, where compilation time may become
# long.
# particularly valuable for large :math:`N`, where traditional circuit processing times can
# grow very large.

plt.scatter(range(len(times)), times, c=[ex[0] for ex in execution_times])
plt.xticks(range(0, len(times), 2), labels=labels, rotation=80)
plt.xlabel("N, a")
plt.ylabel("Runtime (s)");
Copy link
Contributor

Choose a reason for hiding this comment

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

This plot does show the lack of recompilation for different as and even Ns, but I think what might be missing is demonstrating why that is valuable to the user 🤔
What about comparing to the non-jitted version where re-computing and processing new circuits for each a takes a lot of time?

# can automatically determine how subroutines can be simplified based on
# classical information or on the input quantum superposition would be valuable
# to develop, as they would enable co-optimization of the classical and quantum
# parts of workflows.
Copy link
Contributor

Choose a reason for hiding this comment

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

I remember you mentioning how great it was to be able to implement optimizations that are dependent on a without any extra cost, maybe that is something we could highlight in the conclusion? :)

The fact that you can make all these really specific, a-dependent optimizations in the circuit, and it just works after the first run because of jit, is seriously amazing

Co-authored-by: David Ittah <dime10@users.noreply.github.com>
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.

4 participants