Skip to content

Commit 05504ce

Browse files
authored
[mod_arithmetic] Organize modular addition (#907)
* [mod_arithmetic] Organize modular addition * C[AddK] -> AddK with cvs and fixes * format and minimize changes * mark notebook test * revert tcompl removal * reconcile with ecc commit * format * Don't test notebooks twice * fix merge conflict: wire symbol * fixes (typing, generally) * format * merge conflicts * lint * more mergy issues
1 parent 32ad347 commit 05504ce

26 files changed

Lines changed: 780 additions & 610 deletions

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
pip install -r dev_tools/requirements/envs/pytest.env.txt
3333
pip install --no-deps -e .
3434
- run: |
35-
check/pytest -m 'not notebooks'
35+
check/pytest -m 'not notebook'
3636
3737
pytest-dev-tools:
3838
runs-on: ubuntu-latest

dev_tools/autogenerate-bloqs-notebooks-v2.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
import qualtran.bloqs.factoring.mod_exp
7979
import qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp
8080
import qualtran.bloqs.mcmt.and_bloq
81+
import qualtran.bloqs.mod_arithmetic.mod_addition
8182
import qualtran.bloqs.multiplexers.apply_gate_to_lth_target
8283
import qualtran.bloqs.multiplexers.select_pauli_lcu
8384
import qualtran.bloqs.phase_estimation.lp_resource_state
@@ -291,7 +292,6 @@
291292
bloq_specs=[
292293
qualtran.bloqs.arithmetic.addition._ADD_DOC,
293294
qualtran.bloqs.arithmetic.addition._ADD_OOP_DOC,
294-
qualtran.bloqs.arithmetic.addition._SIMPLE_ADD_K_DOC,
295295
qualtran.bloqs.arithmetic.addition._ADD_K_DOC,
296296
],
297297
),
@@ -367,6 +367,17 @@
367367
),
368368
]
369369

370+
MOD_ARITHMETIC = [
371+
NotebookSpecV2(
372+
title='Modular Addition',
373+
module=qualtran.bloqs.mod_arithmetic.mod_addition,
374+
bloq_specs=[
375+
qualtran.bloqs.mod_arithmetic.mod_addition._MOD_ADD_DOC,
376+
qualtran.bloqs.mod_arithmetic.mod_addition._MOD_ADD_K_DOC,
377+
],
378+
)
379+
]
380+
370381

371382
ROT_QFT_PE = [
372383
# --------------------------------------------------------------------------
@@ -544,6 +555,7 @@
544555
('Basic Gates', BASIC_GATES),
545556
('Chemistry', CHEMISTRY),
546557
('Arithmetic', ARITHMETIC),
558+
('Modular Arithmetic', MOD_ARITHMETIC),
547559
('Rotations', ROT_QFT_PE),
548560
('Other', OTHER),
549561
]

docs/bloqs/index.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ Bloqs Library
6565
factoring/ecc/ecc.ipynb
6666
factoring/ecc/ec_add.ipynb
6767

68+
.. toctree::
69+
:maxdepth: 2
70+
:caption: Modular Arithmetic:
71+
72+
mod_arithmetic/mod_addition.ipynb
73+
6874
.. toctree::
6975
:maxdepth: 2
7076
:caption: Rotations:

qualtran/bloqs/arithmetic/__init__.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from qualtran.bloqs.arithmetic.addition import (
16-
Add,
17-
AddConstantMod,
18-
OutOfPlaceAdder,
19-
SimpleAddConstant,
20-
Subtract,
21-
)
15+
from qualtran.bloqs.arithmetic.addition import Add, AddK, OutOfPlaceAdder, Subtract
2216
from qualtran.bloqs.arithmetic.comparison import (
2317
BiQubitsMixer,
2418
EqualsAConstant,
@@ -41,4 +35,4 @@
4135
)
4236
from qualtran.bloqs.arithmetic.sorting import BitonicSort, Comparator
4337

44-
from ._shims import AddK, CHalf, Lt, MultiCToffoli, Negate, Sub
38+
from ._shims import CHalf, Lt, MultiCToffoli, Negate, Sub

qualtran/bloqs/arithmetic/_shims.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,6 @@ def build_call_graph(self, ssa: 'SympySymbolAllocator') -> Set['BloqCountT']:
4040
return {(Toffoli(), self.n - 2)}
4141

4242

43-
@frozen
44-
class AddK(Bloq):
45-
n: int
46-
k: int
47-
48-
@cached_property
49-
def signature(self) -> 'Signature':
50-
return Signature([Register('x', QUInt(self.n))])
51-
52-
5343
@frozen
5444
class Sub(Bloq):
5545
n: int

qualtran/bloqs/arithmetic/addition.ipynb

Lines changed: 27 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -307,149 +307,19 @@
307307
},
308308
{
309309
"cell_type": "markdown",
310-
"id": "1df2fb29",
310+
"id": "2813f173",
311311
"metadata": {
312-
"cq.autogen": "AddConstantMod.bloq_doc.md"
312+
"cq.autogen": "AddK.bloq_doc.md"
313313
},
314314
"source": [
315-
"## `AddConstantMod`\n",
316-
"Applies U(add, M)|x> = |(x + add) % M> if x < M else |x>.\n",
317-
"\n",
318-
"Applies modular addition to input register `|x>` given parameters `mod` and `add_val` s.t.\n",
319-
" 1. If integer `x` < `mod`: output is `|(x + add) % M>`\n",
320-
" 2. If integer `x` >= `mod`: output is `|x>`.\n",
321-
"\n",
322-
"This condition is needed to ensure that the mapping of all input basis states (i.e. input\n",
323-
"states |0>, |1>, ..., |2 ** bitsize - 1) to corresponding output states is bijective and thus\n",
324-
"the gate is reversible.\n",
325-
"\n",
326-
"Also supports controlled version of the gate by specifying a per qubit control value as a tuple\n",
327-
"of integers passed as `cvs`."
328-
]
329-
},
330-
{
331-
"cell_type": "code",
332-
"execution_count": null,
333-
"id": "5ef2dab4",
334-
"metadata": {
335-
"cq.autogen": "AddConstantMod.bloq_doc.py"
336-
},
337-
"outputs": [],
338-
"source": [
339-
"from qualtran.bloqs.arithmetic import AddConstantMod"
340-
]
341-
},
342-
{
343-
"cell_type": "markdown",
344-
"id": "ed3f3c05",
345-
"metadata": {
346-
"cq.autogen": "AddConstantMod.example_instances.md"
347-
},
348-
"source": [
349-
"### Example Instances"
350-
]
351-
},
352-
{
353-
"cell_type": "code",
354-
"execution_count": null,
355-
"id": "195a8047",
356-
"metadata": {
357-
"cq.autogen": "AddConstantMod.add_k_symb"
358-
},
359-
"outputs": [],
360-
"source": [
361-
"n, m, k = sympy.symbols('n m k')\n",
362-
"add_k_symb = AddConstantMod(bitsize=n, mod=m, add_val=k)"
363-
]
364-
},
365-
{
366-
"cell_type": "code",
367-
"execution_count": null,
368-
"id": "9c3f7fb3",
369-
"metadata": {
370-
"cq.autogen": "AddConstantMod.add_k_small"
371-
},
372-
"outputs": [],
373-
"source": [
374-
"add_k_small = AddConstantMod(bitsize=4, mod=7, add_val=1)"
375-
]
376-
},
377-
{
378-
"cell_type": "code",
379-
"execution_count": null,
380-
"id": "bdc82bc1",
381-
"metadata": {
382-
"cq.autogen": "AddConstantMod.add_k_large"
383-
},
384-
"outputs": [],
385-
"source": [
386-
"add_k_large = AddConstantMod(bitsize=64, mod=500, add_val=23)"
387-
]
388-
},
389-
{
390-
"cell_type": "markdown",
391-
"id": "b6885dbb",
392-
"metadata": {
393-
"cq.autogen": "AddConstantMod.graphical_signature.md"
394-
},
395-
"source": [
396-
"#### Graphical Signature"
397-
]
398-
},
399-
{
400-
"cell_type": "code",
401-
"execution_count": null,
402-
"id": "65773e01",
403-
"metadata": {
404-
"cq.autogen": "AddConstantMod.graphical_signature.py"
405-
},
406-
"outputs": [],
407-
"source": [
408-
"from qualtran.drawing import show_bloqs\n",
409-
"show_bloqs([add_k_symb, add_k_small, add_k_large],\n",
410-
" ['`add_k_symb`', '`add_k_small`', '`add_k_large`'])"
411-
]
412-
},
413-
{
414-
"cell_type": "markdown",
415-
"id": "1a4bf832",
416-
"metadata": {
417-
"cq.autogen": "AddConstantMod.call_graph.md"
418-
},
419-
"source": [
420-
"### Call Graph"
421-
]
422-
},
423-
{
424-
"cell_type": "code",
425-
"execution_count": null,
426-
"id": "61f1568e",
427-
"metadata": {
428-
"cq.autogen": "AddConstantMod.call_graph.py"
429-
},
430-
"outputs": [],
431-
"source": [
432-
"from qualtran.resource_counting.generalizers import ignore_split_join\n",
433-
"add_k_symb_g, add_k_symb_sigma = add_k_symb.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
434-
"show_call_graph(add_k_symb_g)\n",
435-
"show_counts_sigma(add_k_symb_sigma)"
436-
]
437-
},
438-
{
439-
"cell_type": "markdown",
440-
"id": "9449e4e9",
441-
"metadata": {
442-
"cq.autogen": "SimpleAddConstant.bloq_doc.md"
443-
},
444-
"source": [
445-
"## `SimpleAddConstant`\n",
315+
"## `AddK`\n",
446316
"Takes |x> to |x + k> for a classical integer `k`.\n",
447317
"\n",
448-
"Applies addition to input register `|x>` given classical integer 'k'.\n",
449-
"\n",
450-
"This is the simple version of constant addition because it involves simply converting the\n",
451-
"classical integer into a quantum parameter and using quantum-quantum addition as opposed to\n",
452-
"designing a bespoke circuit for constant addition based on the classical parameter.\n",
318+
"This construction simply XORs the classical constant into a quantum register and\n",
319+
"applies quantum-quantum addition. This is the lowest T-count algorithm at the expense\n",
320+
"of $n$ auxiliary qubits. This construction also permits an inexpensive controlled version:\n",
321+
"you only need to control the loading of the classical constant which can be done with\n",
322+
"only clifford operations.\n",
453323
"\n",
454324
"#### Parameters\n",
455325
" - `bitsize`: Number of bits used to represent each integer.\n",
@@ -461,26 +331,26 @@
461331
" - `x`: A bitsize-sized input register (register x above). \n",
462332
"\n",
463333
"#### References\n",
464-
" - [Improved quantum circuits for elliptic curve discrete logarithms](https://arxiv.org/abs/2001.09580). Fig 2a\n"
334+
" - [Improved quantum circuits for elliptic curve discrete logarithms](https://arxiv.org/abs/2001.09580). Haner et. al. 2020. Section 3: Components. \"Integer addition\" and Fig 2a.\n"
465335
]
466336
},
467337
{
468338
"cell_type": "code",
469339
"execution_count": null,
470340
"id": "cd255bf9",
471341
"metadata": {
472-
"cq.autogen": "SimpleAddConstant.bloq_doc.py"
342+
"cq.autogen": "AddK.bloq_doc.py"
473343
},
474344
"outputs": [],
475345
"source": [
476-
"from qualtran.bloqs.arithmetic import SimpleAddConstant"
346+
"from qualtran.bloqs.arithmetic import AddK"
477347
]
478348
},
479349
{
480350
"cell_type": "markdown",
481351
"id": "7538f9a5",
482352
"metadata": {
483-
"cq.autogen": "SimpleAddConstant.example_instances.md"
353+
"cq.autogen": "AddK.example_instances.md"
484354
},
485355
"source": [
486356
"### Example Instances"
@@ -491,43 +361,43 @@
491361
"execution_count": null,
492362
"id": "4305289f",
493363
"metadata": {
494-
"cq.autogen": "SimpleAddConstant.simple_add_k_symb"
364+
"cq.autogen": "AddK.add_k"
495365
},
496366
"outputs": [],
497367
"source": [
498368
"n, k = sympy.symbols('n k')\n",
499-
"simple_add_k_symb = SimpleAddConstant(bitsize=n, k=k)"
369+
"add_k = AddK(bitsize=n, k=k)"
500370
]
501371
},
502372
{
503373
"cell_type": "code",
504374
"execution_count": null,
505375
"id": "f6048819",
506376
"metadata": {
507-
"cq.autogen": "SimpleAddConstant.simple_add_k_small"
377+
"cq.autogen": "AddK.add_k_small"
508378
},
509379
"outputs": [],
510380
"source": [
511-
"simple_add_k_small = SimpleAddConstant(bitsize=4, k=2, signed=False)"
381+
"add_k_small = AddK(bitsize=4, k=2, signed=False)"
512382
]
513383
},
514384
{
515385
"cell_type": "code",
516386
"execution_count": null,
517387
"id": "b67fd469",
518388
"metadata": {
519-
"cq.autogen": "SimpleAddConstant.simple_add_k_large"
389+
"cq.autogen": "AddK.add_k_large"
520390
},
521391
"outputs": [],
522392
"source": [
523-
"simple_add_k_large = SimpleAddConstant(bitsize=64, k=-23, signed=True)"
393+
"add_k_large = AddK(bitsize=64, k=-23, signed=True)"
524394
]
525395
},
526396
{
527397
"cell_type": "markdown",
528398
"id": "b8b04228",
529399
"metadata": {
530-
"cq.autogen": "SimpleAddConstant.graphical_signature.md"
400+
"cq.autogen": "AddK.graphical_signature.md"
531401
},
532402
"source": [
533403
"#### Graphical Signature"
@@ -538,20 +408,20 @@
538408
"execution_count": null,
539409
"id": "e93e7f2e",
540410
"metadata": {
541-
"cq.autogen": "SimpleAddConstant.graphical_signature.py"
411+
"cq.autogen": "AddK.graphical_signature.py"
542412
},
543413
"outputs": [],
544414
"source": [
545415
"from qualtran.drawing import show_bloqs\n",
546-
"show_bloqs([simple_add_k_small, simple_add_k_large],\n",
547-
" ['`simple_add_k_small`', '`simple_add_k_large`'])"
416+
"show_bloqs([add_k, add_k_small, add_k_large],\n",
417+
" ['`add_k`', '`add_k_small`', '`add_k_large`'])"
548418
]
549419
},
550420
{
551421
"cell_type": "markdown",
552422
"id": "13552795",
553423
"metadata": {
554-
"cq.autogen": "SimpleAddConstant.call_graph.md"
424+
"cq.autogen": "AddK.call_graph.md"
555425
},
556426
"source": [
557427
"### Call Graph"
@@ -562,14 +432,14 @@
562432
"execution_count": null,
563433
"id": "d8d6584e",
564434
"metadata": {
565-
"cq.autogen": "SimpleAddConstant.call_graph.py"
435+
"cq.autogen": "AddK.call_graph.py"
566436
},
567437
"outputs": [],
568438
"source": [
569439
"from qualtran.resource_counting.generalizers import ignore_split_join\n",
570-
"simple_add_k_small_g, simple_add_k_small_sigma = simple_add_k_small.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
571-
"show_call_graph(simple_add_k_small_g)\n",
572-
"show_counts_sigma(simple_add_k_small_sigma)"
440+
"add_k_g, add_k_sigma = add_k.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
441+
"show_call_graph(add_k_g)\n",
442+
"show_counts_sigma(add_k_sigma)"
573443
]
574444
},
575445
{

0 commit comments

Comments
 (0)