Modular Addition#

from qualtran import Bloq, CompositeBloq, BloqBuilder, Signature, Register
from qualtran import QBit, QInt, QUInt, QAny
from qualtran.drawing import show_bloq, show_call_graph, show_counts_sigma
from typing import *
import numpy as np
import sympy
import cirq

ModAdd#

An n-bit modular addition gate.

Implements |x>|y> => |x>|y + x % p> using \(4n\) Toffoli gates.

This gate can also operate on integers in the Montgomery form.

Parameters#

  • bitsize: Number of bits used to represent each integer.

  • mod: The modulus for the addition.

Registers#

  • x: A bitsize-sized input register (register x above).

  • y: A bitsize-sized input/output register (register y above).

References#

from qualtran.bloqs.mod_arithmetic import ModAdd

Example Instances#

n, p = sympy.symbols('n p')
mod_add = ModAdd(n, mod=p)

Graphical Signature#

from qualtran.drawing import show_bloqs
show_bloqs([mod_add],
           ['`mod_add`'])

Call Graph#

from qualtran.resource_counting.generalizers import ignore_split_join
mod_add_g, mod_add_sigma = mod_add.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(mod_add_g)
show_counts_sigma(mod_add_sigma)
../../_images/0e086f4a193ea52a3a72f13159b98b0c101dec6361d937d9590c6b3799d82ccd.svg

Counts totals:

  • AddK: 1

  • AddK: 1

  • Add: 1

  • LinearDepthGreaterThan: 1

  • XGate: 1

ModAddK#

Applies U(add, M)|x> = |(x + add) % M> if x < M else |x>.

Applies modular addition to input register |x> given parameters mod and add_val s.t.

  1. If integer x < mod: output is |(x + add) % M>

  2. If integer x >= mod: output is |x>.

This condition is needed to ensure that the mapping of all input basis states (i.e. input states |0>, |1>, …, |2 ** bitsize - 1) to corresponding output states is bijective and thus the gate is reversible.

Also supports controlled version of the gate by specifying a per qubit control value as a tuple of integers passed as cvs.

from qualtran.bloqs.mod_arithmetic import ModAddK

Example Instances#

n, m, k = sympy.symbols('n m k')
mod_add_k = ModAddK(bitsize=n, mod=m, add_val=k)
mod_add_k_small = ModAddK(bitsize=4, mod=7, add_val=1)
mod_add_k_large = ModAddK(bitsize=64, mod=500, add_val=23)

Graphical Signature#

from qualtran.drawing import show_bloqs
show_bloqs([mod_add_k, mod_add_k_small, mod_add_k_large],
           ['`mod_add_k`', '`mod_add_k_small`', '`mod_add_k_large`'])

Call Graph#

from qualtran.resource_counting.generalizers import ignore_split_join
mod_add_k_g, mod_add_k_sigma = mod_add_k.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(mod_add_k_g)
show_counts_sigma(mod_add_k_sigma)
../../_images/abf4e2d5f697dcc0adff76a99a00dcfb961e079b673f0defd37f4ab7c00ada06.svg

Counts totals:

  • Add: 5

CModAdd#

Controlled Modular Addition.

Implements \(\ket{c}\ket{x}\ket{y} \rightarrow \ket{c}\ket{x}\ket{(cx+y)\%p}\) using \(5n+1\) Toffoli gates.

Note: The reference reports \(5n\) toffolis. Our construction has an extra toffoli gate due to the current implementaiton of OutOfPlaceAdder.

Parameters#

  • dtype: Type of the input registers.

  • mod: The modulus for the addition.

  • cv: Control value for which the gate is active.

Registers#

  • ctrl: The control qubit.

  • x: A dtype register.

  • y: A dtype register.

References#

from qualtran.bloqs.mod_arithmetic import CModAdd

Example Instances#

cmodadd_example = CModAdd(QUInt(32), 10**9 + 7)
n, p = sympy.symbols('n p')
cmodadd_symbolic = CModAdd(QUInt(n), p)

Graphical Signature#

from qualtran.drawing import show_bloqs
show_bloqs([cmodadd_example, cmodadd_symbolic],
           ['`cmodadd_example`', '`cmodadd_symbolic`'])

Call Graph#

from qualtran.resource_counting.generalizers import ignore_split_join
cmodadd_example_g, cmodadd_example_sigma = cmodadd_example.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(cmodadd_example_g)
show_counts_sigma(cmodadd_example_sigma)
../../_images/0496fc07ca178d0b11abdb8298f6167e6a84f23e88a5ed4306c85e4d4a6fa939.svg

Counts totals:

  • AddK: 1

  • AddK: 1

  • CAdd: 1

  • CLinearDepthGreaterThan: 1

  • XGate: 1

CModAddK#

Perform x += k mod m for constant k, m and quantum x.

Parameters#

  • k: The integer to add to x.

  • mod: The modulus for the addition.

  • bitsize: The bitsize of the x register.

Registers#

  • ctrl: The control bit

  • x: The register to perform the in-place modular addition.

References#

from qualtran.bloqs.mod_arithmetic import CModAddK

Example Instances#

n, m, k = sympy.symbols('n m k')
cmod_add_k = CModAddK(bitsize=n, mod=m, k=k)
cmod_add_k_small = CModAddK(bitsize=4, mod=7, k=1)

Graphical Signature#

from qualtran.drawing import show_bloqs
show_bloqs([cmod_add_k, cmod_add_k_small],
           ['`cmod_add_k`', '`cmod_add_k_small`'])

Call Graph#

from qualtran.resource_counting.generalizers import ignore_split_join
cmod_add_k_g, cmod_add_k_sigma = cmod_add_k.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(cmod_add_k_g)
show_counts_sigma(cmod_add_k_sigma)
../../_images/ca44cdd3b87886329277c3f673fcd18bba58650181cf848d911302ce1ae197a1.svg

Counts totals:

  • CModAdd: 1

CtrlScaleModAdd#

Perform y += x*k mod m for constant k, m and quantum x, y.

Parameters#

  • k: The constant integer to scale x before adding into y.

  • mod: The modulus of the addition

  • bitsize: The size of the two registers.

Registers#

  • ctrl: The control bit

  • x: The ‘source’ quantum register containing the integer to be scaled and added to y.

  • y: The ‘destination’ quantum register to which the addition will apply.

References#

from qualtran.bloqs.mod_arithmetic import CtrlScaleModAdd

Example Instances#

n, m, k = sympy.symbols('n m k')
ctrl_scale_mod_add = CtrlScaleModAdd(bitsize=n, mod=m, k=k)
ctrl_scale_mod_add_small = CtrlScaleModAdd(bitsize=4, mod=7, k=1)

Graphical Signature#

from qualtran.drawing import show_bloqs
show_bloqs([ctrl_scale_mod_add, ctrl_scale_mod_add_small],
           ['`ctrl_scale_mod_add`', '`ctrl_scale_mod_add_small`'])

Call Graph#

from qualtran.resource_counting.generalizers import ignore_split_join
ctrl_scale_mod_add_g, ctrl_scale_mod_add_sigma = ctrl_scale_mod_add.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(ctrl_scale_mod_add_g)
show_counts_sigma(ctrl_scale_mod_add_sigma)
../../_images/900b4e81eaecd04a7479c136428c0cd4f5c5b8bf7339194a3bb503aafc6c6294.svg

Counts totals:

  • And: $\displaystyle n$

  • And†: $\displaystyle n$

  • CModAddK: $\displaystyle n$