Skip to content

Commit

Permalink
Less than equal bloqs. (#348)
Browse files Browse the repository at this point in the history
* Less than equal bloq.

Less than a constant.

* Address comments.
  • Loading branch information
fdmalone authored Aug 15, 2023
1 parent 2d11acc commit 19c150b
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 2 deletions.
80 changes: 79 additions & 1 deletion qualtran/bloqs/arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from functools import cached_property
from typing import Dict, Tuple, Union

import cirq
from attrs import frozen
from cirq_ft import LessThanEqualGate as CirqLessThanEqual
from cirq_ft import LessThanGate as CirqLessThanGate
from cirq_ft import TComplexity

from qualtran import Bloq, Register, Signature
from qualtran import Bloq, CompositeBloq, Register, Signature
from qualtran.cirq_interop import CirqQuregT, decompose_from_cirq_op


@frozen
Expand Down Expand Up @@ -212,3 +219,74 @@ def t_complexity(self):
# See: https://github.com/quantumlib/cirq-qubitization/issues/219
# See: https://github.com/quantumlib/cirq-qubitization/issues/217
return TComplexity(t=8 * self.bitsize)


@frozen
class LessThanEqual(Bloq):
r"""Implements $U|x,y,z\rangle = |x, y, z \oplus {x \le y}\rangle$.
Args:
x_bitsize: bitsize of x register.
y_bitsize: bitsize of y register.
Registers:
- x, y: Registers to compare against eachother.
- z: Register to hold result of comparison.
"""

x_bitsize: int
y_bitsize: int

@cached_property
def signature(self) -> Signature:
return Signature(
[
Register("x", bitsize=self.x_bitsize),
Register("y", bitsize=self.y_bitsize),
Register("z", bitsize=1),
]
)

def decompose_bloq(self) -> 'CompositeBloq':
return decompose_from_cirq_op(self)

def as_cirq_op(
self, qubit_manager: 'cirq.QubitManager', **cirq_quregs: 'CirqQuregT'
) -> Tuple[Union['cirq.Operation', None], Dict[str, 'CirqQuregT']]:
less_than = CirqLessThanEqual(x_bitsize=self.x_bitsize, y_bitsize=self.y_bitsize)
x = cirq_quregs['x']
y = cirq_quregs['y']
z = cirq_quregs['z']
return (less_than.on(*x, *y, *z), cirq_quregs)


@frozen
class LessThanConstant(Bloq):
r"""Implements $U_a|x\rangle = U_a|x\rangle|z\rangle = |x\rangle |z ^ (x < a)\rangle"
Args:
bitsize: bitsize of x register.
val: integer to compare x against (a above.)
Registers:
- x: Registers to compare against val.
- z: Register to hold result of comparison.
"""

bitsize: int
val: int

@cached_property
def signature(self) -> Signature:
return Signature.build(x=self.bitsize, z=1)

def decompose_bloq(self) -> 'CompositeBloq':
return decompose_from_cirq_op(self)

def as_cirq_op(
self, qubit_manager: 'cirq.QubitManager', **cirq_quregs: 'CirqQuregT'
) -> Tuple[Union['cirq.Operation', None], Dict[str, 'CirqQuregT']]:
less_than = CirqLessThanGate(bitsize=self.bitsize, less_than_val=self.val)
x = cirq_quregs['x']
z = cirq_quregs['z']
return (less_than.on(*x, *z), cirq_quregs)
29 changes: 28 additions & 1 deletion qualtran/bloqs/arithmetic_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,21 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from cirq_ft.algos import LessThanEqualGate as CirqLessThanEquals
from cirq_ft.algos import LessThanGate as CirqLessThanConstant
from cirq_ft.infra import t_complexity

import qualtran.testing as qlt_testing
from qualtran import BloqBuilder, Register
from qualtran.bloqs.arithmetic import Add, GreaterThan, Product, Square, SumOfSquares
from qualtran.bloqs.arithmetic import (
Add,
GreaterThan,
LessThanConstant,
LessThanEqual,
Product,
Square,
SumOfSquares,
)
from qualtran.testing import execute_notebook


Expand Down Expand Up @@ -96,5 +109,19 @@ def test_greater_than():
cbloq = bb.finalize(a=q0, b=q1, result=anc)


def test_less_than_equal():
lte = LessThanEqual(5, 5)
qlt_testing.assert_valid_bloq_decomposition(lte)
cirq_lte = CirqLessThanEquals(5, 5)
assert lte.decompose_bloq().t_complexity() == t_complexity(cirq_lte)


def test_less_than_constant():
ltc = LessThanConstant(5, 7)
qlt_testing.assert_valid_bloq_decomposition(ltc)
cirq_ltc = CirqLessThanConstant(5, 7)
assert ltc.decompose_bloq().t_complexity() == t_complexity(cirq_ltc)


def test_notebook():
execute_notebook('arithmetic')

0 comments on commit 19c150b

Please sign in to comment.