Skip to content

Commit 25d9369

Browse files
Add bloq for Binary Polynomial Multiplication (#1554)
The bloqs `BinaryPolynomialMultiplication` and `MultiplyPolyByOnePlusXk` implement karatsuba's algorithm for binary polynomial multiplication with toffoli count of $n^{\log_2{3}}$ and clifford count upper bounded by $(10 + \frac{1}{3}) n^{\log_2{3}}$. The construction of each recursively calls the other. These two bloqs are algorithms 3 and 2 from https://arxiv.org/pdf/1910.02849v2 respectively. In a final PR, I will implement algorithm 4 which implements galois multiplication in GF($2^n$) $\mod m(x)$ where $m(x)$ is an irreducible binary polynomial.
1 parent bf77986 commit 25d9369

File tree

6 files changed

+595
-4
lines changed

6 files changed

+595
-4
lines changed

dev_tools/qualtran_dev_tools/notebook_specs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,8 @@
576576
bloq_specs=[
577577
qualtran.bloqs.gf_arithmetic.gf2_multiplication._GF2_MULTIPLICATION_DOC,
578578
qualtran.bloqs.gf_arithmetic.gf2_multiplication._MULTIPLY_BY_CONSTANT_MOD_DOC,
579+
qualtran.bloqs.gf_arithmetic.gf2_multiplication._MULTIPLY_POLY_BY_ONE_PLUS_XK_DOC,
580+
qualtran.bloqs.gf_arithmetic.gf2_multiplication._BINARY_POLYNOMIAL_MULTIPLICATION_DOC,
579581
],
580582
),
581583
NotebookSpecV2(

qualtran/bloqs/gf_arithmetic/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
from qualtran.bloqs.gf_arithmetic.gf2_addition import GF2Addition
1717
from qualtran.bloqs.gf_arithmetic.gf2_inverse import GF2Inverse
1818
from qualtran.bloqs.gf_arithmetic.gf2_multiplication import (
19+
BinaryPolynomialMultiplication,
1920
GF2Multiplication,
2021
GF2MultiplyByConstantMod,
22+
MultiplyPolyByOnePlusXk,
2123
)
2224
from qualtran.bloqs.gf_arithmetic.gf2_square import GF2Square

qualtran/bloqs/gf_arithmetic/gf2_multiplication.ipynb

Lines changed: 243 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,16 +289,257 @@
289289
"show_call_graph(gf2_multiply_by_constant_modulu_g)\n",
290290
"show_counts_sigma(gf2_multiply_by_constant_modulu_sigma)"
291291
]
292+
},
293+
{
294+
"cell_type": "markdown",
295+
"id": "0b276213",
296+
"metadata": {
297+
"cq.autogen": "MultiplyPolyByOnePlusXk.bloq_doc.md"
298+
},
299+
"source": [
300+
"## `MultiplyPolyByOnePlusXk`\n",
301+
"Out of place multiplication of $(1 + x^k) fg$\n",
302+
"\n",
303+
"Applies the transformation\n",
304+
"$$\n",
305+
"\\ket{f}\\ket{g}\\ket{h} \\rightarrow \\ket{f}{\\ket{g}}\\ket{h \\oplus (1+x^k)fg}\n",
306+
"$$\n",
307+
"\n",
308+
"Note: While this construction follows Algorithm2 of https://arxiv.org/abs/1910.02849v2,\n",
309+
"it has a slight modification. Namely that the original construction doesn't work in\n",
310+
"some cases where $k < n$. However reversing the order of the first set of CNOTs (line 2)\n",
311+
"makes the construction work for all $k \\leq n+1$.\n",
312+
"\n",
313+
"#### Parameters\n",
314+
" - `n`: The degree of the polynomial ($2^n$ is the size of the galois field).\n",
315+
" - `k`: An integer specifing the shift $1 + x^k$ (or $1 + 2^k$ for galois fields.) \n",
316+
"\n",
317+
"#### Registers\n",
318+
" - `f`: The first polynomial.\n",
319+
" - `g`: The second polyonmial.\n",
320+
" - `h`: The target polynomial. \n",
321+
"\n",
322+
"#### References\n",
323+
" - [Space-efficient quantum multiplication of polynomials for binary finite fields with sub-quadratic Toffoli gate count](https://arxiv.org/abs/1910.02849v2). Algorithm 2\n"
324+
]
325+
},
326+
{
327+
"cell_type": "code",
328+
"execution_count": null,
329+
"id": "9949a24e",
330+
"metadata": {
331+
"cq.autogen": "MultiplyPolyByOnePlusXk.bloq_doc.py"
332+
},
333+
"outputs": [],
334+
"source": [
335+
"from qualtran.bloqs.gf_arithmetic import MultiplyPolyByOnePlusXk"
336+
]
337+
},
338+
{
339+
"cell_type": "markdown",
340+
"id": "dd7c9a74",
341+
"metadata": {
342+
"cq.autogen": "MultiplyPolyByOnePlusXk.example_instances.md"
343+
},
344+
"source": [
345+
"### Example Instances"
346+
]
347+
},
348+
{
349+
"cell_type": "code",
350+
"execution_count": null,
351+
"id": "ad918c9f",
352+
"metadata": {
353+
"cq.autogen": "MultiplyPolyByOnePlusXk.multiplypolybyoneplusxk"
354+
},
355+
"outputs": [],
356+
"source": [
357+
"n = 5\n",
358+
"k = 3\n",
359+
"multiplypolybyoneplusxk = MultiplyPolyByOnePlusXk(n, k)"
360+
]
361+
},
362+
{
363+
"cell_type": "markdown",
364+
"id": "aa939469",
365+
"metadata": {
366+
"cq.autogen": "MultiplyPolyByOnePlusXk.graphical_signature.md"
367+
},
368+
"source": [
369+
"#### Graphical Signature"
370+
]
371+
},
372+
{
373+
"cell_type": "code",
374+
"execution_count": null,
375+
"id": "648d128f",
376+
"metadata": {
377+
"cq.autogen": "MultiplyPolyByOnePlusXk.graphical_signature.py"
378+
},
379+
"outputs": [],
380+
"source": [
381+
"from qualtran.drawing import show_bloqs\n",
382+
"show_bloqs([multiplypolybyoneplusxk],\n",
383+
" ['`multiplypolybyoneplusxk`'])"
384+
]
385+
},
386+
{
387+
"cell_type": "markdown",
388+
"id": "4bb8dcef",
389+
"metadata": {
390+
"cq.autogen": "MultiplyPolyByOnePlusXk.call_graph.md"
391+
},
392+
"source": [
393+
"### Call Graph"
394+
]
395+
},
396+
{
397+
"cell_type": "code",
398+
"execution_count": null,
399+
"id": "0890198e",
400+
"metadata": {
401+
"cq.autogen": "MultiplyPolyByOnePlusXk.call_graph.py"
402+
},
403+
"outputs": [],
404+
"source": [
405+
"from qualtran.resource_counting.generalizers import ignore_split_join\n",
406+
"multiplypolybyoneplusxk_g, multiplypolybyoneplusxk_sigma = multiplypolybyoneplusxk.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
407+
"show_call_graph(multiplypolybyoneplusxk_g)\n",
408+
"show_counts_sigma(multiplypolybyoneplusxk_sigma)"
409+
]
410+
},
411+
{
412+
"cell_type": "markdown",
413+
"id": "9d9d1540",
414+
"metadata": {
415+
"cq.autogen": "BinaryPolynomialMultiplication.bloq_doc.md"
416+
},
417+
"source": [
418+
"## `BinaryPolynomialMultiplication`\n",
419+
"Out of place multiplication of binary polynomial multiplication.\n",
420+
"\n",
421+
"Applies the transformation\n",
422+
"$$\n",
423+
"\\ket{f}\\ket{g}\\ket{h} \\rightarrow \\ket{f}{\\ket{g}}\\ket{h \\oplus fg}\n",
424+
"$$\n",
425+
"\n",
426+
"The toffoli cost of this construction is $n^{\\log_2{3}}$, while CNOT count is\n",
427+
"upper bounded by $(10 + \\frac{1}{3}) n^{\\log_2{3}}$.\n",
428+
"\n",
429+
"#### Parameters\n",
430+
" - `n`: The degree of the polynomial ($2^n$ is the size of the galois field). \n",
431+
"\n",
432+
"#### Registers\n",
433+
" - `f`: The first polynomial.\n",
434+
" - `g`: The second polyonmial.\n",
435+
" - `h`: The target polynomial. \n",
436+
"\n",
437+
"#### References\n",
438+
" - [Space-efficient quantum multiplication of polynomials for binary finite fields with sub-quadratic Toffoli gate count](https://arxiv.org/abs/1910.02849v2). Algorithm 3\n"
439+
]
440+
},
441+
{
442+
"cell_type": "code",
443+
"execution_count": null,
444+
"id": "1ba3a057",
445+
"metadata": {
446+
"cq.autogen": "BinaryPolynomialMultiplication.bloq_doc.py"
447+
},
448+
"outputs": [],
449+
"source": [
450+
"from qualtran.bloqs.gf_arithmetic import BinaryPolynomialMultiplication"
451+
]
452+
},
453+
{
454+
"cell_type": "markdown",
455+
"id": "296d193b",
456+
"metadata": {
457+
"cq.autogen": "BinaryPolynomialMultiplication.example_instances.md"
458+
},
459+
"source": [
460+
"### Example Instances"
461+
]
462+
},
463+
{
464+
"cell_type": "code",
465+
"execution_count": null,
466+
"id": "907fcd25",
467+
"metadata": {
468+
"cq.autogen": "BinaryPolynomialMultiplication.binarypolynomialmultiplication"
469+
},
470+
"outputs": [],
471+
"source": [
472+
"n = 5\n",
473+
"binarypolynomialmultiplication = BinaryPolynomialMultiplication(n)"
474+
]
475+
},
476+
{
477+
"cell_type": "markdown",
478+
"id": "a100a193",
479+
"metadata": {
480+
"cq.autogen": "BinaryPolynomialMultiplication.graphical_signature.md"
481+
},
482+
"source": [
483+
"#### Graphical Signature"
484+
]
485+
},
486+
{
487+
"cell_type": "code",
488+
"execution_count": null,
489+
"id": "aad80309",
490+
"metadata": {
491+
"cq.autogen": "BinaryPolynomialMultiplication.graphical_signature.py"
492+
},
493+
"outputs": [],
494+
"source": [
495+
"from qualtran.drawing import show_bloqs\n",
496+
"show_bloqs([binarypolynomialmultiplication],\n",
497+
" ['`binarypolynomialmultiplication`'])"
498+
]
499+
},
500+
{
501+
"cell_type": "markdown",
502+
"id": "c1d23614",
503+
"metadata": {
504+
"cq.autogen": "BinaryPolynomialMultiplication.call_graph.md"
505+
},
506+
"source": [
507+
"### Call Graph"
508+
]
509+
},
510+
{
511+
"cell_type": "code",
512+
"execution_count": null,
513+
"id": "8dc799ef",
514+
"metadata": {
515+
"cq.autogen": "BinaryPolynomialMultiplication.call_graph.py"
516+
},
517+
"outputs": [],
518+
"source": [
519+
"from qualtran.resource_counting.generalizers import ignore_split_join\n",
520+
"binarypolynomialmultiplication_g, binarypolynomialmultiplication_sigma = binarypolynomialmultiplication.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
521+
"show_call_graph(binarypolynomialmultiplication_g)\n",
522+
"show_counts_sigma(binarypolynomialmultiplication_sigma)"
523+
]
292524
}
293525
],
294526
"metadata": {
295527
"kernelspec": {
296-
"display_name": "Python 3",
528+
"display_name": "Python 3 (ipykernel)",
297529
"language": "python",
298530
"name": "python3"
299531
},
300532
"language_info": {
301-
"name": "python"
533+
"codemirror_mode": {
534+
"name": "ipython",
535+
"version": 3
536+
},
537+
"file_extension": ".py",
538+
"mimetype": "text/x-python",
539+
"name": "python",
540+
"nbconvert_exporter": "python",
541+
"pygments_lexer": "ipython3",
542+
"version": "3.11.9"
302543
}
303544
},
304545
"nbformat": 4,

0 commit comments

Comments
 (0)