Skip to content

Commit

Permalink
And.controlled and MultiAnd.controlled should return MultiAnd
Browse files Browse the repository at this point in the history
  • Loading branch information
NoureldinYosri committed Aug 9, 2024
1 parent a4365b2 commit 4299b87
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 1 deletion.
51 changes: 50 additions & 1 deletion qualtran/bloqs/mcmt/and_bloq.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,19 @@
"""
import itertools
from functools import cached_property
from typing import cast, Dict, Iterable, Iterator, List, Optional, Set, Tuple, TYPE_CHECKING, Union
from typing import (
cast,
Dict,
Iterable,
Iterator,
List,
Optional,
Sequence,
Set,
Tuple,
TYPE_CHECKING,
Union,
)

import attrs
import cirq
Expand All @@ -38,6 +50,7 @@
BloqDocSpec,
CompositeBloq,
ConnectionT,
CtrlSpec,
GateWithRegisters,
QBit,
Register,
Expand All @@ -62,6 +75,8 @@
if TYPE_CHECKING:
import quimb.tensor as qtn

from qualtran import AddControlledT, BloqBuilder, SoquetT


@frozen
class And(GateWithRegisters):
Expand Down Expand Up @@ -214,6 +229,23 @@ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.Circ
def _has_unitary_(self) -> bool:
return not self.uncompute

def get_ctrl_system(self, ctrl_spec: 'CtrlSpec') -> Tuple['Bloq', 'AddControlledT']:
if ctrl_spec != CtrlSpec():
return super().get_ctrl_system(ctrl_spec=ctrl_spec)

if self.uncompute:
bloq = MultiAnd([1, self.cv1, self.cv2]).adjoint()
else:
bloq = MultiAnd([1, self.cv1, self.cv2])

def _add_ctrled(
bb: 'BloqBuilder', ctrl_soqs: Sequence['SoquetT'], in_soqs: Dict[str, 'SoquetT']
) -> Tuple[Iterable['SoquetT'], Iterable['SoquetT']]:
# TODO(#1272): implement this function.
raise NotImplementedError('_add_ctrled is not implemented for And')

return bloq, _add_ctrled


@bloq_example(
generalizer=[cirq_to_bloqs, ignore_cliffords, ignore_alloc_free, generalize_rotation_angle]
Expand Down Expand Up @@ -353,6 +385,23 @@ def build_call_graph(self, ssa: 'SympySymbolAllocator') -> Set['BloqCountT']:

return {(And(), self.n_ctrls - 1)} | pre_post_cliffords

def get_ctrl_system(self, ctrl_spec: 'CtrlSpec') -> Tuple['Bloq', 'AddControlledT']:
if ctrl_spec != CtrlSpec():
return super().get_ctrl_system(ctrl_spec=ctrl_spec)

if not isinstance(self.cvs, tuple):
return super().get_ctrl_system(ctrl_spec=ctrl_spec)

bloq = MultiAnd((1,) + self.cvs)

def _add_ctrled(
bb: 'BloqBuilder', ctrl_soqs: Sequence['SoquetT'], in_soqs: Dict[str, 'SoquetT']
) -> Tuple[Iterable['SoquetT'], Iterable['SoquetT']]:
# TODO(#1272): implement this function.
raise NotImplementedError('_add_ctrled is not implemented for MultiAnd')

return bloq, _add_ctrled


@bloq_example(generalizer=(ignore_cliffords, generalize_cvs))
def _multi_and() -> MultiAnd:
Expand Down
6 changes: 6 additions & 0 deletions qualtran/bloqs/mcmt/and_bloq_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,9 @@ def expected_complexity(gate: MultiAnd, adjoint: bool = False) -> TComplexity:

assert gate.t_complexity() == expected_complexity(gate)
assert gate.adjoint().t_complexity() == expected_complexity(gate, adjoint=True)


def test_controlled_and():
assert And(0, 0).controlled() == MultiAnd([1, 0, 0])
assert And(0, 1, True).controlled() == MultiAnd([1, 0, 1]).adjoint()
assert MultiAnd([0, 1, 0]).controlled() == MultiAnd([1, 0, 1, 0])

0 comments on commit 4299b87

Please sign in to comment.