Skip to content

A draft for the approximate multi-qubit toffoli gate algorithm#1786

Open
chenyizhang2000 wants to merge 5 commits into
quantumlib:mainfrom
chenyizhang2000:multi_qubit_toffoli_draft
Open

A draft for the approximate multi-qubit toffoli gate algorithm#1786
chenyizhang2000 wants to merge 5 commits into
quantumlib:mainfrom
chenyizhang2000:multi_qubit_toffoli_draft

Conversation

@chenyizhang2000
Copy link
Copy Markdown

No description provided.

@google-cla
Copy link
Copy Markdown

google-cla Bot commented Dec 19, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@review-notebook-app
Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@chenyizhang2000
Copy link
Copy Markdown
Author

The new version has the following updates:

  1. A draft on "concepts" containing a narrative description of the construction
  2. I moved the file into qualtran.bloqs.mcmt.
  3. I added some comments inside the code to meet the docstring conventions, especially for the SamplePreparationBloq. I also adopted bb.alloc(n), bb.add(OneState()), or bb.add(ZeroState()) to simpify things.
  4. I modified the bloqs to make them have the same external interface as MultiAnd.

Copy link
Copy Markdown
Collaborator

@mpharrigan mpharrigan left a comment

Choose a reason for hiding this comment

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

This is fantastic! I think we should name the file approx_multi_toffoli.ipynb or approx_multi_qubit_toffoli.ipynb

The bloq definitions are fully formed and should ultimately get "promoted" to live in a python file in qualtran.bloqs.mcmt. This is a bit more work, so I'm happy to merge the notebook as-is and leave the rest as a follow up; or do it now as part of the PR. The steps would be

  • take bloq class definitions and put into approx_multi_toffoli.py.. import these bloq classes in the concepts notebook
  • Write one or two @bloq_example example instantiations https://qualtran.readthedocs.io/en/latest/Autodoc.html#demo-bloqs-with-bloqexample
  • Add a file for unit tests: approx_multi_toffoli_test.py. Use the bloq examples to run basic validity checks
  • add en entry to qualtran_dev_tools/notebookspecs.py to make an autogenerated reference-api notebook. This can stay separate from the "concepts" notebook you've written.

let me know if you'd like to do that or merge as-is

Comment thread qualtran/bloqs/mcmt/multi_qubit_toffoli.ipynb Outdated
Comment thread qualtran/bloqs/mcmt/multi_qubit_toffoli.ipynb Outdated
@chenyizhang2000
Copy link
Copy Markdown
Author

Moving the bloq definitions into a python file sounds good! I've made the following updates:

  • Renamed the concepts notebook to approx_multi_toffoli.ipynb.
  • Moved the bloq implementations into approx_multi_toffoli.py.
  • Updated the concepts notebook to import the bloqs from qualtran.bloqs.mcmt.
  • Added a NotebookSpecV2 entry for the autogenerated reference API notebook.
  • Added the file approx_multi_toffoli_file.py for unit test, and tried to run some basic validity checks. I don't fully understand the test log though


_, _, target = bloq.call_classically(ctrl=int_to_bits(x_int, m))

assert target == int(x_int == all_ones)
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.

Please add an additional small test that the notebook executes without error. At the top of the file:

import qualtran.testing as qlt_testing

and here at the bottom

@pytest.mark.notebook
def test_notebook():
    qlt_testing.execute_notebook('approx_multi_toffoli')

@mpharrigan
Copy link
Copy Markdown
Collaborator

I don't fully understand the test log though

Can you say more about this? The unit tests pass on my machine and on the automated CI checks on this PR. You can run the unit tests with pytest qualtran/bloqs/mcmt/approx_multi_toffoli_test.py specifically or check/pytest-quick to run all the tests for the whole project

qualtran.bloqs.mcmt.approx_multi_toffoli._PARITY_MASK_DOC,
qualtran.bloqs.mcmt.approx_multi_toffoli._APPROX_MULTI_TOFFOLI_DOC,
],
),
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.

Please run

python dev_tools/autogenerate-bloqs-notebooks-v2.py

which will create a new notebook "approx_multi_toffoli_reference". You'll need to commit that to git (via git add). It'll also edits docs/bloqs/index.rst to include the new notebook in the table-of-contents. you'll need to commit that too

@mpharrigan
Copy link
Copy Markdown
Collaborator

We run the mypy type-checker to try to detect type errors before runtime. You can run this locally with check/mypy. There are a couple of minor issues. You can fix them with these changes:

diff --git a/qualtran/bloqs/mcmt/approx_multi_toffoli.py b/qualtran/bloqs/mcmt/approx_multi_toffoli.py
index 6d9e8620..946c7478 100644
--- a/qualtran/bloqs/mcmt/approx_multi_toffoli.py
+++ b/qualtran/bloqs/mcmt/approx_multi_toffoli.py
@@ -23,6 +23,8 @@ from qualtran.drawing import (
     directional_text_box,
     show_bloq,
 )
+from qualtran.simulation.classical_sim import ClassicalValRetT
+
 
 @dataclass(frozen=True)
 class MultiAndLogDepth(Bloq):
@@ -190,7 +192,7 @@ class MultiAndLogDepth(Bloq):
         junk = [left_out] + left_junk + [right_out] + right_junk
         return junk, out
 
-    def on_classical_vals(self, ctrl: np.ndarray) -> Dict[str, np.ndarray]:
+    def on_classical_vals(self, ctrl: np.ndarray) -> Dict[str, ClassicalValRetT]:
         ctrl = np.asarray(ctrl, dtype=np.uint8)
         effective_ctrl = np.equal(ctrl, np.asarray(self.concrete_cvs)).astype(np.uint8)
         junk, target = self._classical_tree(list(effective_ctrl))
@@ -226,7 +228,7 @@ class MultiAndLogDepth(Bloq):
         return f"MultiAndLogDepth(n={self.n_ctrls})"
 
     def build_call_graph(self, ssa=None):
-        cost = {Toffoli(): self.n_ctrls - 1}
+        cost: Dict[Bloq, int] = {Toffoli(): self.n_ctrls - 1}
         n_neg = sum(int(cv == 0) for cv in self.concrete_cvs)
         if n_neg:
             cost[XGate()] = 2 * n_neg
diff --git a/qualtran/bloqs/mcmt/approx_multi_toffoli_test.py b/qualtran/bloqs/mcmt/approx_multi_toffoli_test.py
index 690db1b0..91bf15be 100644
--- a/qualtran/bloqs/mcmt/approx_multi_toffoli_test.py
+++ b/qualtran/bloqs/mcmt/approx_multi_toffoli_test.py
@@ -36,6 +36,6 @@ def test_approx_multi_toffoli_classical_randomized_notebook_example():
     sample_strings = tuple(random_sample_string(m) for _ in range(k))
     bloq = ApproxMultiToffoli(n=n, k=k, sample_strings=sample_strings)
 
-    _, _, target = bloq.call_classically(ctrl=int_to_bits(x_int, m))
+    _, _, target = bloq.call_classically(ctrl=int_to_bits(x_int, m))  # type: ignore
 
     assert target == int(x_int == all_ones)

@mpharrigan
Copy link
Copy Markdown
Collaborator

We use a linter to statically detect other issues prior to runtime. You can run it with check/pylint. It can take a minute or two to run. The errors are somewhat self-explanatory but let me know if you have any questions

@mpharrigan
Copy link
Copy Markdown
Collaborator

Finally, we use an automated code formatter. When the other checks are good to go, run check/format-incremental --apply to automatically format the code in the PR

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.

2 participants