Skip to content

Commit

Permalink
Fix CSwap bloq in mod division (#1528)
Browse files Browse the repository at this point in the history
* fix mod division cswap

* cswapapprox doc - relative phase
  • Loading branch information
anurudhp authored Jan 24, 2025
1 parent c6c11e3 commit 123b83a
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 20 deletions.
23 changes: 9 additions & 14 deletions qualtran/bloqs/mod_arithmetic/mod_division.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,13 @@
from qualtran.bloqs.arithmetic.bitwise import BitwiseNot, XorK
from qualtran.bloqs.arithmetic.comparison import LinearDepthHalfGreaterThan
from qualtran.bloqs.arithmetic.controlled_addition import CAdd
from qualtran.bloqs.basic_gates import CNOT, TwoBitCSwap, XGate
from qualtran.bloqs.basic_gates import CNOT, CSwap, TwoBitCSwap, XGate
from qualtran.bloqs.mcmt import And, MultiAnd
from qualtran.bloqs.mod_arithmetic.mod_multiplication import ModDbl
from qualtran.bloqs.swap_network import CSwapApprox
from qualtran.resource_counting import BloqCountDictT
from qualtran.resource_counting._call_graph import SympySymbolAllocator
from qualtran.symbolics import HasLength, is_symbolic

if TYPE_CHECKING:
from qualtran.resource_counting import BloqCountDictT
from qualtran.resource_counting import BloqCountDictT, SympySymbolAllocator
from qualtran.simulation.classical_sim import ClassicalValT
from qualtran.symbolics import SymbolicInt

Expand Down Expand Up @@ -260,14 +257,12 @@ def on_classical_vals(
def build_composite_bloq(
self, bb: 'BloqBuilder', u: Soquet, v: Soquet, r: Soquet, s: Soquet, a: Soquet
) -> Dict[str, 'SoquetT']:
# CSwapApprox is a CSWAP with a phase flip.
# Since we are doing two SWAPs the overal phase is correct.
a, u, v = bb.add(CSwapApprox(self.bitsize), ctrl=a, x=u, y=v)
a, r, s = bb.add(CSwapApprox(self.bitsize), ctrl=a, x=r, y=s)
a, u, v = bb.add(CSwap(self.bitsize), ctrl=a, x=u, y=v)
a, r, s = bb.add(CSwap(self.bitsize), ctrl=a, x=r, y=s)
return {'u': u, 'v': v, 'r': r, 's': s, 'a': a}

def build_call_graph(self, ssa: SympySymbolAllocator) -> 'BloqCountDictT':
return {CSwapApprox(self.bitsize): 2}
def build_call_graph(self, ssa: 'SympySymbolAllocator') -> 'BloqCountDictT':
return {CSwap(self.bitsize): 2}


@frozen
Expand Down Expand Up @@ -379,8 +374,8 @@ def build_composite_bloq(

r = bb.add(ModDbl(QMontgomeryUInt(self.bitsize), self.mod), x=r)

a, u, v = bb.add(CSwapApprox(self.bitsize), ctrl=a, x=u, y=v)
a, r, s = bb.add(CSwapApprox(self.bitsize), ctrl=a, x=r, y=s)
a, u, v = bb.add(CSwap(self.bitsize), ctrl=a, x=u, y=v)
a, r, s = bb.add(CSwap(self.bitsize), ctrl=a, x=r, y=s)

s_arr = bb.split(s)
s_arr[-1] = bb.add(XGate(), q=s_arr[-1])
Expand All @@ -395,7 +390,7 @@ def build_call_graph(self, ssa: 'SympySymbolAllocator') -> 'BloqCountDictT':
CNOT(): 3,
XGate(): 2,
ModDbl(QMontgomeryUInt(self.bitsize), self.mod): 1,
CSwapApprox(self.bitsize): 2,
CSwap(self.bitsize): 2,
TwoBitCSwap(): self.bitsize - 1,
}

Expand Down
6 changes: 2 additions & 4 deletions qualtran/bloqs/mod_arithmetic/mod_division_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,8 @@ def test_kaliski_mod_bloq_counts(bitsize, mod):
def test_kaliski_symbolic_cost():
n, p = sympy.symbols('n p')
b = KaliskiModInverse(n, p)
cost = get_cost_value(b, QECGatesCost()).total_t_and_ccz_count()
# We have some T gates since we use CSwapApprox instead of n CSWAPs.
total_toff = (cost['n_t'] / 4 + cost['n_ccz']) * sympy.Integer(1)
total_toff = total_toff.expand()
total_toff = get_cost_value(b, QECGatesCost()).total_toffoli_only()
total_toff = sympy.expand(total_toff)

# The toffoli cost from Litinski https://arxiv.org/abs/2306.08585 is 26n^2 + 2n.
# The cost of Kaliski is 2*n*(cost of an iteration) + (cost of computing $p - x$)
Expand Down
2 changes: 1 addition & 1 deletion qualtran/bloqs/swap_network/cswap_approx.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class CSwapApprox(GateWithRegisters):
r"""Approximately implements a multi-target controlled swap unitary using only $4n$ T-gates.
Implements $\mathrm{CSWAP}_n = |0 \rangle\langle 0| I + |1 \rangle\langle 1| \mathrm{SWAP}_n$
such that the output state is correct up to a global phase factor of +1 / -1.
such that the output state is correct up to a relative phase factor of +1/-1 in the standard basis.
This is useful when the incorrect phase can be absorbed in a garbage state of an algorithm
and thus ignored. See the reference for more details.
Expand Down
2 changes: 1 addition & 1 deletion qualtran/bloqs/swap_network/swap_network.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"Approximately implements a multi-target controlled swap unitary using only $4n$ T-gates.\n",
"\n",
"Implements $\\mathrm{CSWAP}_n = |0 \\rangle\\langle 0| I + |1 \\rangle\\langle 1| \\mathrm{SWAP}_n$\n",
"such that the output state is correct up to a global phase factor of +1 / -1.\n",
"such that the output state is correct up to a relative phase factor of +1/-1 in the standard basis.\n",
"\n",
"This is useful when the incorrect phase can be absorbed in a garbage state of an algorithm\n",
"and thus ignored. See the reference for more details.\n",
Expand Down

0 comments on commit 123b83a

Please sign in to comment.