Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permutation Bloq #1110

Merged
merged 18 commits into from
Jul 17, 2024
Prev Previous commit
Next Next commit
cleanup EqualsAConstant
anurudhp committed Jul 17, 2024
commit b2bd6ba54c2cd00fefea8b84df0f8a69911729c3
62 changes: 11 additions & 51 deletions qualtran/bloqs/arithmetic/comparison.py
Original file line number Diff line number Diff line change
@@ -38,7 +38,6 @@
Bloq,
bloq_example,
BloqDocSpec,
DecomposeTypeError,
GateWithRegisters,
QAny,
QBit,
@@ -51,7 +50,7 @@
)
from qualtran.bloqs.basic_gates import CNOT, XGate
from qualtran.bloqs.mcmt.and_bloq import And, MultiAnd
from qualtran.bloqs.mcmt.multi_control_multi_target_pauli import MultiControlX
from qualtran.bloqs.mcmt.multi_control_multi_target_pauli import MultiControlPauli, MultiControlX
from qualtran.drawing import WireSymbol
from qualtran.drawing.musical_score import Text, TextBox
from qualtran.symbolics import HasLength, is_symbolic, SymbolicInt
@@ -960,60 +959,21 @@ def wire_symbol(self, reg: Optional[Register], idx: Tuple[int, ...] = tuple()) -
def is_symbolic(self):
return is_symbolic(self.bitsize, self.val)

def build_composite_bloq(
self, bb: 'BloqBuilder', x: 'Soquet', target: 'Soquet'
) -> Dict[str, 'SoquetT']:
@property
def bits_k(self) -> Union[tuple[int, ...], HasLength]:
if self.is_symbolic():
raise DecomposeTypeError(f"cannot decompose symbolic {self}")
return HasLength(self.bitsize)

bits_k = x.reg.dtype.to_bits(self.val)

if self.bitsize == 1:
# Note: when self.val = 0, this is just a negative-control CNOT.
if self.val == 0:
x = bb.add(XGate(), q=x)
x, target = bb.add(CNOT(), ctrl=x, target=target)
if self.val == 0:
x = bb.add(XGate(), q=x)
elif self.bitsize == 2:
and_bloq = And(bits_k[0], bits_k[1])

xs = bb.split(x)
xs, and_xs = bb.add(and_bloq, ctrl=xs)
and_xs, target = bb.add(CNOT(), ctrl=and_xs, target=target)
xs = bb.add(and_bloq.adjoint(), ctrl=xs, target=and_xs)
x = bb.join(xs)
else:
multi_and_bloq = MultiAnd(tuple(bits_k))

xs = bb.split(x)
xs, junk, and_xs = bb.add(multi_and_bloq, ctrl=xs)
and_xs, target = bb.add(CNOT(), ctrl=and_xs, target=target)
xs = bb.add(multi_and_bloq.adjoint(), ctrl=xs, junk=junk, target=and_xs)
x = bb.join(xs)
assert not isinstance(self.bitsize, sympy.Expr)
assert not isinstance(self.val, sympy.Expr)
return tuple(QUInt(self.bitsize).to_bits(self.val))

def build_composite_bloq(
self, bb: 'BloqBuilder', x: 'Soquet', target: 'Soquet'
) -> Dict[str, 'SoquetT']:
bb.add(MultiControlPauli(self.bits_k, target_gate=cirq.X), controls=x, target=target)
return {'x': x, 'target': target}

def build_call_graph(self, ssa: 'SympySymbolAllocator') -> Set['BloqCountT']:
if not self.is_symbolic():
return super().build_call_graph(ssa)

op: Bloq
if not is_symbolic(self.bitsize) and self.bitsize <= 2:
if self.bitsize == 1:
op = XGate()
else:
cv = ssa.new_symbol('cv')
op = And(cv, cv)
else:
op = MultiAnd(HasLength(self.bitsize))

bloq_counts: dict[Bloq, int] = defaultdict(lambda: 0)
bloq_counts[op] += 1
bloq_counts[op.adjoint()] += 1
bloq_counts[CNOT()] += 1
return set(bloq_counts.items())


def _make_equals_a_constant():
from qualtran.bloqs.arithmetic import EqualsAConstant