23
23
BloqBuilder ,
24
24
BloqDocSpec ,
25
25
CtrlSpec ,
26
+ QBit ,
26
27
Register ,
27
28
Side ,
28
29
Signature ,
29
30
SoquetT ,
30
31
)
31
- from qualtran ._infra .single_qubit_controlled import SpecializedSingleQubitControlledExtension
32
32
from qualtran .bloqs .block_encoding .block_encoding_base import BlockEncoding
33
33
from qualtran .bloqs .multiplexers .black_box_select import BlackBoxSelect
34
34
from qualtran .bloqs .multiplexers .select_base import SelectOracle
@@ -45,7 +45,7 @@ def _total_bits(registers: Union[Tuple[Register, ...], Signature]) -> int:
45
45
46
46
47
47
@attrs .frozen
48
- class SelectBlockEncoding (BlockEncoding , SpecializedSingleQubitControlledExtension ):
48
+ class SelectBlockEncoding (BlockEncoding ):
49
49
r"""LCU based block encoding using SELECT and PREPARE oracles.
50
50
51
51
Builds the block encoding via
@@ -96,11 +96,6 @@ class SelectBlockEncoding(BlockEncoding, SpecializedSingleQubitControlledExtensi
96
96
97
97
select : Union [BlackBoxSelect , SelectOracle ]
98
98
prepare : Union [BlackBoxPrepare , PrepareOracle ]
99
- control_val : Optional [int ] = None
100
-
101
- @cached_property
102
- def control_registers (self ) -> Tuple [Register , ...]:
103
- return self .select .control_registers
104
99
105
100
@cached_property
106
101
def ancilla_bitsize (self ) -> int :
@@ -137,14 +132,7 @@ def epsilon(self) -> SymbolicFloat:
137
132
138
133
@cached_property
139
134
def signature (self ) -> Signature :
140
- return Signature (
141
- [
142
- * self .control_registers ,
143
- * self .selection_registers ,
144
- * self .junk_registers ,
145
- * self .target_registers ,
146
- ]
147
- )
135
+ return Signature ([* self .selection_registers , * self .junk_registers , * self .target_registers ])
148
136
149
137
@cached_property
150
138
def signal_state (self ) -> Union [BlackBoxPrepare , PrepareOracle ]:
@@ -158,26 +146,12 @@ def build_composite_bloq(self, bb: 'BloqBuilder', **soqs: SoquetT) -> Dict[str,
158
146
def wire_symbol (self , reg : Optional [Register ], idx : Tuple [int , ...] = tuple ()) -> 'WireSymbol' :
159
147
if reg is None :
160
148
return Text ('' )
161
- if reg .name == 'control' :
162
- return Circle (filled = bool (self .control_val ))
163
149
else :
164
150
return TextBox ('B[H]' )
165
151
166
- def get_single_qubit_controlled_bloq (self , control_val : int ) -> 'SelectBlockEncoding' :
167
- if self .control_val is not None :
168
- raise ValueError (
169
- "control_val is not None but trying to build controlled SelectBlockEncoding."
170
- )
171
- c_select = self .select .controlled (ctrl_spec = CtrlSpec (cvs = control_val ))
172
- if not isinstance (c_select , SelectOracle ):
173
- raise TypeError (
174
- f"controlled version of { self .select } = { c_select } must also be a SelectOracle"
175
- )
176
- return attrs .evolve (self , select = c_select , control_val = control_val )
177
-
178
152
179
153
@attrs .frozen
180
- class LCUBlockEncoding (BlockEncoding , SpecializedSingleQubitControlledExtension ):
154
+ class LCUBlockEncoding (BlockEncoding ):
181
155
r"""LCU based block encoding using SELECT and PREPARE oracles.
182
156
183
157
Builds the standard block encoding from an LCU as
@@ -231,7 +205,7 @@ class LCUBlockEncoding(BlockEncoding, SpecializedSingleQubitControlledExtension)
231
205
232
206
@cached_property
233
207
def control_registers (self ) -> Tuple [Register , ...]:
234
- return self .select . control_registers
208
+ return () if self .control_val is None else ( Register ( 'ctrl' , QBit ()),)
235
209
236
210
@cached_property
237
211
def ancilla_bitsize (self ) -> int :
@@ -287,8 +261,18 @@ def _extract_soqs(bloq: Bloq) -> Dict[str, 'SoquetT']:
287
261
return {reg .name : soqs .pop (reg .name ) for reg in bloq .signature .lefts ()}
288
262
289
263
soqs |= bb .add_d (self .prepare , ** _extract_soqs (self .prepare ))
290
- soqs |= bb .add_d (self .select , ** _extract_soqs (self .select ))
264
+
265
+ select_soqs = _extract_soqs (self .select )
266
+ if self .control_val is None :
267
+ soqs |= bb .add_d (self .select , ** select_soqs )
268
+ else :
269
+ _ , ctrl_select_adder = self .select .get_ctrl_system (CtrlSpec (cvs = self .control_val ))
270
+ (ctrl ,), select_soqs_t = ctrl_select_adder (bb , [soqs .pop ('ctrl' )], select_soqs )
271
+ soqs |= {'ctrl' : ctrl }
272
+ soqs |= dict (zip ([reg .name for reg in self .select .signature ], select_soqs_t ))
273
+
291
274
soqs |= bb .add_d (self .prepare .adjoint (), ** _extract_soqs (self .prepare .adjoint ()))
275
+
292
276
return soqs
293
277
294
278
def wire_symbol (self , reg : Optional [Register ], idx : Tuple [int , ...] = tuple ()) -> 'WireSymbol' :
@@ -299,17 +283,13 @@ def wire_symbol(self, reg: Optional[Register], idx: Tuple[int, ...] = tuple()) -
299
283
else :
300
284
return TextBox ('B[H]' )
301
285
302
- def get_single_qubit_controlled_bloq (self , control_val : int ) -> 'LCUBlockEncoding' :
303
- if self .control_val is not None :
304
- raise ValueError (
305
- "control_val is not None but trying to build controlled SelectBlockEncoding."
306
- )
307
- c_select = self .select .controlled (ctrl_spec = CtrlSpec (cvs = control_val ))
308
- if not isinstance (c_select , SelectOracle ):
309
- raise TypeError (
310
- f"controlled version of { self .select } = { c_select } must also be a SelectOracle"
311
- )
312
- return attrs .evolve (self , select = c_select , control_val = control_val )
286
+ def adjoint (self ) -> 'Bloq' :
287
+ from qualtran .bloqs .mcmt .specialized_ctrl import (
288
+ AdjointWithSpecializedCtrl ,
289
+ SpecializeOnCtrlBit ,
290
+ )
291
+
292
+ return AdjointWithSpecializedCtrl (self , SpecializeOnCtrlBit .ONE )
313
293
314
294
315
295
@bloq_example
0 commit comments