data_loading
data_loading ¶
DataLookupClean ¶
DataLookupClean(select: Select, swap_up: SwapUpInterface, fallback_read=FallbackCoinToss, symbolic_mode: str = 'worst', **kwargs)
Bases: Qubrick
Data lookup (QROM) circuit using the SELECT-SwapUp architecture.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
select
|
Qubrick
|
SELECT unitary instance. |
required |
swap_up
|
Qubrick
|
SwapUp unitary instance. |
required |
fallback_read
|
FallbackReadGenerator
|
Constructor of an object providing results of read in case there's no state-vector simulator available. |
FallbackCoinToss
|
symbolic_mode
|
str
|
What kind of symbolic QREs should be provided. Can be either "worst" or "average". |
'worst'
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
compute(index_reg: Qubits, bits_of_precision: int, data: Iterable[int], lambda_val: int | None = None, ctrl: Qubits | int = 0, *, clean: Qubits | None = None)
Compute data lookup (QROM) circuit with clean auxiliary qubits.
This routine loads data conditioned by an index register. It makes use of the SELECT-SwapUp constructions introduced in "Trading T gates for dirty qubits in state preparation and unitary synthesis" (arXiv:1812.00954 ⧉), where we may tune a parameter (colloquially referred to as "lambda") that allows us to trade off between gates and qubits.
Depending on the input args and the chosen lambda value, we consider three cases:
-
If "lambda" is equal to 1, this means we do not introduce any additional auxiliary qubits. This case reduces the QROM to a classic SELECT.
-
If "lambda" is equal to the number of items we are loading, this case reduces to classically writing all data elements and using SwapUp to fetch a particular item and bring it to the top
b"clean" qubits. -
All other cases make use of both SELECT and SwapUp to coherently write and fetch indexed data, respectively.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Index register. |
required |
bits_of_precision
|
int
|
Number of bits to represent item in list. |
required |
data
|
Iterable[int]
|
List of data to load. |
required |
lambda_val
|
int | None
|
Power-of-two knob to trade off between gates
and qubits. If |
None
|
ctrl
|
Qubits | int
|
Qreg to control on. Defaults to 0. |
0
|
clean
|
Qubits | None
|
If passed in, will be used as the output qubits. Useful for reusing registers. |
None
|
Notes
With the introduction of a custom uncompute method for this class, the compute circuit is no longer fully coherent; if we are making use of additional junk registers, we measure them and record the read result to later be used during uncompute. This allows us to release auxiliary qubits that may otherwise constitute a significant space cost.
compute_phase_fixups ¶
Use QROM data to compute the addresses that require phase fixups.
Returns:
| Type | Description |
|---|---|
list[int]
|
A list of each address (int) that requires a phase fixup. |
compute_phase_fixups_symbolic ¶
Use QROM data to compute the addresses that require phase fixups.
It models the worst-case scenario, where all the addresses need a fixup, or the average scenario when only half of them do, depending on self.symbolic_mode.
Returns:
| Type | Description |
|---|---|
SymbolicArray
|
A list of each address (int) that requires a phase fixup. |
DataLookupDirtyNaive ¶
Bases: Qubrick
Naive data lookup (QROM) oracle using dirty auxiliary qubits.
Introduced in Fig. 1D from "Trading T gates for dirty qubits in state preparation and unitary synthesis" (arXiv:1812.00954 ⧉).
Note
This routine makes use of dirty, borrowable qubits. The auxiliary qubits in question can be
any qubits on the entirety of the QPU, so long as they are not the qubits acted on by
the routine itself. By "borrowable", we mean that after compute is called, the dirty
auxiliary qubits are returned to their initial state; we do not need to wait until uncomputation
for these qubits to be returned to their initial state.
The current implementation makes use of _dirty_qubits to find borrowable qubits; this will
likely change in the future once a dirty auxiliary qubits management scheme is formally implemented in Workbench.
A consequence of the current implementation is that when uncompute is called, the exact same dirty register
will be used. This is technically correct and permissible, but absolutely not necessary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
select
|
Qubrick
|
Select unitary instance. |
required |
swap_up
|
Qubrick
|
SwapUp unitary instance. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute data lookup (QROM) circuit with dirty auxiliary qubits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Index register. |
required |
b
|
int
|
Number of bits to represent item in list. |
required |
data
|
list
|
List of data to load. |
required |
lambda_val
|
int
|
Power-of-two knob to trade off between gates
and qubits. If |
None
|
ctrl
|
Optional[Qubits, int]
|
Qreg to control on. Defaults to 0. |
0
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the compute. |
{}
|
DataLookupDirtyOptimized ¶
Bases: Qubrick
Optimized data lookup (QROM) oracle using dirty auxiliary qubits.
Introduced in Fig. 4 from "Qubitization of Arbitrary Basis Quantum Chemistry Leveraging Sparsity and Low Rank Factorization" (arXiv:1902.02134 ⧉).
Note
\(\text{SWAP}\) and \(\text{SWAP}^\dagger\) are switched in the code below from the drawing in Fig. 4 because \(\text{SWAP}\) and \(\text{SWAP}^\dagger\) in PsiQDK Algorithms are defined in the usual way as swapping the lth register up to the 0th, NOT the other way around.
This routine makes use of dirty, borrowable qubits. The auxiliary qubits in question can be
any qubits on the entirety of the QPU so long as they are not the qubits acted on by
the routine itself. By "borrowable", we mean that after compute is called, the dirty
auxiliary qubits are returned to their initial state; we do not need to wait until uncomputation
for these qubits to be returned to their initial state.
The current implementation makes use of _dirty_qubits to find borrowable qubits; this will
likely change in the future once a dirty auxiliary qubits management scheme is formally implemented in Workbench.
A consequence of the current implementation is that when uncompute is called, the exact same dirty register
will be used. This is technically correct and permissible, but absolutely not necessary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
select
|
Qubrick
|
Select unitary instance. |
required |
swap_up
|
Qubrick
|
SwapUp unitary instance. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute data lookup (QROM) circuit with dirty auxiliary qubits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Index register. |
required |
b
|
int
|
Number of bits to represent item in list. |
required |
data
|
list
|
List of data to load. |
required |
lambda_val
|
int
|
Power-of-two knob to trade off between gates
and qubits. If |
None
|
ctrl
|
Optional[Qubits, int]
|
Qreg to control on. Defaults to 0. |
0
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
MultiplexedSparseDataLookup ¶
Bases: Qubrick
Multiplexed data lookup oracle in Fig. 43 of "Quantum computing enhanced computational catalysis" (arXiv:2007.14460 ⧉).
The goal is to do a "multiplex of multiplexors", that is a quantum for loop over values \(k\) that index a second, inner for loop over \(k-\)dependent values \(j_k\), with the goal being to apply a series of bitstrings \(x_{j,k}\). This can be done efficiently by using a smaller QROM circuit (that also needs to be uncomputed), an adder and a larger "inner" QROM that actually outputs the values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inner_qrom
|
Qubrick
|
Qubrick to implement the data loading over the flattened list of nested elements. |
required |
outer_qrom
|
Qubrick
|
Qubrick to load the offsets for each set of nested data. |
required |
adder
|
Qubrick
|
Qubrick to add the offsets to contiguize the indices. Defaults to |
None
|
**kwargs
|
dict[str, Any]
|
Other keyword arguments to pass to the constructor. |
{}
|
compute ¶
compute(index_1, index_2, bits_of_precision, data, inner_lambda_val=None, outer_lambda_val=None) -> None
Compute the multiplexed data lookup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_1
|
Qubits
|
Register for the outer loop in the multiplexed QROM. |
required |
index_2
|
Qubits
|
Register for the inner loop in the multiplexed QROM. |
required |
bits_of_precision
|
int
|
Number of bits of precision for the inner QROM (the number of bits for the outer QROM is inferred). |
required |
data
|
List[List[int]]
|
Nested list of data values to load; the first dimension corresponds to the outer QROM indices and the second to the inner QROM indices. |
required |
inner_lambda_val
|
int
|
Power-of-two knob to trade off between gates and qubits. Defaults to |
None
|
outer_lambda_val
|
int
|
Power-of-two knob to trade off between gates and qubits. Defaults to |
None
|
UnaryQROM ¶
Bases: Qubrick
A unary-encoded data-loader.
This class provides a unary QROM (Quantum Read-Only Memory) data loader, which can be used to encode data into quantum registers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**kwargs
|
dict[str, Any]
|
Additional keyword arguments passed to the |
{}
|
compute ¶
compute(index_reg: Qubits, b_of_p: int, data: list, ctrl: int | Qubits = 0, *, clean: Qubits | None = None)
This method loads the given data into the quantum register using unary encoding.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
The index register, encoded in unary. |
required |
b_of_p
|
int
|
The number of bits of precision per item to be loaded. |
required |
data
|
list
|
A list of integers representing the data to be loaded. |
required |
ctrl
|
int | Qubits
|
A control register for conditional loading.
Defaults to |
0
|
clean
|
Qubits | None
|
Qubits encoding the output data. If left as |
None
|