Skip to content

Cleaner way to add CirqGateAsBloq to bloq decompsition? #360

@fdmalone

Description

@fdmalone

I found in #350 a few places where it was initially a bit awkward to map bloq registers to cirq registers and back again. The first case was for arithmetic gates which expect a register called qubits of bitsize=1, and shape=(n,), (rather than bitsize=n in bloqs land)

Converter

def add_from_bloq_register_flat_qubits(
    bb: 'BloqBuilder', cirq_bloq: Bloq, **regs: SoquetT
) -> Tuple[SoquetT, ...]:
    """Helper function to split / join registers for cirq gates expeciting single 'qubits' register.
    Args:
        bb: Bloq builder used during decompostion.
        cirq_bloq: A CirqGateAsBloq wrapped arithmetic gate.
        regs: bloq registers we wish to use as flat list of qubits for cirq gate.
    Returns:
        regs: bloq registers appropriately rejoined following split.
    """
    flat_regs = []
    for _, v in regs.items():
        if v.reg.bitsize == 1:
            flat_regs.append([v])
        else:
            flat_regs.append(bb.split(v))
    qubits = np.concatenate(flat_regs)
    qubits = bb.add(cirq_bloq, qubits=qubits)
    out_soqs = {}
    start = 0
    for _, v in regs.items():
        if v.reg.bitsize == 1:
            end = start + 1
            out_soqs[v] = qubits[start:end][0]
            start += 1
        else:
            end = start + v.reg.bitsize
            out_soqs[v] = bb.join(qubits[start:end])
            start += v.reg.bitsize
    return tuple(s for _, s in out_soqs.items()) 

The second case is being addressed in quantumlib/Cirq#6286 I think, but occurs if bitsize=n, shape=(), then cirq expects bitsize=1 and shape=(n,)

Converter:

def add_from_bloq_registers(
    bb: 'BloqBuilder', cirq_bloq: Bloq, **bloq_regs: SoquetT
) -> Tuple[SoquetT, ...]:
    """Shift from bitsize=n, shape=() to bitsize=1, shape=(n,) and back again"""
    cirq_regs = {}
    for reg_name, soq in bloq_regs.items():
        cirq_regs[reg_name] = bb.split(soq)
    cirq_regs = bb.add(cirq_bloq, **cirq_regs)
    out_soqs = {}
    for ix, (reg_name, soq) in enumerate(bloq_regs.items()):
        out_soqs[reg_name] = bb.join(cirq_regs[ix])
    return tuple(s for _, s in out_soqs.items())

A third example I have is the following (but I'm not sure there is anything to be done):

        ...
        ctrl0, ctrl1, ctrl2, trg = bb.split(bb.allocate(4))
        ctrls, trg = bb.add(
            CirqGateAsBloq(MultiControlPauli(cvs=(1, 1, 1), target_gate=cirq.X)),
            controls=[ctrl0, ctrl1, ctrl2],
            target=[trg],
        )
        ctrl0, ctrl1, ctrl2 = ctrls
        succ = trg[0]

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions