multiplexing
multiplexing ¶
BinaryTreeMultiplexor ¶
Bases: Qubrick
Optimized multiplexing based on Fig. 7 in "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).
compute ¶
compute(index_reg: Qubits, multiplex_function: Callable, used_indices: list[int] | None = None, ctrl: Qubits | int = 0)
Compute the binary tree multiplexing circuit.
We account for various cases:
- There is no data to load (exit the routine).
- Loading a single item does not require this hefty machinery.
- Loading two items without a control is similarly cheap to the single-item-case.
- Loading n > 2 items without a control.
- Loading n > 1 items with a control.
The bottom two cases are handled by calling workhorse methods in this class.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Qubit register storing the values over which the multiplexing is performed. |
required |
multiplex_function
|
Callable
|
A function which takes an index and then index register and performs the operation associated with that index. |
required |
used_indices
|
list
|
List of indices corresponding to terms where the operators are actually being applied. |
None
|
ctrl
|
(int, Qubits)
|
Control register. Defaults to 0. |
0
|
ConditionallyCleanMultiplexor ¶
Bases: Qubrick
Multiplexor utilizing conditionally clean construction as presented in "Rise of conditionally clean ancillae for efficient quantum circuit constructions" (arXiv:2407.17966 ⧉).
See Figure 9 in reference.
This qubrick works by constructing the first relevant index as aggregated conditions and then applies the corresponding data conditioned on this.
Then it sequentially moves through the relevant indices by finding the MSB difference, undoing the structure to this point, and then redo-ing with the
new condition utilising the partial_compute() function.
Notes
This should be called with the filter '>>hermitian-window-filter>>' to take advantage of the cancellations that occur when you replace one condition with the next.
This does the minimal work before calling the filter without hardcoding the cancellations with a maximum filter window required that is linear in the number of qubits in index register.
Hardcoding like in the BinaryTreeMultiplexor requires more care as gates that begin each layer in the conditionally clean structure include adjacent bits such
that the gate that switches branch for bit i, will need to be aware of the higher bit (i-1) to apply the correct cancellation.
compute ¶
compute(index_reg: Qubits, multiplex_function: Callable, used_indices: list[int] | None = None, ctrl: Qubits | int = 0)
Compute the serial multiplexing circuit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Qubit register storing the values over which the multiplexing is performed. |
required |
multiplex_function
|
callable
|
A function which takes an index and then index register and performs the operation associated with that index. |
required |
used_indices
|
list
|
List of indices corresponding to terms where the operators are actually being applied. |
None
|
ctrl
|
(int, Qubits)
|
Control register. Defaults to 0. |
0
|
OneAncMultiplexor ¶
Bases: Qubrick
\(\text{SELECT}\) operator using a single, clean auxiliary qubit.
Circuit shown in Fig. (1.a) in "Trading T gates for dirty qubits in state preparation and unitary synthesis" (arXiv:1812.00954 ⧉).
compute ¶
compute(index_reg: Qubits, multiplex_function: Callable, used_indices: list[int] | None = None, ctrl: Qubits | int = 0)
Compute a multiplexing circuit using a single, clean auxiliary qubit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Qubit register storing the values over which the multiplexing is performed. |
required |
multiplex_function
|
callable
|
A function which takes an index and then index register and performs the operation associated with that index. |
required |
used_indices
|
list
|
List of indices corresponding to terms where the operators are actually being applied. |
None
|
ctrl
|
(int, Qubits)
|
Control register. Defaults to 0. |
0
|
SawtoothMultiplexor ¶
Bases: Qubrick
Unoptimized multiplexor from Fig. 5 in "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).
For some function \(f\) which returns an operator associated with an integer index, performs
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_index
|
(Optional, int)
|
Integer corresponding to the maximum possible index that will be multiplexed over. Defaults to None. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
set_max_index ¶
Set the max index.
Sets the max_index attribute to the input arg.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_val
|
int
|
The max possible index to iterate over. |
required |
compute ¶
compute(index_reg: Qubits, multiplex_function: Callable, used_indices: list[int] | None = None, ctrl: Qubits | int = 0)
Compute the sawtooth multiplexing circuit.
We account for four cases, and some sub-cases:
- There is no data to load (exit the routine).
- Loading a single item does not require this hefty machinery.
- Loading two items without a control is similarly cheap to the single-item-case.
- All other cases will proceed with unary iteration, removing controls on the index register when possible.
The last case above has a couple of sub-cases:
4a) We (rarely, but sometimes) may determine we needn't control on any qubit for a particular index value; consider this a free lunch!
4b) The uncontrolled version of this routine is slightly cheaper than the controlled case. We actually have additional small sub-cases here: (i) If we determine we only need to control on a single qubit for a particular index, we can directly apply that element and exit the for loop. (ii) In all other cases, the uncontrolled case uses one fewer auxiliary qubit than the controlled case (and also one fewer elbow).
4c) After accounting for one fewer qubit for the uncontrolled case, the controlled and uncontrolled case than perform the same logic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Qubit register storing the values over which the multiplexing is performed. |
required |
multiplex_function
|
callable
|
A function which takes an index and then index register and performs the operation associated with that index. |
required |
used_indices
|
list
|
List of indices corresponding to terms where the operators are actually being applied. |
None
|
ctrl
|
(int, Qubits)
|
Control register. Defaults to 0. |
0
|
ZeroAncMultiplexor ¶
Bases: Qubrick
Most naïve version of multiplexing possible.
For some function \(f\) which returns an operator associated with an integer index performs
compute ¶
compute(index_reg: Qubits, multiplex_function: Callable, used_indices: list[int] | None = None, ctrl: Qubits | int = 0)
Compute the serial multiplexing circuit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Qubit register storing the values over which the multiplexing is performed. |
required |
multiplex_function
|
callable
|
A function which takes an index and then index register and performs the operation associated with that index. |
required |
used_indices
|
list
|
List of indices corresponding to terms where the operators are actually being applied. |
None
|
ctrl
|
(int, Qubits)
|
Control register. Defaults to 0. |
0
|
get_default_multiplex_function ¶
Factory to generate the default multiplexing function.
This default function assumes two kinds of input data:
- A PauliSum object.
- A list of integers (to be loaded by, say, a QROM).
This function acts as a factory to return a multiplexing function that applies the element in data at the position given by the index onto the target register controlled on the index qubits being in the binary state representing the index value.
Note
All multiplexing functions must adhere to the contract of having a signature of index (int), index_qubits (Qubits), and ctrl (Qubits or int), such that the multiplexors that call them are promised a certain signature.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_reg
|
Qubits
|
The target register to apply the operation on. |
required |
data
|
Union[PauliSum, List, Dict]
|
The object storing the operation that should be applied at the given index. Typically a PauliSum, List, or Dict. Examples also include a List/Dict of PauliMasks or a List/Dict of bitmasks. |
required |
Returns:
| Type | Description |
|---|---|
Callable
|
Multiplexing function. |
get_multiplex_function_of_indexed_callables ¶
Factory to generate a multiplexing function when data contains a list of callable operators.
This function acts as a factory to return a multiplexing function that takes the callable given by the first element at the position in "data" given by "index" and calls that operation on the target register controlled on the index qubits being in the binary state representing the index value.
Note
All multiplexing functions must adhere to the contract of having a signature of index (int), index_qubits (Qubits), and ctrl (Qubits or int), such that the multiplexors that call them are promised a certain signature.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_reg
|
Qubits
|
The target register to apply the operation on. |
required |
data
|
List or Dict
|
The List or Dict storing the callables (as the first element in the Tuple) and any kwargs needed for that callable (as the second element in the Tuple). |
required |
Returns:
| Type | Description |
|---|---|
Callable
|
Callable multiplexing function. |