Skip to content

Commit

Permalink
Merge branch 'main' into LessThanGateWriteup
Browse files Browse the repository at this point in the history
  • Loading branch information
NoureldinYosri authored Aug 16, 2023
2 parents 2818d35 + 19c150b commit 573fc2c
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 8 deletions.
2 changes: 1 addition & 1 deletion dev_tools/requirements/envs/dev.env.txt
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ tomlkit==0.12.1
# via pylint
toolz==0.12.0
# via cytoolz
tornado==6.3.2
tornado==6.3.3
# via
# ipykernel
# jupyter-client
Expand Down
2 changes: 1 addition & 1 deletion dev_tools/requirements/envs/docs.env.txt
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ toolz==0.12.0
# via
# -c envs/dev.env.txt
# cytoolz
tornado==6.3.2
tornado==6.3.3
# via
# -c envs/dev.env.txt
# ipykernel
Expand Down
2 changes: 1 addition & 1 deletion dev_tools/requirements/envs/format.env.txt
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ toolz==0.12.0
# via
# -c envs/dev.env.txt
# cytoolz
tornado==6.3.2
tornado==6.3.3
# via
# -c envs/dev.env.txt
# jupyter-client
Expand Down
2 changes: 1 addition & 1 deletion dev_tools/requirements/envs/pylint.env.txt
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ toolz==0.12.0
# via
# -c envs/dev.env.txt
# cytoolz
tornado==6.3.2
tornado==6.3.3
# via
# -c envs/dev.env.txt
# jupyter-client
Expand Down
2 changes: 1 addition & 1 deletion dev_tools/requirements/envs/pytest.env.txt
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ toolz==0.12.0
# via
# -c envs/dev.env.txt
# cytoolz
tornado==6.3.2
tornado==6.3.3
# via
# -c envs/dev.env.txt
# ipykernel
Expand Down
2 changes: 1 addition & 1 deletion dev_tools/requirements/envs/runtime.env.txt
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ toolz==0.12.0
# via
# -c envs/dev.env.txt
# cytoolz
tornado==6.3.2
tornado==6.3.3
# via
# -c envs/dev.env.txt
# jupyter-client
Expand Down
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')
1 change: 1 addition & 0 deletions qualtran/bloqs/basic_gates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@
from .t_gate import TGate
from .toffoli import Toffoli
from .x_basis import MinusEffect, MinusState, PlusEffect, PlusState, XGate
from .y_gate import YGate
from .z_basis import IntEffect, IntState, OneEffect, OneState, ZeroEffect, ZeroState, ZGate
64 changes: 64 additions & 0 deletions qualtran/bloqs/basic_gates/y_gate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

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

import numpy as np
import quimb.tensor as qtn
from attrs import frozen

from qualtran import Bloq, Signature, SoquetT

if TYPE_CHECKING:
import cirq

from qualtran.cirq_interop import CirqQuregT
from qualtran.simulation.classical_sim import ClassicalValT

_PAULIY = np.array([[0, -1j], [1j, 0]], dtype=np.complex128)


@frozen
class YGate(Bloq):
"""The Pauli Y gate.
This causes a bit flip (with a complex phase): Y|0> = 1j|1>, Y|1> = -1j|0>
"""

@cached_property
def signature(self) -> 'Signature':
return Signature.build(q=1)

def add_my_tensors(
self,
tn: qtn.TensorNetwork,
binst,
*,
incoming: Dict[str, SoquetT],
outgoing: Dict[str, SoquetT],
):
tn.add(
qtn.Tensor(
data=_PAULIY, inds=(outgoing['q'], incoming['q']), tags=[self.short_name(), binst]
)
)

def as_cirq_op(
self, qubit_manager: 'cirq.QubitManager', q: 'CirqQuregT'
) -> Tuple['cirq.Operation', Dict[str, 'CirqQuregT']]:
import cirq

(q,) = q
return cirq.Y(q), {'q': [q]}
40 changes: 40 additions & 0 deletions qualtran/bloqs/basic_gates/y_gate_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import cirq
import numpy as np

from qualtran import BloqBuilder
from qualtran.bloqs.basic_gates import MinusState, PlusState, YGate


def test_to_cirq():
bb = BloqBuilder()
q = bb.add(PlusState())
q = bb.add(YGate(), q=q)
cbloq = bb.finalize(q=q)
circuit, _ = cbloq.to_cirq_circuit()
cirq.testing.assert_has_diagram(circuit, "_c(0): ───H───Y───")
vec1 = cbloq.tensor_contract()
vec2 = cirq.final_state_vector(circuit)
np.testing.assert_allclose(vec1, vec2)

bb = BloqBuilder()
q = bb.add(MinusState())
q = bb.add(YGate(), q=q)
cbloq = bb.finalize(q=q)
circuit, _ = cbloq.to_cirq_circuit()
cirq.testing.assert_has_diagram(circuit, "_c(0): ───[ _c(0): ───X───H─── ]───Y───")
vec1 = cbloq.tensor_contract()
vec2 = cirq.final_state_vector(circuit)
np.testing.assert_allclose(vec1, vec2)

0 comments on commit 573fc2c

Please sign in to comment.