Skip to content

Commit d2f8baa

Browse files
authored
Fix Identity's ctrl_adder (#1781)
`Identity` is a special bloq: its controlled version is still an identity, but with a larger register, ie. calling `Identity(n).controlled(CtrlSpec(QAny(m)))` gets us `Identity(n+m)` The old version of `ctrl_adder()` was using `Autopartition` which failed during decomposition as `Autopartition` is not designed to merge registers and pass them to the inner bloq. This is fixed by this PR by replacing `Autopartition` with `Partition(s)`. This fix is functional but the resulting `show_bloq()` output is less clean as the Partition steps are visible. An alternative (maybe better) fix is to keep using `Autopartition` but mark the control registers as `Unused()`, but It is weird conceptually to not use Identity(n+m) as the controlled Identity. This PR also adds a test covering this bug.
1 parent a897b34 commit d2f8baa

2 files changed

Lines changed: 25 additions & 5 deletions

File tree

qualtran/bloqs/basic_gates/identity.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
Signature,
3333
SoquetT,
3434
)
35+
from qualtran.bloqs.bookkeeping import Partition
3536
from qualtran.drawing import Text, TextBox, WireSymbol
3637
from qualtran.symbolics import is_symbolic, SymbolicInt
3738

@@ -116,11 +117,17 @@ def ctrl_adder(
116117
bb: 'BloqBuilder', ctrl_soqs: Sequence['SoquetT'], in_soqs: Dict[str, 'SoquetT']
117118
) -> Tuple[Iterable['SoquetT'], Iterable['SoquetT']]:
118119
parts = [
119-
(Register(f'ctrl_{i}', dtype=dtype, shape=shape), 'q')
120+
Register(f"ctrl_{i}", dtype=dtype, shape=shape)
120121
for i, (dtype, shape) in enumerate(ctrl_spec.activation_function_dtypes())
121-
] + [(reg, 'q') for reg in self.signature]
122-
all_soqs = in_soqs | {f'ctrl_{i}': ctrl_soq for i, ctrl_soq in enumerate(ctrl_soqs)}
123-
out_soqs = bb.add_and_partition(ctrl_I, partitions=parts, left_only=False, **all_soqs)
122+
] + [reg for reg in self.signature]
123+
124+
all_soqs = in_soqs | {f"ctrl_{i}": ctrl_soq for i, ctrl_soq in enumerate(ctrl_soqs)}
125+
126+
pratition = Partition(ctrl_I.signature.n_qubits(), regs=parts)
127+
q = bb.add(pratition.adjoint(), **all_soqs)
128+
q = bb.add(ctrl_I, q=q)
129+
out_soqs = bb.add(pratition, x=q)
130+
124131
return out_soqs[:-1], out_soqs[-1:]
125132

126133
return ctrl_I, ctrl_adder

qualtran/bloqs/basic_gates/identity_test.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import pytest
1717
import sympy
1818

19-
from qualtran import BloqBuilder
19+
from qualtran import BloqBuilder, CtrlSpec, QBit, Register
2020
from qualtran.bloqs.basic_gates import OneState
2121
from qualtran.bloqs.basic_gates.identity import _identity, _identity_n, _identity_symb, Identity
2222
from qualtran.simulation.classical_sim import (
@@ -106,6 +106,19 @@ def test_identity_controlled():
106106
assert Identity(n).controlled() == Identity(n + 1)
107107

108108

109+
def test_identity_ctrl_adder():
110+
111+
ctrl_I, ctrl_adder = Identity(1).get_ctrl_system(CtrlSpec())
112+
113+
bb = BloqBuilder()
114+
ctrl0 = bb.add_register(Register("ctrl_0", QBit()))
115+
q = bb.add_register(Register("q", QBit()))
116+
assert ctrl0 is not None and q is not None
117+
[ctrl_out], (out_reg,) = ctrl_adder(bb, ctrl_soqs=[ctrl0], in_soqs={"q": q})
118+
composite = bb.finalize(ctrl_0=ctrl_out, q=out_reg)
119+
composite.flatten()
120+
121+
109122
@pytest.mark.notebook
110123
def test_notebook():
111124
execute_notebook('identity')

0 commit comments

Comments
 (0)