algorithms
algorithms ¶
CondCleanBuild ¶
Bases: Qubrick
General function for composing the conditionally clean architecture over a register. Used to construct arithmetic circuits and unary iteration circuit in "Rise of conditionally clean ancillae for efficient quantum circuit constructions" (arxiv:2407.17966 ⧉).
Note
This qubrick is uncomputed progressively in the arithmetic qubricks (with payload operations in between) such that a full uncompute is never required. never_uncompute is defaulted to True to avoid over-flushing of the op stream during this iterative process.
compute ¶
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
val_reg
|
Qubits
|
regsiter acting as conditionally clean ancilla. |
required |
avail_anc
|
Qubits
|
option to provide log(n) clean* ancilla required for conditionally clean architecture. |
None
|
bit
|
int
|
bit position to begin adding / removing conditions from -- used extensively in CondCleanSelect to minimise uncomputation / recomputation steps |
None
|
CondCleanIncrementer ¶
Bases: Qubrick
This is a way to increment the value stored in a register within the conditionally clean structre presented in "Rise of conditionally clean ancillae for efficient quantum circuit constructions" (arxiv:2407.17966 ⧉).
This Qubrick works by first constructing the all ON condition on the register, except for the final qubit (most significant bit). It then applies an X gate to the MSB conditioned on this state. It then sequentially removes this bit as a condition from the structure and applies an X gate to the qubit storing the next highest bit conditioned on all but that bit being in the ON state.
compute ¶
Steps backwards through the registers (from most to least significant bit), applying X gates to the qubit registers to implement an increment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
val_reg
|
Qubits
|
Qubit register acting as indices. |
required |
avail_anc
|
Qubits | None
|
Option to provide log*(n) clean auxiliary qubits. |
None
|
ctrl
|
Qubits | int | None
|
Control register to apply payload gates. |
None
|
CondCleanLessThanConst ¶
Bases: Qubrick
Quantum-classical comparator using conditionally clean construction. Taken from "Rise of conditionally clean ancillae for efficient quantum circuit constructions" (arxiv:2407.17966 ⧉) (Fig.8) with the following optimisations:
- Gate savings during equality testing layer: only do an X gate if classical bit is zero for idx > 0.
- If after some idx all bits of constant are zero, we can exit early, as the flag qubit already stores answer.
compute ¶
CondCleanSelect ¶
Bases: Qubrick
This is a way to perform tree transversal within the conditionally clean structre presented in "Rise of conditionally clean ancillae for efficient quantum circuit constructions" (arxiv:2407.17966 ⧉). The idea of utilising this for multiplexing is presented in Figure 9.
This Qubrick works by first constructing the all zero condition and applies the first index of the data.
Then it sequentially moves through the indices by finding the MSB difference,
undoing the structure to this point, and then redoing with the new condition utiliing
the partial_compute() function.
Notes
This should be called with the filter >>toffoli-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.
Hardcoding requires a bit 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: QUInt, target_reg: Qubits, data: list, avail_anc: Qubits = None, grey: bool = True, skip_zeros: bool = True)
Looks through indices, updating the gate conditions and applying the data item.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
QUInt
|
Qubit register acting as indicies. |
required |
target_reg
|
Qubits
|
Register to load data items to. |
required |
data
|
list
|
List of data values to load based on index. |
required |
avail_anc
|
Qubits
|
Option to provide log*(n) clean auxiliary qubits. |
None
|
grey
|
bool
|
Option to use grey counting. |
True
|
skip_zeros
|
bool
|
Option to not write any data element equal to 0. |
True
|
AddBase ¶
AddBase(add_engine=gidney_add_engine, expand_dest_qreg: bool = False, release_ancillae: bool = True, **kwargs)
Bases: Qubrick
Basic boilerplate for adder.
check_overflow ¶
compute ¶
compute(lhs: QType, rhs: QType, ctrl: Qubits | None = None, *, carry_in: bool = None, subtract_condition: bool = False, alloc_result: bool = False, release_ancillae: bool = None, condition: bool = None)
This computes (lhs += rhs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
Qubits
|
Left-hand operand and destination |
required |
rhs
|
Qubits or int
|
Right-hand operand |
required |
ctrl
|
Qubits
|
Quantum condition |
None
|
subtract_condition
|
Qubits or bool
|
If True (classically or quantumly), subtract instead of adding |
False
|
alloc_result
|
bool
|
If True, compute into a new register |
False
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
None
|
carry_in
|
Qubits or int or None
|
Additional value to add, if any |
None
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
ConditionallyCleanAdd ¶
Bases: AddBase
Wrapper for Conditionally Clean Add.
compute ¶
compute(lhs: QType, rhs: QType, ctrl: Qubits | None = None, *, carry_in: bool = None, subtract_condition: bool = False, alloc_result: bool = False, release_ancillae: bool = None, condition: bool = None)
This computes (lhs += rhs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
Qubits
|
Left-hand operand and destination |
required |
rhs
|
Qubits or int
|
Right-hand operand |
required |
ctrl
|
Qubits
|
Quantum condition |
None
|
subtract_condition
|
Qubits or bool
|
If True (classically or quantumly), subtract instead of adding |
False
|
alloc_result
|
bool
|
If True, compute into a new register |
False
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
None
|
carry_in
|
Qubits or int or None
|
Additional value to add, if any |
None
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
CuccaroAdd ¶
Bases: AddBase
Wrapper for Cuccaro Add.
compute ¶
compute(lhs: QType, rhs: QType, ctrl: Qubits | None = None, *, carry_in: bool = None, subtract_condition: bool = False, alloc_result: bool = False, release_ancillae: bool = None, condition: bool = None)
This computes (lhs += rhs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
Qubits
|
Left-hand operand and destination |
required |
rhs
|
Qubits or int
|
Right-hand operand |
required |
ctrl
|
Qubits
|
Quantum condition |
None
|
subtract_condition
|
Qubits or bool
|
If True (classically or quantumly), subtract instead of adding |
False
|
alloc_result
|
bool
|
If True, compute into a new register |
False
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
None
|
carry_in
|
Qubits or int or None
|
Additional value to add, if any |
None
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
CuccaroDepthOptimisedAdd ¶
Bases: AddBase
Wrapper for Cuccaro Depth Optimised Add.
compute ¶
compute(lhs: QType, rhs: QType, ctrl: Qubits | None = None, *, carry_in: bool = None, subtract_condition: bool = False, alloc_result: bool = False, release_ancillae: bool = None, condition: bool = None)
This computes (lhs += rhs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
Qubits
|
Left-hand operand and destination |
required |
rhs
|
Qubits or int
|
Right-hand operand |
required |
ctrl
|
Qubits
|
Quantum condition |
None
|
subtract_condition
|
Qubits or bool
|
If True (classically or quantumly), subtract instead of adding |
False
|
alloc_result
|
bool
|
If True, compute into a new register |
False
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
None
|
carry_in
|
Qubits or int or None
|
Additional value to add, if any |
None
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
CuccaroMultiplyAdd ¶
Bases: MultiplyAdd
Wrapper for Cuccaro Multiply-Add.
compute ¶
compute(dst, lhs, rhs, ctrl=None, release_ancillae: bool = True, condition=None, subtract_condition: bool = False)
This computes dst + (lhs * rhs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dst
|
Qubits or None
|
Destination to add into. If None, allocate a new register |
required |
lhs
|
Qubits
|
Left-hand multiply operand |
required |
rhs
|
Qubits
|
Right-hand multiply operand |
required |
ctrl
|
Qubits
|
Quantum control |
None
|
subtract_condition
|
Qubits or bool
|
If True (classically or quantumly), subtract instead of adding |
False
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
True
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
GidneyAdd ¶
Bases: AddBase
Wrapper for Gidney Add.
compute ¶
compute(lhs: QType, rhs: QType, ctrl: Qubits | None = None, *, carry_in: bool = None, subtract_condition: bool = False, alloc_result: bool = False, release_ancillae: bool = None, condition: bool = None)
This computes (lhs += rhs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
Qubits
|
Left-hand operand and destination |
required |
rhs
|
Qubits or int
|
Right-hand operand |
required |
ctrl
|
Qubits
|
Quantum condition |
None
|
subtract_condition
|
Qubits or bool
|
If True (classically or quantumly), subtract instead of adding |
False
|
alloc_result
|
bool
|
If True, compute into a new register |
False
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
None
|
carry_in
|
Qubits or int or None
|
Additional value to add, if any |
None
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
GidneyMultiplyAdd ¶
Bases: MultiplyAdd
Wrapper for Gidney Multiply-Add.
compute ¶
compute(dst, lhs, rhs, ctrl=None, release_ancillae: bool = True, condition=None, subtract_condition: bool = False)
This computes dst + (lhs * rhs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dst
|
Qubits or None
|
Destination to add into. If None, allocate a new register |
required |
lhs
|
Qubits
|
Left-hand multiply operand |
required |
rhs
|
Qubits
|
Right-hand multiply operand |
required |
ctrl
|
Qubits
|
Quantum control |
None
|
subtract_condition
|
Qubits or bool
|
If True (classically or quantumly), subtract instead of adding |
False
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
True
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
GidneySquare ¶
Bases: Square
Wrapper for Gidney Square.
compute ¶
compute(lhs, ctrl=None, dst=None, alloc_result=None, add_to_dest=None, release_ancillae: bool = True, condition=None) -> None
This computes (lhs * lhs) into a new register.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
Qubits
|
Left-hand operand and destination |
required |
ctrl
|
Qubits
|
Quantum ctrl |
None
|
dst
|
Qubits or None
|
If provided, ADD result into this reg |
None
|
alloc_result
|
None
|
Deprecated and will be removed in WB 5.0.0. To allocate a new result, pass None as dst. |
None
|
add_to_dest
|
None
|
If False or dst=None, just compute square assuming dst is zero. Otherwise, add to dst |
None
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
True
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
MultiplyAdd ¶
MultiplyAdd(add_engine=gidney_add_engine, mul_engine=naive_mul_engine, allow_negative_input=None, **kwargs)
Bases: Qubrick
Basic Gidney Multiply-Add.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
allow_negative_input
|
bool or None
|
Set to allow negative input values. If None, decide based on input params. |
None
|
compute ¶
compute(dst, lhs, rhs, ctrl=None, release_ancillae: bool = True, condition=None, subtract_condition: bool = False)
This computes dst + (lhs * rhs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dst
|
Qubits or None
|
Destination to add into. If None, allocate a new register |
required |
lhs
|
Qubits
|
Left-hand multiply operand |
required |
rhs
|
Qubits
|
Right-hand multiply operand |
required |
ctrl
|
Qubits
|
Quantum control |
None
|
subtract_condition
|
Qubits or bool
|
If True (classically or quantumly), subtract instead of adding |
False
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
True
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
NaiveAdd ¶
Bases: AddBase
Wrapper for Naive Add.
compute ¶
compute(lhs: QType, rhs: QType, ctrl: Qubits | None = None, *, carry_in: bool = None, subtract_condition: bool = False, alloc_result: bool = False, release_ancillae: bool = None, condition: bool = None)
This computes (lhs += rhs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
Qubits
|
Left-hand operand and destination |
required |
rhs
|
Qubits or int
|
Right-hand operand |
required |
ctrl
|
Qubits
|
Quantum condition |
None
|
subtract_condition
|
Qubits or bool
|
If True (classically or quantumly), subtract instead of adding |
False
|
alloc_result
|
bool
|
If True, compute into a new register |
False
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
None
|
carry_in
|
Qubits or int or None
|
Additional value to add, if any |
None
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
NaiveMultiplyAdd ¶
Bases: MultiplyAdd
Wrapper for Naive Multiply-Add.
compute ¶
compute(dst, lhs, rhs, ctrl=None, release_ancillae: bool = True, condition=None, subtract_condition: bool = False)
This computes dst + (lhs * rhs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dst
|
Qubits or None
|
Destination to add into. If None, allocate a new register |
required |
lhs
|
Qubits
|
Left-hand multiply operand |
required |
rhs
|
Qubits
|
Right-hand multiply operand |
required |
ctrl
|
Qubits
|
Quantum control |
None
|
subtract_condition
|
Qubits or bool
|
If True (classically or quantumly), subtract instead of adding |
False
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
True
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
NaiveSquare ¶
Bases: Square
Wrapper for Naive Square.
compute ¶
compute(lhs, ctrl=None, dst=None, alloc_result=None, add_to_dest=None, release_ancillae: bool = True, condition=None) -> None
This computes (lhs * lhs) into a new register.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
Qubits
|
Left-hand operand and destination |
required |
ctrl
|
Qubits
|
Quantum ctrl |
None
|
dst
|
Qubits or None
|
If provided, ADD result into this reg |
None
|
alloc_result
|
None
|
Deprecated and will be removed in WB 5.0.0. To allocate a new result, pass None as dst. |
None
|
add_to_dest
|
None
|
If False or dst=None, just compute square assuming dst is zero. Otherwise, add to dst |
None
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
True
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
OptimizedGidneyMultiplyAdd ¶
Bases: MultiplyAdd
Wrapper for Gidney Multiply-Add.
compute ¶
compute(dst, lhs, rhs, ctrl=None, release_ancillae: bool = True, condition=None, subtract_condition: bool = False)
This computes dst + (lhs * rhs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dst
|
Qubits or None
|
Destination to add into. If None, allocate a new register |
required |
lhs
|
Qubits
|
Left-hand multiply operand |
required |
rhs
|
Qubits
|
Right-hand multiply operand |
required |
ctrl
|
Qubits
|
Quantum control |
None
|
subtract_condition
|
Qubits or bool
|
If True (classically or quantumly), subtract instead of adding |
False
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
True
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
OptimizedNaiveMultiplyAdd ¶
Bases: MultiplyAdd
Wrapper for Naive Multiply-Add.
compute ¶
compute(dst, lhs, rhs, ctrl=None, release_ancillae: bool = True, condition=None, subtract_condition: bool = False)
This computes dst + (lhs * rhs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dst
|
Qubits or None
|
Destination to add into. If None, allocate a new register |
required |
lhs
|
Qubits
|
Left-hand multiply operand |
required |
rhs
|
Qubits
|
Right-hand multiply operand |
required |
ctrl
|
Qubits
|
Quantum control |
None
|
subtract_condition
|
Qubits or bool
|
If True (classically or quantumly), subtract instead of adding |
False
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
True
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
Square ¶
Square(add_engine=gidney_add_engine, square_engine=square_engine, allow_negative_input=None, **kwargs)
Bases: Qubrick
Basic Gidney square.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
allow_negative_input
|
bool or None
|
Set to allow negative input values. If None, decide based on input params. |
None
|
compute ¶
compute(lhs, ctrl=None, dst=None, alloc_result=None, add_to_dest=None, release_ancillae: bool = True, condition=None) -> None
This computes (lhs * lhs) into a new register.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
Qubits
|
Left-hand operand and destination |
required |
ctrl
|
Qubits
|
Quantum ctrl |
None
|
dst
|
Qubits or None
|
If provided, ADD result into this reg |
None
|
alloc_result
|
None
|
Deprecated and will be removed in WB 5.0.0. To allocate a new result, pass None as dst. |
None
|
add_to_dest
|
None
|
If False or dst=None, just compute square assuming dst is zero. Otherwise, add to dst |
None
|
release_ancillae
|
bool
|
If True, uncompute and release auxiliary qubits. If False, hold auxiliary qubits till uncompute. |
True
|
Notes
release_ancillae allows us to trade off Toffoli cost vs. qubit cost:
- If True, then the ONLY effect remaining after compute() is the desired sum.
- If False, it uses fewer gates but rhs and the auxiliary qubits will be scrambled until uncompute.
ModularAdd ¶
Bases: Qubrick
Modular addition: computes dst = (dst + rhs) % M, where M is a positive integer.
dst and rhs must store values less than M.
While this was implemented independently, it ended up similar to the one described in "How to compute a 256-bit elliptic curve private key with only 50 million Toffoli gates" (https://arxiv.org/abs/2306.08585 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
adder_qubrick
|
Qubrick or None
|
Qubrick to perform internal additions. Defaults to GidneyAdd. |
None
|
compute ¶
Computes dst = (dst + rhs) % M.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dst
|
QUInt
|
Register to add the number to. |
required |
rhs
|
QUInt | int
|
The number to add to |
required |
M
|
int
|
The modulo used for modular addition. |
required |
ctrl
|
Qubits | None
|
Optional quantum control. |
None
|
Note
dst and rhs must store values less than M, i.e., this modular add may wrap
around at most once.
QFTAdd ¶
Bases: Qubrick
Quantum adder implemented using QFT.
Follows the construction in "Quantum arithmetic with the Quantum Fourier Transform" (arxiv:1411.5949 ⧉).
compute ¶
Compute an adder using QFT.
Note
This Qubrick does arithmetic addition, NOT modular addition.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
QUInt
|
Register to be added to. |
required |
rhs
|
(QUInt, int)
|
Amount to add to |
required |
ctrl
|
(Qubits, Optional)
|
Qubits the addition is conditioned on. Defaults to None. |
None
|
QFTIncrement ¶
Bases: Qubrick
Qubrick for incrementing a qubit register using QFT.
Follows the construction in "Quantum arithmetic with the Quantum Fourier Transform" (arxiv:1411.5949 ⧉).
compute ¶
Compute an adder using QFT.
Note
This Qubrick does arithmetic addition, NOT modular addition.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
Qubits
|
Register to be incremented. |
required |
rhs
|
(Qubits, int)
|
Amount to add to |
1
|
ctrl
|
(Qubits, Optional)
|
Qubits the addition is conditioned on. Defaults to None. |
None
|
QFTMultiply ¶
Bases: Qubrick
Quantum multiplier implemented using QFT.
Follows the construction in "Quantum arithmetic with the Quantum Fourier Transform" (arxiv:1411.5949 ⧉).
compute ¶
Compute multiplication using QFT.
Notes
- Only works if
a.num_qubits = b.num_qubits = n - Allocates a fresh output register consisting of \(2n\) qubits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
QUInt
|
First register to be multiplied. |
required |
b
|
QUInt
|
Second register to be multiplied. |
required |
cond
|
(Qubits, int)
|
Qubits the addition is conditioned on. Defaults to 0. |
0
|
QFTSubtract ¶
Bases: Qubrick
Quantum subtractor implemented using QFT.
compute ¶
Compute a subtractor using QFT using reversed phase adder.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_qubits
|
QUInt
|
Register to be added to. |
required |
subtraction_amount
|
(QUInt, int)
|
Amount to subtract from |
required |
cond
|
(Qubits, int)
|
Qubits the subtraction is conditioned on. |
0
|
Reflect ¶
Bases: Qubrick
Qubrick for Reflection (as the reflection about the mean in Grover's algorithm).
compute ¶
compute(target_qreg: Qubits, theta: float | RotationAngle | tuple[int, int] | None = None, ctrl: Qubits | int = 0, basis: str | None = None, error_param: float = 0.0)
Perform a reflection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_qreg
|
Qubits
|
The register to operate on. |
required |
theta
|
float | RotationAngle | tuple or None
|
Phase reflect angle in degrees (or (theta * units.rad) for radians, or (num,denom) for fraction of pi). Defaults to 180 degrees. |
None
|
ctrl
|
Qubits or None
|
Optional quantum control. |
0
|
basis
|
str
|
The reflection basis 'x', 'y', 'z'. Defaults to 'z'. |
None
|
error_param
|
float
|
A parameter to control the precision of the angle. Defaults to 0 (no error). |
0.0
|
Note
For more details, see Built-in Qubricks tutorial.
PhaseGradientSynthesis ¶
PhaseGradientSynthesis(adder=GidneyAdd(), gate_efficient: bool = True, do_label: bool = False, **kwargs: Any)
Bases: Qubrick
Implement a rotation with a specified angle via addition with a phase gradient state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
adder
|
Qubrick
|
Adder Qubrick |
GidneyAdd()
|
gate_efficient
|
bool
|
If True, use gate-efficient version |
True
|
do_label
|
bool
|
If True, puts label on circuit for printing |
False
|
**kwargs
|
Any
|
Additonal Qubrick kwargs |
{}
|
Note
If gate-efficient, write angle to another register and add. Otherwise, controlled-add with classical number (more qubit-efficient).
compute_precision_bits
staticmethod
¶
Compute precision bits of angle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
angle
|
float
|
An angle (in degrees) |
required |
Returns:
| Type | Description |
|---|---|
radix (int
|
Radix for fixed-point number representation of an angle |
Note
This routine will try to determine the smallest radix to represent the value exactly.
compute ¶
compute(angle, bits_of_precision, target_register, qft_state_register, rot_is_rz, ctrl: int = 0) -> None
Compute rotation synthesis circuit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
angle
|
float
|
An angle (in degrees) |
required |
bits_of_precision
|
int
|
Number of bits to truncate the angle |
required |
target_register
|
Qubits
|
Target qubit |
required |
qft_state_register
|
Qubits
|
Catalyst qubits |
required |
rot_is_rz
|
bool
|
If true, op is RZ (vs. phase) |
required |
ctrl
|
Qubits or int
|
Quantum control |
0
|
RossSelingerSynthesis ¶
Bases: Qubrick
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rs_engine
|
str or None
|
Right now the only valid choice is 'pygridsynth' (or None, which defaults to it). |
None
|
compute ¶
compute(target_register, angle, error_param, ctrl: int = 0, rot_is_rz: bool = True, verbose: bool = False) -> None
Implement single-qubit Rz rotation via Ross-Selinger.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_register
|
Qubits
|
Qubit to apply Rz rotation to |
required |
angle
|
float
|
Rotation angle, in degrees |
required |
error_param
|
float
|
Error in approximating unitary, between 0 and 1 |
required |
ctrl
|
Qubit
|
Quantum control |
0
|
rot_is_rz
|
bool
|
Rotation is Rz if True, Phase if False |
True
|
verbose
|
bool
|
If True, prints info on Ross-Selinger |
False
|
Note
Assumes target_register is one qubit and ctrl is at most one qubit.
Rotation ¶
Bases: Qubrick
Implement a rotation gate with a specified angle parameter via one of rotation synthetis engines or simulation.
Experimental. Do not use.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rotation_engine
|
Qubrick or None
|
Qubrick for synthesizing a rotation (Rz and phase gates) |
None
|
qc
|
QPU
|
QPU on which synthesis engine will run |
None
|
phase ¶
rz ¶
rx ¶
ry ¶
ppr ¶
Compute Pauli product rotation (PPR) gate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
angle
|
float
|
An angle (in degrees) |
required |
x_mask
|
int
|
X mask of PPR |
required |
z_mask
|
int
|
Z mask of PPR |
required |
error_param
|
int or float
|
Additive error in some operator norm or number of precision bits |
0
|
compute ¶
Execute rotation engine Qubrick.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
angle
|
float
|
An angle (in degrees) |
required |
target
|
Qubits
|
Target qubit |
required |
error_param
|
int or float
|
additive error in some operator norm or number of precision bits |
required |
rot_is_rz
|
bool
|
If true, op is RZ (vs. phase) |
required |
ctrl
|
Qubits or int
|
Quantum control |
required |
RotationCatalystHandler ¶
Context manager for QPU to know when catalyst qubits can be used.
Note
- This would enable down the line to deal with proper allocation/deallocation of catalyst qubits
- The metadata
validis currently not being used but may be used in the future; currently it serves more as a tag that marks the region of validity
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
qc
|
QPU
|
QPU |
required |
angle
|
float
|
An angle (in degrees) specifying the angle of the catalyst state |
required |
size
|
int
|
Number of qubits to include in the catalyst state |
required |
RotationCatalystStatePrep ¶
Bases: Qubrick
Create a catalyst State with a specified angle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
angle
|
(float, Parameter)
|
An angle (in degrees) specifying the angle of the catalyst state |
required |
size_of_catalyst_state
|
(int, Parameter)
|
Number of qubits to include in the catalyst state |
required |
**kwargs
|
Any
|
Additonal Qubrick kwargs |
{}
|
Notes
- Re: ordering of qubits, consider the 3-qubit example: 0x1: |0> -- H -- Phase(angle/4) -- 0x2: |0> -- H -- Phase(angle/2) -- 0x4: |0> -- H -- Phase(angle) --
- When the angle is truncated to some b bits of precision AND the size of catalyst state is at least b, this is what we refer to as "QFT-state"
Add ¶
CompareEQ ¶
CompareNE ¶
CondInvert ¶
CondXor ¶
QFT ¶
Bases: Qubrick
Qubrick to compute the quantum Fourier transform.
compute ¶
compute(target: Qubits, ctrl: Qubits | int = 0, do_bit_reverse: bool = True, error_param: float = 0)
Compute the QFT.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Qubits
|
The register to perform QFT on. |
required |
ctrl
|
Qubits or None
|
Optional quantum control. |
0
|
do_bit_reverse
|
bool
|
Optionally enable/disable for trailing bit reversal. |
True
|
error_param
|
float
|
Optional error parameter for all rotations. |
0
|
Note
error_param sets the precision of each angle in the QFT (not the overall error).
Sqrt ¶
Bases: Qubrick
Qubrick for square root.
This is implemented starting from "T-count and Qubit Optimized Quantum Circuit Design of the Non-Restoring Square Root Algorithm" (arxiv:1712.08254 ⧉) but with multiple fixes and optimizations:
- Qubit highwater and Toffoli count are significantly reduced from the original paper.
- The original paper doesn't work when the high 2 input qubits are 1, but this one does.
- The original paper requires n to be even and >= 6, this one has no restrictions (for tiny inputs it auto-pads them to 6).
compute ¶
Compute square root.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_qreg
|
Qubits or QUInt
|
Input register for square root operation |
required |
Note
For more details, see Built-in Qubricks tutorial.
AliasSampling ¶
Bases: Qubrick
Qubrick for implementing alias sampling.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
qrom
|
Qubrick
|
Data lookup instance. |
required |
usp
|
Qubrick
|
Uniform state preparation instance. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute_num_states
staticmethod
¶
Helper to compute number of states to prepare in alias sampling (works for symbolics & numerics).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_list
|
list or SymbolicArray
|
List of coefficients to prepare. |
required |
Returns:
| Type | Description |
|---|---|
tuple
|
Number of states to prepare, and value to pad combined list by. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the inputs are not the correct type for either numerics or symbolics. |
compute ¶
State preparation by alias sampling.
Note
Uses the circuit in Fig. 11 of "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prep_reg
|
Qubits or SymbolicQubits
|
Register to prepare coefficients onto. |
required |
input_list
|
list or SymbolicArray
|
List of coefficients to prepare. |
required |
bit_precision
|
int or Parameter
|
Number of bits to represent each coefficient. |
required |
lambda_val
|
int or Parameter
|
Power-of-two knob to trade off between gates
and qubits. If |
None
|
ctrl
|
Qubits, SymbolicQubits, or int
|
Control register. Defaults to no control, i.e. |
0
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the compute. |
{}
|
AmplitudeAmplification ¶
AmplitudeAmplification(init_refl: Qubrick, good_refl: Qubrick, fixed_point: bool = False, eps: float = 0.001, use_radians: bool = False, **kwargs)
Bases: Qubrick
Performs amplitude amplification to boost the amplitude of a desired outcome.
Amplitude amplification takes two reflections: a "good" reflection about a target state \(|\psi_{\text{good}}\rangle\) and a "starting" reflection about the state \(|\psi_{0}\rangle\) that forms the starting point of the routine. If the starting state \(|\psi_0\rangle\) is prepared with some (potentially low) overlap with the target state \(|\psi_{\text{good}}\rangle\), repeatedly applying these two reflections \(\mathcal{O}(1/\sqrt{p})\) times should result in a final state which has \(\Omega(1)\) overlap with the target state.
These reflections can't be made blindly: if you pick a number of iterations that is too small, you "undercook" the
state, and if you pick a number that is too high, you "overcook" the state, leading to low fidelities in both cases.
The optimal number of iterations depends on the initial success probability p_succ, which you may or may not know
a priori. AmpAmp requires p_succ to be passed as an argument in order to calculate the number of rounds needed and provides
provision for two scenarios:
- If you know
p_succexactly a priori, you can realize the good state deterministically following the procedure in "Quantum Amplitude Amplification and Estimation" (arXiv:quant-ph/0005055 ⧉). - If you don't know
p_succ, we can use fixed point amplitude amplification (the PsiQDK Algorithms implementation follows "Fixed-point quantum search with an optimal number of queries" (arXiv:1409.3305 ⧉) along with a lower bound on the success probability asp_succ. Unlike vanilla AA, fixed point AA is guaranteed to succeed for any number of iterations greater than some threshold (calculated from the lower bound on the success probability). Thus, while it may use more resources than necessary, it is useful for when we can't determinep_succexactly.
Note
The reflections that are passed to this Qubrick are entirely general - they may have additional parameters
that need to be passed to them. These parameters can be passed through the kwargs as if the AmpAmp
Qubrick has those parameters. For example, if you have a block encoding unitary which takes be_ancilla_reg as
an argument, you can do
AmpAmp(init_refl, good_refl).compute(sys_reg, p_succ, be_ancilla_reg=be_ancilla_reg).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
init_refl
|
Qubrick
|
Reflection about the initial state. |
required |
good_refl
|
Qubrick
|
Reflection about the good (target) state. |
required |
fixed_point
|
bool
|
Whether to use fixed point amplitude amplification rather than vanilla amplitude amplification.
Defaults to |
False
|
eps
|
float
|
Desired error \(\epsilon\) such that \(|\langle\psi_{f}|\psi_{targ}\rangle|^2 \geq 1 - \epsilon\).
Needed to calculate the fixed point rotation angles; not necessary if you use vanilla amplitude amplification. Defaults to
|
0.001
|
use_radians
|
bool
|
(Deprecated) True if angles in Radians. |
False
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute the amplitude amplification.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sys_reg
|
Qubits
|
Main register the computation is performed on. |
required |
p_succ
|
float
|
The initial probability of obtaining the "good" state. If |
required |
ctrl
|
int | Qubits
|
Register the amplitude amplification is controlled on. Defaults to 0. |
0
|
**kwargs
|
dict[str, Any]
|
Optional arguments that may be passed on to the reflection Qubricks. |
{}
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
be_ancilla_reg |
Qubrick
|
Block encoding register. |
data |
PauliSum or List[int]
|
Data for \(\text{SELECT}\) Qubricks. |
AmplitudeAmplifiedQubrick ¶
AmplitudeAmplifiedQubrick(base_qubrick: Qubrick, init_refl: Qubrick, good_refl: Qubrick, fixed_point: bool = False, eps: float = 0.001, use_radians: bool = False, **kwargs)
Bases: Qubrick
Performs amplitude amplification on the input Qubrick to provide an "amplified" Qubrick.
This Qubrick is intended to be used as a wrapper around a base Qubrick along with Amplitude Amplification (the AmpAmp Qubrick) in order to produce an amplitude amplified version of the base Qubrick.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_qubrick
|
Qubrick
|
The base Qubrick to be amplified. |
required |
init_refl
|
Qubrick
|
Reflection about the initial state. |
required |
good_refl
|
Qubrick
|
Reflection about the good (target) state. |
required |
fixed_point
|
bool
|
Whether to use fixed point amplitude amplification rather than vanilla amplitude amplification.
Defaults to |
False
|
eps
|
float
|
Desired error \(\epsilon\) such that \(|\langle\psi_{f}|\psi_{targ}\rangle|^2 \geq 1 - \epsilon\).
Needed to calculate the fixed point rotation angles, not necessary for vanilla amp amp. Defaults to
|
0.001
|
use_radians
|
bool
|
(Deprecated) True if angles in Radians. |
False
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
amp_amp
instance-attribute
¶
amp_amp: Incomplete = AmpAmp(init_refl, good_refl, fixed_point=fixed_point, eps=eps, use_radians=use_radians)
compute ¶
Compute the base Qubrick along with amplitude amplification.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sys_reg
|
Qubits
|
Main register the computation is performed on. |
required |
p_succ
|
float
|
The initial probability of obtaining the "good" state. If |
required |
ctrl
|
int | Qubits
|
Register the amplitude amplification is controlled on. Defaults to 0. |
0
|
**kwargs
|
dict[str, Any]
|
Optional arguments that may be passed on to the AmpAmp Qubrick, reflection Qubricks, or the base Qubrick. |
{}
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
be_ancilla_reg |
Qubrick
|
Block encoding register. |
data |
PauliSum or List[int]
|
Data for \(\text{SELECT}\) Qubricks. |
GoodReflectionBlockEncoding ¶
Bases: Qubrick
Reflection about a block encoded good state (i.e., all block encoding auxiliary qubits in \(\ket{0}\)).
Implements the reflection
Note
See references "Quantum Amplitude Amplification and Estimation" (arXiv:quant-ph/0005055 ⧉) and "Fixed-point quantum search with an optimal number of queries" (arXiv:1409.3305 ⧉) for details.
compute ¶
Compute the reflection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sys_reg
|
Qubits
|
Qubits register defining the system. Included to maintain compatibility with other Qubricks. |
required |
ancillae
|
Qubits
|
Auxiliary qubits used to block encode the matrix. |
required |
angle
|
float
|
Angle about which the generalized reflection is performed. |
180
|
ctrl
|
int | Qubits
|
Qubits to control the reflection on. Defaults to 0. |
0
|
**kwargs
|
dict[str, Any]
|
Additional keyword arguments included to maintain compatibility with other reflections. |
{}
|
GoodReflectionGrover ¶
Bases: Qubrick
Qubrick for reflecting about a good state in Grover.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
good_state
|
str
|
Binary representation of the good state as the basis state, e.g. '101'. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute the reflection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sys_reg
|
Qubits
|
Register on which the state is prepared. |
required |
angle
|
float
|
Angle about which the generalized reflection is performed, in degrees. |
required |
ctrl
|
int | Qubits
|
Qubits to control the reflection on. Defaults to 0. |
0
|
**kwargs
|
dict[str, Any]
|
Additional keyword arguments included to maintain compatibility with other reflections. |
{}
|
GroverDiffuser ¶
Bases: Qubrick
Qubrick for Grover diffuser (reflection about the mean).
compute ¶
Compute the reflection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sys_reg
|
Qubits
|
Register on which the state is prepared. |
required |
angle
|
float
|
Angle about which the generalized reflection is performed, in degrees. |
180
|
ctrl
|
int | Qubits
|
Qubits to control the reflection on. Defaults to 0. |
0
|
**kwargs
|
dict[str, Any]
|
Additional keyword arguments included to maintain compatibility with other reflections. |
{}
|
InitReflectionBlockEncoding ¶
Bases: Qubrick
Reflection about the initial state given a unitary that prepares that state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
unitary
|
Qubrick
|
Qubrick implementing the unitary to reflect about. |
required |
**kwargs
|
dict[str, Any]
|
Other keyword arguments to pass to the Qubrick constructor. |
{}
|
compute ¶
compute(sys_reg: Qubits, angle: float = 180, ancillae: int | Qubits = 0, ctrl: int | Qubits = 0, **kwargs)
Compute the reflection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sys_reg
|
Qubits
|
Register on which the state is prepared. |
required |
angle
|
float
|
Angle about which the generalized reflection is performed, in degrees. |
180
|
ancillae
|
int | Qubits
|
Ancillae used to facillitate the implementation of the state. Defaults to 0. |
0
|
ctrl
|
int | Qubits
|
Qubits to control the reflection on. Defaults to 0. |
0
|
**kwargs
|
dict[str, Any]
|
Additional keyword arguments included to maintain compatibility with other reflections. |
{}
|
InitReflectionFromUnitary ¶
Bases: Qubrick
Reflection about the initial state given a unitary that prepares that state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
unitary
|
Qubrick
|
Qubrick implementing the unitary that prepares the state to reflect about. |
required |
**kwargs
|
dict[str, Any]
|
Other keyword arguments to pass to the Qubrick constructor. |
{}
|
compute ¶
Compute the reflection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sys_reg
|
Qubits
|
Register on which the state is prepared. |
required |
angle
|
float
|
Angle about which the generalized reflection is performed, in degrees. |
180
|
ctrl
|
int | Qubits
|
Qubits to control the reflection on. Defaults to 0. |
0
|
**kwargs
|
dict[str, Any]
|
Additional keyword arguments included to maintain compatibility with other reflections. |
{}
|
Antisymmetrizer ¶
Bases: Qubrick
Qubrick to antisymmetrize a register of qubits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prep_qbk
|
Qubrick
|
A state preparation Qubrick. |
required |
prob_knob
|
(Optional, int)
|
A value to use which determines the number of qubits to use per seed register, which influences the probability of needing to restart. Defaults to None, in which case a default value which ensures >= 1/2 probability of success is used. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Circuit for preparation of an antisymmetrized state.
The antisymmetrization procedure works as follows:
- We prepare an auxiliary "seed" register in an equal superposition state.
- We employ a sorting network on the seed register, keeping a record of all permutations made during the sort on another "record" register.
- The seed register is measured in order to post-select on the collision-free subspace. If we observe a collision, we go back to step 1. If not, continue.
- We apply Pauli Zs on each record qubit.
- We use the record to reverse the sorting operations on the input system register, resulting in an equal superpotision of all permutations of the input state.
- Because we applied Pauli Zs on each record qubit prior to the sort reversal, we also phase each permutation state according to its parity.
The above prepares the desired antisymmetrized state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system_reg
|
Qubits
|
Register to prepare antisymmetrized state on. |
required |
ctrl
|
(int, Qubits)
|
Control register for the routine. Defaults to 0. |
0
|
PowerOfTwoBatchedHammingWeightPhasing ¶
PowerOfTwoBatchedHammingWeightPhasing(hamming_weight_qubrick: Qubrick | None = None, n_hwp_batches: int = 1, rot_is_rz: bool = True, use_black_box: bool = False, **kwargs)
Bases: Qubrick
Implements Hamming weight phasing by splitting the target register into batches.
This Qubrick divides a large rotation tower into smaller batches, where the number of batches is a power of two. Each batch is processed with a smaller Hamming weight phasing circuit. This approach can significantly reduce the number of qubits and catalyst rotation requirements for large registers.
This is particularly useful for applications like Fermi-Hubbard simulation where the number of parallel Rz rotations is either L²/2 or L², where L is the lattice size.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hamming_weight_qubrick
|
Qubrick | None
|
Qubrick for computing the Hamming weight for
the Hamming weight phasing operation. If None, a default method using
|
None
|
n_hwp_batches
|
int
|
Number of batches to split the rotations into. Must be a power of 2. Larger values reduce resource costs but may increase circuit depth. |
1
|
rot_is_rz
|
bool
|
Whether to use RZ rotations (True) or phase rotations (False). |
True
|
use_black_box
|
bool
|
Uses black box AV counts if set to True. Default is False. |
False
|
**kwargs
|
dict[str, Any]
|
Additional arguments to pass to the Qubrick constructor. |
{}
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If n_hwp_batches is not a power of 2. |
hamming_weight_qubrick
property
¶
Returns the Hamming weight qubrick used for computation.
Returns:
| Type | Description |
|---|---|
Qubrick
|
The Hamming weight calculation Qubrick. |
compute ¶
Computes the batched Hamming weight phasing operation.
This method splits the target register into batches, then applies a Hamming weight phasing operation to each batch separately. This approach can significantly reduce Toffoli gate counts and catalyst rotation requirements for large registers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rz_rotation_angle
|
float
|
Rotation angle (in degrees) for the phase operations. |
required |
target_register
|
Qubits
|
Register on which to apply the rotations. |
required |
ctrl
|
Qubits | int
|
Controls for the operation. Can be an integer bitmask or a Qubits register. Default is 0 (uncontrolled). |
0
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the number of batches is greater than the number of qubits in the target register. |
LCU ¶
Bases: Qubrick
Implements a general block encoding using Linear Combination of Unitaries (LCU).
Constructs the block encoding as \(\text{PREP}-\text{SELECT}-\text{PREP}^\dagger\)
using provided Qubrick implementations of SELECT and PREP.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state_prep
|
StatePreparation
|
A Qubrick implementing a state preparation ( |
required |
select
|
Select
|
A Qubrick implementing a select ( |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
compute(psi: Qubits, be_ancilla_reg: Qubits, data: PauliSum | list[int], ctrl: Qubits | int = 0, **kwargs: dict[str, Any])
Compute the block encoding.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psi
|
Qubits
|
Target state register. |
required |
be_ancilla_reg
|
Qubits
|
Block encoding auxiliary register. |
required |
data
|
PauliSum | list[int]
|
Hamiltonian or bitstring values to be block-encoded. |
required |
ctrl
|
Qubits | int
|
Register to control on. Defaults to |
0
|
**kwargs
|
dict[str, Any]
|
Extra kwargs to maintain compatibility with other Qubricks. |
{}
|
CompressionGadget ¶
Bases: Qubrick
Compression gadget for block-encoding powers.
Given block encoding of \(H_i\), applies a block encoding of product of \(H_i\) according to Fig. 3 from "Time-marching based quantum solvers for time-dependent linear differential equations" (arXiv:2208.06941 ⧉).
Note
The block-encoding is successful in the subspace where counter == 0. The controlled version is such that the controlled unitary is applied accordingly when the block-encoding's ancillae qubits are in the zero state. However, the controlled-qubrick might still have an action in other subspace. This allows to reduce the cost of the implementation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
strategy
|
CompressionGadgetStrategy
|
Block-encoding of the Hamiltonian H. |
required |
adder
|
Qubrick
|
Adder Qubrick. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
strategy
property
¶
Set the strategy property so it can't be modified.
Returns:
| Type | Description |
|---|---|
CompressionGadgetStrategy
|
The Compression gadget strategy. |
compute ¶
Compute CompressionGadget.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system_reg
|
Qubits
|
System qubits to apply to block-encodings. |
required |
be_anc
|
int
|
Block-encoding auxiliary register. |
required |
idx_stop
|
int
|
Final index of the multiplication. |
required |
idx_start
|
int
|
Starting index of the multiplication. |
0
|
counter
|
Qubits
|
Counter register to perform the compression. If None, the register will be allocated at compute. |
None
|
ctrl
|
(Qubits, int)
|
Control register. |
0
|
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
|
DysonSeriesLCU ¶
Bases: Qubrick
A Dyson Series LCU Qubrick with a unary version of the truncation register.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prepare
|
Qubrick
|
Prepare Qubrick for Dyson Series. |
required |
select
|
Qubrick
|
Select Qubrick for Dyson Series. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Apply Dyson Series.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
register
|
CompositeRegister
|
A composite register for Dyson Series. |
required |
data
|
DysonSeriesData
|
Dataclass for the DysonSeries operator parameters. |
required |
ctrl
|
(Qubits, int)
|
A register to control this operation on. Default to |
0
|
DysonSeriesPrepareBinary ¶
Bases: Qubrick
A modified version of the Dyson series expansion as in "Hamiltonian Simulation in the Interaction Picture" (arXiv:1805.00675 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sort
|
Qubrick
|
A Qubrick implementing quantum sort. |
None
|
prepare
|
Qubrick
|
Prepare Qubrick to implement the prepare oracle for |
None
|
usp
|
Qubrick
|
A Qubrick that prepares a uniform state. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Apply the Dyson series prepare operator with binary version of the truncation register.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
register
|
CompositeRegister
|
register for Dyson series indexing (binary). |
required |
data
|
DysonSeriesData
|
Dataclass for the DysonSeries operator parameters. |
required |
ctrl
|
(Qubits, int)
|
A register to control this operation on. Default to |
0
|
Note
The control version is an optimized version when an input register is 0.
If the input register is not 0, the gates will be applied.
DysonSeriesPrepareUnary ¶
Bases: Qubrick
A modified version of the Dyson series expansion as in "Hamiltonian Simulation in the Interaction Picture" (arXiv:1805.00675 ⧉).
Uses the PrepareClockState Qubrick as its subroutine to encode probabilities.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sort
|
Qubrick
|
A Qubrick implementing quantum sort. |
None
|
prepare
|
Qubrick
|
Prepare Qubrick to implement the prepare oracle for |
None
|
usp
|
Qubrick
|
A Qubrick that prepares a uniform state. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
prepare
instance-attribute
¶
compute ¶
Apply the Dyson series prepare operator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
register
|
CompositeRegister
|
A register for Dyson series indexing. |
required |
data
|
DysonSeriesData
|
Dataclass for the DysonSeries operator parameters. |
required |
ctrl
|
(Qubits, int)
|
A register to control this operation on. Default to |
0
|
Note
The control version is an optimized version when the input register is 0.
If the input register is not 0, the gates will be applied.
DysonSeriesSelectBinary ¶
Bases: Qubrick
A modified version of the Dyson series expansion as in "Hamiltonian Simulation in the Interaction Picture" (arXiv:1805.00675 ⧉).
Note
If flagging time collisions, a flag Qubrick is placed before the DysonSeriesSelectBinary
in the binary version.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
strategy_cg
|
class
|
Strategy to apply compression gadget subroutine. |
required |
flag
|
Qubrick
|
A binary version of a flag to mark time collisions in the time-discretization register. Flagging time collisions is optional. |
None
|
adder
|
Qubrick
|
A Qubrick implementing add/subtract operation. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Apply the Dyson series select operator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
register
|
CompositeRegister
|
register (binary) for Dyson series indexing. |
required |
data
|
DysonSeriesData
|
Dataclass for the DysonSeries operator parameters. |
required |
ctrl
|
(Qubits, int)
|
A register to control this operation on. Default to |
0
|
DysonSeriesSelectUnary ¶
Bases: Qubrick
A modified version of the Dyson series expansion as in "Hamiltonian Simulation in the Interaction Picture" (arXiv:1805.00675 ⧉).
Note
If flagging time collisions, a flag Qubrick is placed after the DysonSeriesSelectUnary
in the unary version.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fast_forward_exp
|
Qubrick
|
A Qubrick implementing the time-evolution of the fast-forwardable part of the Hamiltonian. |
required |
lcu
|
Qubrick
|
A block-encoding subroutine for appliying Hamiltonian to the sustem register. |
required |
flag
|
Qubrick
|
A unary version of a flag to mark time collisions in the time-discretization register. Flagging time collisions is optional. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Apply the Dyson series select operator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
register
|
CompositeRegister
|
register for Dyson series indexing (unary version). |
required |
data
|
DysonSeriesData
|
Dataclass for the DysonSeries operator parameters. |
required |
ctrl
|
(Qubits, int)
|
A register to control this operation on. Default to |
0
|
FlagCollisionsBinary ¶
Bases: Qubrick
A FlagCollisionsBinary Qubrick to reflect (time) collisions.
Implementation of the collision functionality as described in "Optimized quantum algorithms for simulating the Schwinger effect" (arXiv:2508.16831 ⧉).
Note
For the DysonSeriesBinary logic, the flag is to applied before the application of Hamiltonians, in contrast to DysonSeriesUnary logic.
compute ¶
Construct the Qubrick.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
discret_reg
|
Qubits
|
registers to be compared (registers where time collisions may occure). |
required |
trunc_reg
|
Qubits
|
register indicating the value to compare up to. |
required |
ctrl
|
(Qubits, int)
|
a register to control this operation on. Default to |
0
|
Note on convention
The resulting register, flag, stores 1 if at least one collision occured, 0 otherwise.
FlagCollisionsUnary ¶
Bases: Qubrick
A FlagCollisions Qubrick to reflect (time) collisions.
Implementation of the collision functionality as described in "Optimized quantum algorithms for simulating the Schwinger effect" (arXiv:2508.16831 ⧉).
Note
For unary version of the DysonSeries (unary version of the truncation register).
compute ¶
Construct the Qubrick.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
discret_reg
|
Qubits
|
registers to be compared (registers where time collisions may occure). |
required |
trunc_reg
|
Qubits
|
register indicating the value to compare up to. |
required |
ctrl
|
(Qubits, int)
|
a register to control this operation on. Default to |
0
|
Note on convention
The resulting register, flag, stores 1 if at least one collision occured, 0 otherwise.
Rz ¶
RzAdder ¶
Bases: Qubrick
Implementation of Rz rotation using an adder-based approach.
This uses the rotation catalyst state and an adder to implement an Rz rotation on the target register.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
adder
|
Qubrick
|
Qubrick for implementing the addition in PGA. |
None
|
**kwargs
|
dict[str, Any]
|
Extra keyword arguments for the Qubrick constructor. |
{}
|
compute ¶
ComputeHammingWeightBinaryRecursion ¶
Bases: Qubrick
Quantum circuit to compute the Hamming weight of a register that uses roughly O(N/2) auxiliary qubits and O(N) Toffoli.
This Qubrick computes the Hamming weight of a quantum register (coherently) based on the algorithm outlined in this paper: Boyar, Joan, and René Peralta, "The exact multiplicative complexity of the Hamming weight function." This is a truly recursive algorithm that computes the Hamming weight of a register by splitting it into three separate registers: U, V, and M. The third register, M, is of size 1 and is just an arbitrary qubit in the original register. Reigsters U and V are then an even split of qubits in the original register excluding the M qubit. The Hamming weight is then computed as H(U) + H(V) + M, where H(U) and H(V) are the Hamming weights of U and V which are computed by calling the Hamming weight computation function recursively.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
adder
|
Qubrick
|
Adder Qubrick. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
ComputeHammingWeightGroupOfThrees ¶
Bases: Qubrick
Quantum circuit to compute the Hamming weight of a quantum register that uses roughly N auxiliary qubits and O(N) Toffoli gates.
This Qubrick computes the Hamming weight of a quantum register (coherently). This is a recursive algorithm that groups qubits into batches of three and computes the Hamming weight of these qubits. The carry bit in this output is upgraded to the "next level" while the low-bit is tossed back into the current group of qubits. This process is repeated until all low-bits at the current level have been added and we are left with only one bit - this becomes the low bit in our Hamming weight register. The process is then repeated on all of the carry bits that were upgraded to the "next level". This process is repeated until there are no more carry bits that get upgraded. This algorithm is described in "Halving the cost of quantum addition" (arXiv:1709.06648 ⧉).
compute ¶
Compute the Hamming weight.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_register
|
Qubits
|
The target qubit register to compute the Hamming weight of. |
required |
ctrl
|
Qubits or int
|
Control register. |
0
|
Note
- Allocates a quantum register storing the Hamming weight.
- If Qubrick is controlled and the user wants black box cost, then the black box cost will be just naively counted from operations.
ComputeHammingWeightNaive ¶
Bases: Qubrick
Naive/Qubit-efficient circuit to compute the Hamming weight of a quantum register.
This Qubrick computes the Hamming weight of a quantum register (coherently). The structure of this algorithm is to initialize a register of size log(N + 1) for an N-qubit register and then traverse serially through the qubits in the target register and perform controlled adders onto the newly allocated auxiliary register such that the value of the qubit in the target register is added into the value of the Hamming weight register.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
adder
|
Qubrick
|
Adder Qubrick. |
GidneyAdd()
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
HammingWeightPhasing ¶
HammingWeightPhasing(angle, rot_is_rz: bool = False, hamming_weight_qubrick=None, use_catalyst_state: bool = False, catalyst_state_reg=None, use_padding: bool = False, use_black_box: bool = False, **kwargs)
Bases: Qubrick
Implement a stack of rotations of the same angle using Hamming weight phasing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
angle
|
float | RotationAngle
|
An angle specifying the angle of the rotations |
required |
rot_is_rz
|
bool
|
Flag to determine if attempting to perform Rz rotations or phase gates |
False
|
hamming_weight_qubrick
|
Qubrick
|
A Qubrick that computes the Hamming weight of a register. |
None
|
use_catalyst_state
|
bool
|
A flag to determine if the Phasing circuit should be used to implement the growingtower of rotations. |
False
|
catalyst_state_reg
|
Qubits
|
The catalyst state for the PhaseC circuit. |
None
|
use_padding
|
bool
|
A flag to determine if the Hamming weight register should be padded with clean auxiliary qubits so that the size is consistent with the size of the catalyst state. If it is not padded, then a single phase gate needs to be applied during the PhaseC circuit. If it is padded, then the rotations should be completely decomposed via Toffolis when adding onto the catalyst state assuming the catalyst state is large enough to implement the angle passed in exactly. If the catalyst state is not large enough based on the precision of the angle, a rotation is still required. |
False
|
use_black_box
|
bool
|
Uses black box AV counts if set to True. Default is False. |
False
|
**kwargs
|
dict[str, Any]
|
Additonal Qubrick kwargs. |
{}
|
PhasingCircuit ¶
Bases: Qubrick
Implement the phasing circuit.
Notes
- See under section "Additional basis rotations."
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_angle
|
float | RotationAngle
|
An angle specifying the base angle of the growing tower of rotations. |
required |
rot_is_rz
|
bool
|
Flag to determine if attempting to perform Rz rotations or phase gates. |
False
|
use_black_box
|
bool
|
Uses black box AV counts if set to True. Default is False. |
False
|
**kwargs
|
dict[str, Any]
|
Additonal Qubrick kwargs. |
{}
|
base_angle
property
writable
¶
Angle specifying the base angle of the growing tower of rotations.
compute ¶
compute(target_reg: Qubits, catalyst_reg: Qubits, ctrl: Qubits | int = 0, final_qubits: Qubits | int = 0)
Use the phasing circuit to implement a tower of growing rotations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_reg
|
Qubits
|
The state to implement the rotations upon. |
required |
catalyst_reg
|
Qubits
|
The catalyst state to use which is specific to the base angle being implemented. |
required |
ctrl
|
int or Qubits
|
Classical or Quantum control conditions. |
0
|
final_qubits
|
Qubits
|
If passed in, these are the three qubits on which we just perform Z, S, and T directly instead of adding on to the catalyst state. |
0
|
Notes
The implemented circuit applies rotations of base_angle*(2**i) for the i-th qubit of
the target_reg, where i runs from 0 to len(target_reg) - 1.
LKSMultiplexor ¶
Bases: Qubrick
Multiplexor using data-lookup oracles.
The construction is detailed in "Trading T gates for dirty qubits in state preparation and unitary synthesis" (arXiv:1812.00954 ⧉). Circuit described in Appendix D.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
qrom
|
Qubrick
|
Data-loader for loading angles to bits_of_precision-bits of precision. |
required |
gate
|
op
|
Rotation gate type to use in multiplexed rotations. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute circuit for LKS multiplexor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Index register. |
required |
tgt
|
Qubits
|
Register to apply rotations onto. |
required |
angles
|
list or None
|
List of angles to supply to rotations. |
required |
bits_of_precision
|
int
|
Bits of precision for rotations. |
required |
lambda_val
|
int
|
Power-of-two knob to trade off between gates
and qubits. If |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the compute. |
{}
|
Note
We want to apply single-qubit \(\text{RY}\) rotations conditioned on different significant bits. We truncate the exact angle and obtain an integer approximation of it, and so, each angle we apply is \(\frac{2\pi a_k} {2^{k + 1}}\). However, we express \(\text{RY}\) rotations as \(\text{RY}(\theta) = e^{iY \frac{\theta}{2}}\). If you account for this factor of 2 in the denominator, and also convert from radians to degrees \((\frac{180}{\pi})\), you end up using:
LKSStatePrep ¶
Bases: Qubrick
State preparation detailed in "Trading T gates for dirty qubits in state preparation and unitary synthesis" (arXiv:1812.00954 ⧉).
This routine works for real, positive coefficients.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coeffs
|
list or None
|
List of coefficients to load into state. |
required |
mplxr
|
Qubrick
|
Multiplexor to use in state prep. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute circuit for LKS state prep.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
qbits
|
Qubits
|
Qubits to prep state on. |
required |
**mplxr_kwargs
|
dict
|
Dictionary with keyword arguments to pass to the multiplexor. |
{}
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
bits_of_precision |
int
|
Bits of precision for rotations. |
lambda_val |
int
|
Power-of-two knob to trade off between gates
and qubits. If |
MajoranaFermionOperator ¶
Bases: Qubrick
The Majorana Fermion Operator shown in Fig. 9 of "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operator
|
callable
|
A function implementing an operator taking in two arguments: (1) the qubit register
and (2) the control conditions. Typically either the |
required |
multiplexor_cls
|
Qubrick
|
The class for a Qubrick that implements multiplexing. |
required |
**kwargs
|
dict[str, Any]
|
Additional Qubrick kwargs. |
{}
|
compute ¶
Compute the Majorana Fermion Operator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
The qubit register that represents the indices to multiplex over. |
required |
target_reg
|
Qubits
|
The qubit register that the Majorana Fermion Operator gets applied onto. |
required |
ctrl
|
Qubits or int
|
Additional classical or quantum control conditions. Defaults to |
0
|
MultiplexedAliasSampling ¶
Bases: Qubrick
Implements the multiplexed alias sampling subroutine for multiplexed arbitrary state preparation.
The goal of this protocol is to take a list of lists of coefficients (probabilities corresponding to the squares of statevector amplitudes), load these coefficients using QROM, and prepare the state formed as the superposition of the states defined by each list of coefficients. This method is heavily based on the Alias Sampling technique used in quantum computing.
Steps of the Routine
Assuming familiarity with regular alias sampling, the steps are:
-
Superposition preparation:
MultiplexedUSPis used to prepare a superposition of uniform superposition states multiplexed over indices \( i \).- The dimension of the \( i \)th USP state corresponds to the length of the coefficients for the \( i \)th state that we want to prepare.
-
Computing
altandkeepvalues:- We calculate the
altandkeepvalues for each set of coefficients. - The size of the
altregister is buffered to fit the largest value for all states in superposition. - This is managed by bit-shifting the
keepvalues by this maximum value, similar to regular alias sampling.
- We calculate the
-
Multiplexor of multiplexors:
- We load the
altandkeepvalues in superposition using the construction from "Quantum computing enhanced computational catalysis" (arXiv:2007.14460 ⧉).
- We load the
-
Partitioning QROM output:
- The multiplexed QROM output is partitioned into
altandkeepregisters.
- The multiplexed QROM output is partitioned into
-
Creating a coin flip state:
- Hadamards are applied to create a uniform superposition in the coin flip register.
-
Conditional swapping:
- A comparator checks whether
coin_toss_regis less thankeep_reg. - If true, the input
prep_regis swapped withalt_reg.
- A comparator checks whether
Note
- This construction is based on step 3 in "Even more efficient quantum computations of chemistry through tensor hypercontraction" (arxiv:2011.03494 ⧉).
- As implemented, this routine is deterministic. However, in the reference above, it only succeeds conditioned on a success flag.
- The success flag comes from the comparator in
MultiplexedUSP. - Currently, this always succeeds because rotations are directly implemented.
- Once synthesis is introduced, alias sampling will succeed only conditionally based on the USP.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
multiplexed_usp
|
Qubrick
|
A subroutine implementation for multiplexed USP. |
required |
multiplexed_qrom
|
Qubrick
|
A subroutine implementation for multiplexed QROM. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
compute(prep_reg, index, data_reg, data, bit_precision, inner_lambda_val=None, outer_lambda_val=None) -> None
Compute the multiplexed alias sampling.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prep_reg
|
Qubits
|
Register in which we want to prepare our superposition of states. |
required |
index
|
Qubits
|
Register containing the coefficients for the multiplexing loop. |
required |
data_reg
|
Qubits
|
Register with the different |
required |
data
|
List[List[int]]
|
A list of lists of coefficients representing each of the states to be prepared in superposition. |
required |
bit_precision
|
int
|
Number of bits of precision to be used in the alias sampling discretization procedure. |
required |
inner_lambda_val
|
int
|
Power-of-two knob to trade off between gates and qubits for the inner loop in
multiplexed QROM. Defaults to |
None
|
outer_lambda_val
|
int
|
Power-of-two knob to trade off between gates and qubits for the outer loop in
multiplexed QROM. Defaults to |
None
|
Contiguizer ¶
Bases: Qubrick
Given an input register, produce a new register with 1s from the most significant bit down to 0.
This routine comes from "Even more efficient quantum computations of chemistry through tensor hypercontraction" (arxiv:2011.03494 ⧉). See step 3.(a) of the double factorization compilation in Appendix C.
The motivation behind the routine is as follows: in regular USP, we apply Hadamard gates on the input register as
the first step in the routine. The number of Hadamards is determined by the bit-length of the number of states
\(d\), so \(d=10_{10}=1010_2\) would require Hadamards on 4 qubits in the first step of the USP protocol. When
multiplexing, we could in principle have numbers with different bit lengths over which we multiplex, meaning that
we would need different numbers of Hadamard gates. The solution to implement this is to initialize a new register
(copy in this qubrick) and to prepare a state which has 1's on all the bits up to and including the bit-length
of \(d\) (or more precisely, a superposition over such states for all \(d\) over which we are
multiplexing). This register can then be used to apply a sequence of controlled Hadamards such that the appropriate
number of Hadamards are applied for each value of \(d\).
As an example, say we are multiplexing over two values, \(d_1=2\) and \(d_2=10\). 2 has a bit length of 2
and 10 has a bit length of 4, so the contiguizer would realize a superposition \(|0011\rangle + |1111\rangle\).
Notice that for each value \(d_i\), the value loaded into the state is (1 << d_i.bit_length()) - 1.
compute ¶
Compute the contiguizer.
Takes an target_reg register and produces a new register (copy_reg) with 1's corresponding to the bit
lengths of the values encoded in the register (loaded in superposition).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_reg
|
Qubits
|
Register encoding the data to be multiplexed over. |
required |
ctrl
|
Qubits or int
|
Optional register to control on. Defaults to |
0
|
MultiplexedRealUSP ¶
Bases: Qubrick
Qubrick to perform multiplexed USP.
Uses the RealUSP flavor of USP from
"Even more efficient quantum computations of chemistry through tensor hypercontraction" arxiv:2011.03494 ⧉.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
contiguizer
|
Qubrick
|
Qubrick instance to generate the contiguized register. Defaults to
instance of |
None
|
multiplexor
|
Qubrick
|
Qubrick class to perform the multiplexing. Defaults to
|
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
compute(psi, index_reg, data_reg, data, rotator=None, succ_reg=None, error_param=None, ctrl: int = 0) -> None
Generate a superposition of USPs with values given by data.
The idea behind multiplexed USP is to take a list of dimensions d, and for each to prepare a d-dimensional
uniform state in a coherent superposition. This superposition will be loaded into the psi register. Two
additional registers must be passed in: index_reg, which is used to perform the multiplexing, and
data_reg, which contains an encoding of all of the d values (e.g. as loaded in via QROM).
To illustrate the idea, let's use a simple worked example. Say we have data=[2, 3].
Let us assume for simplicity that index_reg has been prepared in a uniform superposition state:
Then loading the data into the data_reg using QROM will yield the following state:
And the goal of multiplexed USP is to prepare the multiplexed state
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psi
|
Qubits
|
The register on which the superposition of uniform states is to be prepared. |
required |
index_reg
|
Qubits
|
The register used to load the indices for the multiplexing. |
required |
data_reg
|
Qubits
|
A register with the different values of |
required |
data
|
List[int]
|
List of dimensions for each of the USPs we are multiplexing over. |
required |
rotator
|
Qubits
|
Register to perform rotation on. Defaults to |
None
|
succ_reg
|
Qubits
|
Qubit to herald success. Defaults to |
None
|
error_param
|
float or int
|
Parameter determining the accuracy of truncated rotation
angles. If |
None
|
ctrl
|
Qubits or int
|
Optional register to control on. Defaults to |
0
|
Note
The effect of setting various default args has not been tested.
MultiplexedUSP ¶
Bases: Qubrick
Qubrick to perform multiplexed USP.
Uses the USP flavor of USP from
"Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
multiplexor
|
Qubrick
|
Qubrick class to perform the multiplexing. Defaults to ZeroAncMultiplexor. |
None
|
contiguizer
|
Qubrick
|
Qubrick instance to generate the contiguized register. Defaults to instance of Contiguizer. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Generate a superposition of USPs with values given by data.
The idea behind multiplexed USP is to take a list of dimensions d, and for each to prepare a d-dimensional
uniform state in a coherent superposition. This superposition will be loaded into the psi register. Two
additional registers must be passed in: index_reg, which is used to perform the multiplexing, and
data_reg, which contains an encoding of all of the d values (e.g. as loaded in via QROM).
To illustrate the idea, let's use a simple worked example. Say we have data=[2, 3].
Let us assume for simplicity that index_reg has been prepared in a uniform superposition state:
Then loading the data into the data_reg using QROM will yield the following state:
And the goal of multiplexed USP is to prepare the multiplexed state
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psi
|
Qubits
|
The register on which the superposition of uniform states is to be prepared. |
required |
index_reg
|
Qubits
|
The register used to load the indices for the multiplexing. |
required |
data_reg
|
Qubits
|
A register with the different values of |
None
|
data
|
List[int]
|
List of dimensions for each of the USPs we are multiplexing over. |
None
|
ctrl
|
Qubits or int
|
Optional register to control on. Defaults to |
0
|
data_bits
|
Qubits
|
Deprecated argument name for |
None
|
Note
The effect of setting various default args has not been tested.
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
|
BasisRotatedNumberOperator ¶
BasisRotatedNumberOperator(basis_transformation: MultiplexedRotationInterface, **kwargs: dict[str, Any])
Bases: Qubrick
Qubrick for basis-rotated number operator (BRNO).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
basis_transformation
|
MultiplexedRotationInterface
|
Qubrick to perform a basis transformation (in many chemistry algorithms, often products of Givens rotations). |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Perform the BRNO.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Index register. |
required |
target_reg
|
Qubits
|
Target register. |
required |
rotation_specs
|
RotationSpec
|
Specifications for each rotation. |
required |
config
|
GeneralMultiplexedRotationViaQROMConfig | int
|
Configuration data for the multiplexed rotation. |
required |
ctrl
|
Qubits | int
|
A register to control on. Defaults to |
0
|
GeneralMultiplexedRotationNaive ¶
GeneralMultiplexedRotationNaive(rot_qbk: RotationInterface | GivensRotation[float] = None, **kwargs)
Bases: Qubrick
Routine for implementing multiplexed rotations, allowing for various tradeoffs.
Attributes:
| Name | Type | Description |
|---|---|---|
rot_qbk |
RotationInterface
|
The rotation protocol compliant Qubrick used for rotation operations. |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rot_qbk
|
RotationInterface
|
The rotation protocol compliant Qubrick used for rotation operations. |
None
|
**kwargs
|
dict[str, Any]
|
Additional keyword arguments. |
{}
|
compute ¶
compute(index_reg: Qubits, target_reg: Qubits, rotation_specs: list[RotationSpec] | None = None, bits_of_precision: int | None = None, *, ctrl: Qubits | int = 0, **kwargs)
Compute circuit for a naive multiplexed rotation.
Implements the naive approach to multiplexed rotations by applying each rotation conditionally based on the index register matching the rotation's mux_idx. This implementation has no constraints on target qubits or rotation specifications, offering maximum flexibility at the cost of circuit efficiency.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Index register that selects which rotation to apply. |
required |
target_reg
|
Qubits
|
Target register containing all qubits where rotations may be applied. |
required |
rotation_specs
|
list[RotationSpec] | None
|
List of specifications for each rotation to be multiplexed. |
None
|
bits_of_precision
|
int | None
|
Precision for the rotation angles. |
None
|
ctrl
|
Qubits | int
|
Additional control for the entire operation (keyword-only parameter). |
0
|
**kwargs
|
dict[str, Any]
|
Additional keyword arguments. |
{}
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If rotation_specs is not provided, or if a rotation spec doesn't have a rotation Qubrick specified and no default was provided. |
GeneralMultiplexedRotationViaQROM ¶
GeneralMultiplexedRotationViaQROM(qrom: QROM, rot_qbk: RotationInterface | GivensRotation[Qubits] = None, adder: Adder = PhaseGradientAdder(), is_unary: bool | None = None, **kwargs)
Bases: Qubrick
Optimized implementation of multiplexed rotations using QROM for angle loading.
This Qubrick implements multiplexed rotations using a QROM-based approach for efficient angle loading, significantly reducing the T-count compared to naive implementations when there are many rotations.
The implementation has specific constraints: within each multiplexer group:
- All rotations must use the same rotation Qubrick.
- All rotations must target the same qubit indices.
However, different multiplexer groups can have different target qubits and rotation Qubricks. This allows for efficient batching while maintaining some flexibility.
Attributes:
| Name | Type | Description |
|---|---|---|
qrom |
Incomplete
|
The Qubrick used for quantum ROM operations to load rotation angles. |
rot_qbk |
Incomplete
|
Default rotation protocol compliant Qubrick used for all rotations unless overridden. |
adder |
Incomplete
|
Adder Qubrick used in the rotation implementation. |
bin_to_unary |
Incomplete
|
Converter for binary to unary encoding when required by the QROM. |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
qrom
|
QROM
|
The Qubrick instance used for quantum ROM operations. |
required |
rot_qbk
|
RotationInterface | GivensRotation[Qubits]
|
Default rotation protocol compliant Qubrick to use if not specified in individual rotation specs. If None, each RotationSpec must provide its own. |
None
|
adder
|
Adder
|
Adder Qubrick used in the rotation implementation. Defaults to PhaseGradientAdder(). |
PhaseGradientAdder()
|
is_unary
|
bool | None
|
Whether to use unary encoding for the index register. If None, auto-detects from the QROM implementation. |
None
|
**kwargs
|
dict[str, Any]
|
Additional keyword arguments passed to the Qubrick constructor. |
{}
|
compute_rotations ¶
compute_rotations(target_indices: list[list[int]], angle_reg: Qubits, target_reg: Qubits, rot_qbks_for_batch: list[RotationInterface], b_of_p: int) -> None
Apply rotation operations for each mux group using loaded angles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_indices
|
list[list[int]]
|
List of target qubit indices for each rotation. |
required |
angle_reg
|
Qubits
|
Register containing loaded angle values. |
required |
target_reg
|
Qubits
|
Target register containing qubits where rotations are applied. |
required |
rot_qbks_for_batch
|
list[RotationInterface]
|
List of rotation Qubricks to use for each rotation. |
required |
b_of_p
|
int
|
Bits of precision per rotation angle. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no rotation Qubrick is available for a rotation. |
compute ¶
compute(index_reg: Qubits, target_reg: Qubits, rotation_specs: list[RotationSpec] | None = None, mux_data: GeneralMultiplexedRotationViaQROMConfig | None = None, *, ctrl: Qubits | int = 0)
Compute circuit for multiplexed rotation using QROM-based implementation.
This method implements multiplexed rotations using QROM for efficient angle loading. It processes rotation specifications in batches, loads batched angle data from QROM, and applies rotations to target qubits according to the specifications.
The implementation requires that within each multiplexer group:
- All rotations must use the same rotation Qubrick.
- All rotations must target the same qubit indices.
Different multiplexer groups can have different target qubits and rotation Qubricks, allowing for flexibility while maintaining efficiency.
Note
This Qubrick supports Unary QROMs as well as Binary QROMs. If the QROM is unary,
it must have a is_unary attribute or you must set the is_unary flag in the __init__.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
The index register that selects which rotation to apply. |
required |
target_reg
|
Qubits
|
The register where rotations are applied. |
required |
rotation_specs
|
list[RotationSpec] | None
|
Specifications for each rotation. |
None
|
mux_data
|
GeneralMultiplexedRotationViaQROMConfig | None
|
Configuration data for the multiplexed rotation. |
None
|
ctrl
|
Qubits | int
|
Optional control for the entire operation. |
0
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
GivensPPRs ¶
Bases: Qubrick
Applies the Givens rotation using Pauli Product Rotations.
This method implements the unitary:
which is equivalent to applying two single-qubit rotations, one with \( +\theta \) and the other with \( -\theta \).
compute ¶
GivensRZs ¶
Bases: Qubrick
Implements a Givens rotation using RZ gates.
This class applies a Givens rotation using Pauli Z rotations (RZ) combined
with Clifford gates. The operation targets two qubits and implements the unitary:
This transformation can be decomposed into single-qubit RZ gates with Clifford conjugation:
- Apply a Clifford pre-rotation to transform the computational basis.
- Perform controlled
RZgates to introduce the phase shift. - Apply a Clifford post-rotation to revert to the original basis.
This method is useful in multiplexed rotations and block encoding techniques.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**kwargs
|
dict[str, Any]
|
Additional arguments passed to |
{}
|
compute ¶
GivensRotationFusedAdder ¶
Bases: Qubrick
Implements a Givens rotation using a fused quantum adder.
This method optimizes the standard two-adder approach by using a single fused adder, reducing qubit usage and circuit depth. Instead of requiring a full carry bit, it compresses the operation into a more compact form.
Note
- This implementation requires only \( b - 1 \) bits for a \( b \)-bit approximation of \( \theta \).
- The reduced bit count results from the fused adder structure, which avoids additional carry propagation.
- However, current implementations may have basis states reversed, which requires correction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
adder
|
GidneyAdd or NaiveAdd
|
The quantum adder used to update phase values.
Defaults to |
None
|
**kwargs
|
dict[str, Any]
|
Additional arguments passed to |
{}
|
compute ¶
GivensRotationTwoAdders ¶
Bases: Qubrick
Implements a Givens rotation using two quantum adders.
This method applies a Givens rotation by using a phase gradient register and two
quantum adders (GidneyAdd or NaiveAdd). It is particularly useful for
multiplexed rotations, allowing for efficient conditional operations on quantum states.
Note
- This implementation requires \( b + 1 \) bits for a \( b \)-bit approximation of \( \theta \).
- The extra bit accounts for the additional carry bit required in the controlled addition.
- If \( b \) bits are used, precision loss can occur due to truncation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
adder
|
GidneyAdd or NaiveAdd
|
The quantum adder used to update phase values.
Defaults to |
None
|
**kwargs
|
dict[str, Any]
|
Additional arguments passed to |
{}
|
compute ¶
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
|
ArbitraryStatePrep ¶
Bases: Qubrick
State preparation based on the routine in "Transformation of quantum states using uniformly controlled rotations" (arXiv:quant-ph/0407010 ⧉).
Realizes:
Note
This routine prepares the desired state up to a global phase. When checking the validity of this routine, one should check fidelity rather than exact state vector matching. The other consequence is that controlling this routine will lead to (incorrect) relative phases.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
multiplexor
|
(Qubrick, None)
|
Which multiplexing scheme to use in state prep.
Defaults to |
None
|
amps
|
list or None
|
List of amplitudes to load into state. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
EfficientMultiplexedRotations ¶
Bases: Qubrick
Decomposition of uniformly controlled rotations to single-qubit rotation + CNOTs.
Corresponds to Figure 2 in "Transformation of quantum states using uniformly controlled rotations" (arXiv:quant-ph/0407010 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
gate
|
op or None
|
Rotation gate type to use in multiplexed rotations. Defaults to None. |
None
|
angles
|
list or None
|
List of angles to supply to rotations. Defaults to None. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute the multiplexed rotation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits / int
|
Index qubits. |
required |
tgt
|
Qubits / int
|
Target qubit. |
required |
ctrl
|
(Qubits, int)
|
A register to control this operation on. Default to |
0
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the compute. |
{}
|
NaiveMultiplexedRotations ¶
Bases: Qubrick
Controlled rotations from "Transformation of quantum states using uniformly controlled rotations" (arXiv:quant-ph/0407010 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
gate
|
op or None
|
Rotation gate type to use in multiplexed rotations. Defaults to None. |
None
|
angles
|
list or None
|
List of angles to supply to rotations. Defaults to None |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute the multiplexed rotation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits / int
|
Index qubits. |
required |
tgt
|
Qubits / int
|
Target qubit. |
required |
ctrl
|
(Qubits, int)
|
A register to control this operation on. Default to |
0
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the compute. |
{}
|
PrepareNaive ¶
Bases: Qubrick
State preparation based on the routine in "Transformation of quantum states using uniformly controlled rotations" (arXiv:quant-ph/0407010 ⧉).
Realizes:
Warning
This function only works for real and positive coefficients.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
multiplexor
|
Qubrick
|
Which multiplexing scheme to use in state prep.
Defaults to |
None
|
coeffs
|
list or None
|
List of coefficients to load into state. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
BitonicPermutation ¶
Bases: Qubrick
A routine that permutes qubit registers.
compute ¶
compute(target_reg: Qubits, reg_size: int, register_permutation_function: Callable, ctrl: Qubits | int = 0)
Compute the circuit for the canonical SwapUp-type permutation.
The sorting/permutation logic to perform a permutation of a register is independent of the particular quantum operation used to effect a permutation. to use. This compute method exists so we can write down this logic just once and re-use it with your favorite "payload".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_reg
|
(Qubits, list)
|
Register we apply the permutation to. This register can conceptually be interpreted as a single large register, or as several registers of equal size. To facilitate this dual use, we currently allow passing a list of Qubits objects (though this is likely to be refactored). |
required |
reg_size
|
int
|
Number of bits in each target sub-register of |
required |
register_permutation_function
|
callable
|
Which quantum operation to use to effect the permutation of the target register. |
required |
ctrl
|
Optional[Qubits, int]
|
Qreg to control on. Defaults to 0. |
0
|
Note
target_reg is given as a single register or as a list of multiple registers.
PhaseGradientAdder ¶
Bases: Qubrick
Optimized adder for use in phase gradient addition.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**kwargs
|
dict[str, Any]
|
Keyword arguments |
{}
|
compute ¶
Circuit for optimized phase gradient adder.
This construction comes from Fig. 13 in "Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization" (arXiv:2007.07391 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
QUInt | None
|
The register with the phase gradient catalyst state. May be |
required |
rhs
|
QUInt
|
The register we are adding into the phase gradient register. |
required |
ctrl
|
(Optional, int | Qubits)
|
Control register. Defaults to |
None
|
Note
- The phase gradient register is usually one qubit smaller than the rhs.
- However, there exists at least one known case where they are equal in size
(for example, when using
GivensRotationTwoAdders). - When they are the same size, we can actually drop a CZ, so we distinguish these cases.
- For
rhstwo qubits andlhsone qubit shorter thanrhs, the Fig.~13 chain collapses to three bilinear gates (no temporary elbow). With no adder control, those arelhs.z(rhs[0]),lhs.x(rhs[0]),rhs[1].z(). With a control registerctrl(e.g. bidirectional rotation tests), mergectrlinto each gate aslhs[0].z(rhs[0] | ctrl),lhs[0].x(rhs[0] | ctrl),rhs[1].z(cond=ctrl). - For
lhsandrhsboth a single qubit, only the closing segment remains (matchingGidneyAddon one-qubitlhs).
NaivePhaseGradient ¶
Bases: Qubrick
Implement a phase gradient with a specified base angle.
This naive version simply applies a sequence of phase gates with angles that are halved for each subsequent qubit in the target register.
Note
For definition of a phase gradient, refer to Craig Gidney's blog post ⧉.
compute ¶
compute(target_reg: Qubits, base_angle: float | RotationAngle = ..., error_param: float = 0, ctrl: Qubits | int = 0)
Compute phase gradient circuit.
The default base angle is 180 degrees, which corresponds to a Z gate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_reg
|
Qubits
|
Target register upon which to apply rotations (a gradient of rotations). |
required |
base_angle
|
float | RotationAngle
|
Base angle from which subsequent angles are divided by \(2^k\), where \(k\) iterates over the target register. |
...
|
error_param
|
float
|
Precision of each angle in phase gradient, not overall error. |
0
|
ctrl
|
Qubits | int
|
Quantum control. |
0
|
PrepareClockState ¶
Bases: Qubrick
Prepares a clock state.
Example
For \(n = 3\) the output state will be of the form \(\sqrt{p_0}|000\rangle + \sqrt{p_1}|100\rangle + \sqrt{p_2}|110\rangle + \sqrt{p_3}|111\rangle\).
The ket-states should be understood as a unary representation of an integer. For example, \(|1110\rangle\) is 3 in decimal, and \(|1000\rangle\) is 1 in decimal.
Note
The controlled version only ensures \(\text{c-PREP}|+\rangle|0\rangle^{\otimes n} = |0\rangle|0\rangle^{\otimes n}+|1\rangle \text{PREP}|0\rangle^{\otimes n}\). In other words, if the input state is not zero, there is still an action of this Qubrick.
compute ¶
Prepare the clock state according to given probabilities.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Qubits
|
Target qubits. |
required |
probs
|
list
|
List of probabilities, such that the output state is of the form \(\sqrt{p_0}|000\rangle + \sqrt{p_1}|100\rangle + \sqrt{p_2}|110\rangle + \sqrt{p_3}|111\rangle\). |
required |
ctrl
|
(Qubits, int)
|
Control register. Default to 0. |
0
|
PrepareWState ¶
Bases: Qubrick
Prepares a W state.
Note
The controlled version only ensures \(\text{c-PREP}|+\rangle|0\rangle^{\otimes n} = |0\rangle|0\rangle^{\otimes n} + |1\rangle\text{PREP}|0\rangle^{\otimes n}\). In other words, if the input state is not zero, there is still an action of this Qubrick.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
khot_prep
|
Qubrick
|
Qubrick to implement a Clock state. |
None
|
wpower2_prep
|
Qubrick
|
Qubrick to prepare a W state over a power-of-two number of amplitudes. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
PrepareWStatePowerTwo ¶
Bases: Qubrick
Prepares a W state for power of two target size.
Note
The controlled version only ensures \(\text{c-PREP}|+\rangle|0\rangle^{\otimes 2^n} = |0\rangle|0\rangle^{\otimes 2^n} + |1\rangle\text{PREP}|0\rangle^{\otimes 2^n}\). In other words, if the input state is not zero, there is still an action of this Qubrick.
CosineWindow ¶
Bases: Qubrick
Cosine window from "Effects of Cosine Tapering Window on Quantum Phase Estimation" (arXiv:2110.09590 ⧉).
compute ¶
Executes circuit for implementing cosine window.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
phase_reg
|
Qubits
|
Phase qubit register. |
required |
ctrl
|
(Optional, int, Qubits)
|
Control register. |
0
|
**kwargs
|
dict[str, Any]
|
Optional keyword arguments. Included to stay consistent with the arguments of window emulators. |
{}
|
RectWindow ¶
Bases: Qubrick
Rectangular/Dirichlet window. This is the default window function for the textbook QPE.
compute ¶
Executes circuit for implementing rectangular window.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
phase_reg
|
Qubits
|
Phase qubit register. |
required |
ctrl
|
(Optional, int, Qubits)
|
Control register. |
0
|
**kwargs
|
dict[str, Any]
|
Optional positional arguments. Included to stay consistent with the arguments of window emulators. |
{}
|
SineWindow ¶
Bases: Qubrick
Qubrick for window state with the sine function over the amplitudes.
This window state can be used to achieve an optimal Holevo variance as outlined in Section II B. of "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉). See \(\Xi_m\) state.
Note
The state prepared here has a global phase of pi. Additionally, if the user does not care about having purely real or purely imaginary values in the prepared state, the rz gates can be replaced by phase gates, in which case the magnitudes will be the same as the expected state, but each amplitude will be rotated by some (global) phase.
compute ¶
Computes sine window function.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_reg
|
Qubits
|
Register on which the sine window state is prepared. |
required |
flag_reg
|
Qubits
|
Flag qubit when 0, the sine window state is prepared. |
required |
ctrl
|
Qubits
|
Control register. |
0
|
use_real_amps
|
bool
|
If True, prepares real amplitudes. |
False
|
**kwargs
|
dict[str, Any]
|
Optional keyword arguments. |
{}
|
Note
Needs a round of amplitude amplification.
SineWindowPhaseCatalysis ¶
Bases: Qubrick
Qubrick for window state with the sine function over the amplitudes.
Prepared via phase catalyst register.
This window state can be used to achieve an optimal Holevo variance as outlined in Section II B. of "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉). See \(\Xi_m\) state.
The phase catalyst implementation is outlined in Appendix B of "Option pricing under stochastic volatility on a quantum computer" (arXiv:2312.15871 ⧉)
Note
The state prepared here will be the same as SineWindow up to a global phase.
compute ¶
Computes sine window function via phase catalyst state.
Note
Needs a round of amplitude amplification.
SineWindowQubitEfficient ¶
Bases: Qubrick
Qubrick for window state with the sine function over the amplitudes using only two active qubits at a time.
This window state can be used to achieve an optimal Holevo variance with the construction of the circuit outlined in Section IV of "Optimum phase estimation with two control qubits" (arXiv:2303.12503 ⧉).
WindowEmulator ¶
WindowEmulator(emulator_func: Callable[Concatenate[int, P], NDArray], emulator_function_options: dict[str, Any] | None = None, **kwargs)
Bases: Qubrick
Constructor for window emulator.
Note
- Check the window utils module for
emulator_funcoptions. - Note that this Qubrick does not execute quantum operations; it directly modifies the state vector and is not meant to run on a real QPU program.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
emulator_func
|
callable
|
Method for computing amplitudes of a window state. |
required |
emulator_function_options
|
dict[str, Any]
|
Extra keyword arguments for the |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
emulator_func_kwargs
instance-attribute
¶
compute ¶
Compute amplitudes of taper state.
Note
Assumes qubits are ordered within QPU as: (1) Psi (2) Phase Register (3) All other qubits
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
phase_reg
|
Qubits
|
Phase qubit register. |
required |
psi
|
Qubits
|
System register. |
required |
ctrl
|
(Optional, int, Qubits)
|
Control register. |
0
|
**kwargs
|
dict[str, Any]
|
Optional keyword arguments. Included to stay consistent with the arguments of window emulators. |
{}
|
Note
- Use emulators for a reasonably small number of phase qubits!
- The controlled version is not currently implemented.
WindowStatePrep ¶
Bases: Qubrick
General class for simulating window state via state prep.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
amps
|
ndarray
|
Amplitudes for window state. |
required |
state_prep
|
Qubrick
|
Qubrick to implement the state preparation for the window function. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Executes circuit for preparing window state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
phase_reg
|
Qubits
|
Phase qubit register. |
required |
ctrl
|
(Optional, int, Qubits)
|
Control register. |
0
|
**kwargs
|
dict[str, Any]
|
Optional keyword arguments. Included to stay consistent with the arguments of window emulators. |
{}
|
CoherentIterativeQPE ¶
CoherentIterativeQPE(bits_of_precision, unitary, window_kwargs=None, window_func=RectWindow(), **kwargs)
Bases: Qubrick
Performs iterative QPE as shown in Fig. 16 of "A Grand Unification of Quantum Algorithms" (arXiv:2105.02859 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bits_of_precision
|
int
|
The number of bits of precision to estimate the eigenphase to. |
required |
unitary
|
Qubrick
|
The unitary to compute the eigenphase of. |
required |
window_kwargs
|
dict[str, Any]
|
Keyword arguments to pass to the window function. |
None
|
window_func
|
Qubrick
|
Which window func to apply to the initial state of the phase register. Defaults to
|
RectWindow()
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute coherent iterative quantum phase estimation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psi
|
Qubits
|
State register for the computation. |
required |
phase_reg
|
Qubits
|
Register to load the eigenphase into. |
required |
ctrl
|
(Optional, int, Qubits)
|
Register to control the QPE on. |
0
|
unitary_kwargs
|
dict[str, Any]
|
Any additional kwargs that need to be passed to the |
{}
|
Note
The control version makes no assumptions on the input states (phase register), and thus uses a naive control implementation (control on all operations). If the phase register is known to be in the zero state, one can control only phase window and the QFT.
DoublePhaseKickbackQPE ¶
DoublePhaseKickbackQPE(bits_of_precision, unitary: QubitizedWalkOperator, window_func=RectWindow(), window_kwargs=None, **kwargs)
Bases: Qubrick
Implements the double-phase kickback quantum phase estimation routine.
This version of QPE achieves m bits of precision using m qubits in the
phase register, but uses approximately half the number of queries to the unitary
than is necessary when using traditional QPE. It should be noted however that the
input unitary for this approach must be in the form of a qubitized walk operator
as outlined in Fig. 1 of "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity"
(arXiv:1805.03662 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bits_of_precision
|
int
|
The number of bits to estimate the phase. |
required |
unitary
|
QubitizedWalkOperator
|
The unitary for which we want to estimate the eigenphase. Must be in the form of a qubitized walk operator as outlined in Fig. 1 of "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉). |
required |
window_func
|
Qubrick
|
Which window func to apply to the initial state of the phase register. |
RectWindow()
|
window_kwargs
|
dict
|
Keyword args for window func (e.g. in case it uses amplitude amplification). Defaults to None. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute QPE based on Figure 2 of "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psi
|
Qubits
|
State register for the computation. |
required |
phase_reg
|
Qubits
|
Register to load the eigenphase into. |
required |
be_ancilla_reg
|
Qubits
|
State register used to implement the
block encoding on |
required |
ctrl
|
(Optional, int, Qubits)
|
Register to control the QPE on.
Defaults to |
0
|
kwargs
|
dict[str, Any]
|
Any additional kwargs that need to be passed to the
|
{}
|
IterativeQPE ¶
Bases: Qubrick
Implements incoherent (measurement-based) QPE.
Warning
Iterative quantum phase estimation can be performed using a single auxiliary qubit, and
this Qubrick can do it. In this case, you need to fetch the result from the compute method
via get_classical_result('phase_readout') method.
If you're performing iterative phase estimation using multiple auxiliary qubits, you can fetch the result by measuring the phase register, same as for the other QPE implementations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bits_of_precision
|
int
|
The number of bits of precision to estimate the eigenphase to. |
required |
unitary
|
Qubrick
|
The unitary to compute the eigenphase of. |
required |
window_kwargs
|
dict[str, Any]
|
Keyword arguments to pass to the window function. |
None
|
window_func
|
Qubrick
|
Which window func to apply to the initial state of the phase register. Defaults to
|
RectWindow()
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute quantum phase estimation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psi
|
Qubits
|
State register for the computation. |
required |
phase_reg
|
(Qubits, Optional)
|
Register into which the eigenphase is loaded. |
required |
ctrl
|
(Optional, int, Qubits)
|
Register to control the QPE on. |
0
|
unitary_kwargs
|
dict[str, Any]
|
Any additional kwargs that need to be passed to the |
{}
|
Note
- The control version makes no assumptions on the input states (phase register), and thus uses a naive control implementation (control on all operations). If the phase register is known to be in the zero state, one can control only phase window and the QFT.
- Classical result is the list of binary values corresponding to the
bits_of_precisionbit representation of the estimated eigenphase, in little-endian encoding.
OptimizedDoublePhaseKickbackQPE ¶
OptimizedDoublePhaseKickbackQPE(bits_of_precision, unitary: QubitizedWalkOperator, window_func=RectWindow(), window_kwargs=None, **kwargs)
Bases: Qubrick
Implements an optimized version of the double-phase kickback quantum phase estimation routine.
There are two main optimizations we use here that lead to some minor gate-cost reductions:
- Subsequent applications of the controlled reflections (C-R_L) can be merged together with some simple qubit logic consisting of two CNOT gates. This means that in the middle of the circuit, we reduce the cost of applications of C-R_L (PREP^ - Refl - PREP) by approximately a factor of 2.
- Inspecting the naive
DoublePhaseKickbackQPEcircuit, there are often applications of PREP that are immediately followed by PREP^. With some classical logic, we can choose to not apply these gates, as PREP is self-inverse.
In the same way as DoublePhaseKickbackQPE, this version of QPE achieves m bits of precision using m qubits in
the phase register, but uses approximately half the number of queries to the unitary than is necessary when using
traditional QPE. It should be noted however that the input unitary for this approach must be in the form of a
qubitized walk operator as outlined in Fig. 1 of "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity"
(arXiv:1805.03662 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bits_of_precision
|
int
|
The number of bits to estimate the phase. |
required |
unitary
|
QubitizedWalkOperator
|
The unitary for which we want to estimate the eigenphase. Must be in the form of a qubitized walk operator as outlined in Fig. 1 of "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉). |
required |
window_func
|
Qubrick
|
Which window func to apply to the initial state of the phase register. |
RectWindow()
|
window_kwargs
|
dict
|
Keyword args for window func (e.g. in case it uses amplitude amplification). Defaults to None. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute QPE based on Figure 2 of "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psi
|
Qubits
|
State register for the computation. |
required |
phase_reg
|
Qubits
|
Register to load the eigenphase into. |
required |
be_ancilla_reg
|
Qubits
|
State register used to implement the block encoding on psi. |
required |
ctrl
|
(Optional, int, Qubits)
|
Register to control the QPE on.
Defaults to |
0
|
kwargs
|
dict[str, Any]
|
Any additional kwargs that need to be passed to the
|
{}
|
QPE ¶
Bases: Qubrick
Implements the standard quantum phase estimation routine using controlled unitaries and QFT.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bits_of_precision
|
int
|
The number of bits to estimate the phase to. |
required |
unitary
|
Qubrick
|
The unitary for which we want to estimate the eigenphase. |
required |
window_kwargs
|
dict
|
Keyword args for window func (e.g. in case it uses amplitude amplification). Defaults to None. |
None
|
window_func
|
Qubrick
|
Which window func to apply to the initial state of the phase register. Defaults to
|
RectWindow()
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute quantum phase estimation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psi
|
Qubits
|
State register for the computation. |
required |
phase_reg
|
Qubits
|
Register to load the eigenphase into. |
required |
ctrl
|
(Optional, int, Qubits)
|
Register to control the QPE on. |
0
|
unitary_kwargs
|
dict[str, Any]
|
Any additional kwargs that need to be passed to the |
{}
|
Note
The control version makes no assumptions on the input states (phase register), and
thus uses a naive control implementation (control on all operations). If the phase
register is known to be in the zero state, one can control only phase window and the
QFT or, if the RectWindow is used, one could only control the unitary.
Qubitization ¶
Bases: Qubrick
Canonical qubitization iterate.
This Qubrick follows the canonical form of Qubitization introduced in "Hamiltonian Simulation by Qubitization" (arXiv:1610.06546 ⧉) and used extensively in Lin Lin's lecture notes ⧉. This convention starts with a block encoding followed by an all-zero reflection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
block_encoding
|
Qubrick
|
Qubrick to apply the block encoding circuit. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
compute(psi: Qubits, be_ancilla_reg: Qubits, data: PauliSum | list[int], ctrl: Qubits | int = 0, **kwargs: dict[str, Any])
Compute the qubitization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psi
|
Qubits
|
Target state register. |
required |
be_ancilla_reg
|
Qubits
|
Block encoding auxiliary register. |
required |
data
|
PauliSum | list[int]
|
Hamiltonian or bitstring values to be qubitized. |
required |
ctrl
|
Qubits | int
|
Register to control the qubitization on. Defaults to |
0
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the compute. |
{}
|
QubitizedWalkOperator ¶
Bases: Qubrick
Qubitization iterate.
This Qubrick uses the form introduced in "Quantum Algorithm for Spectral Measurement with Lower Gate Count" (arXiv:1711.11025 ⧉).
This form is also used by the Google group for their QPE-Qubitization papers.
This form differs from the canonical Qubitization iterate (see Fig. 1 of
"Even more efficient quantum computations of chemistry through tensor hypercontraction"
(arXiv:2011.03494 ⧉)), and effectively performs a qubitization
of a quantum walk, hence the name QubitizedWalkOperator.
Note
Despite being a Qubitization iterate, this Qubrick has a different signature
than the canonical Qubitization Qubrick, in that it is defined in terms of
\(\text{PREP}\) and \(\text{SELECT}\) rather than arbitrary block encodings.
Furthermore, when plugging it in to QPE, one must be careful with what initial state
is passed to QPE. When using this Qubrick, one must first call \(\text{PREP}\)'s
compute before calling QPE's compute, as this \(\text{PREP}\) effectively
prepares a portion of an eigenstate of the QubitizedWalkOperator
(or at least a state which has meaningful support on it).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state_prep
|
Qubrick
|
Qubrick to apply the state prep. |
required |
select
|
Qubrick
|
Qubrick to select the Hamiltonian terms from. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
compute(psi: Qubits, be_ancilla_reg: Qubits, data: PauliSum | list[int], ctrl: Qubits | int = 0, **kwargs: dict[str, Any])
Compute the qubitization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psi
|
Qubits
|
Target state register. |
required |
be_ancilla_reg
|
Qubits
|
Block encoding auxiliary register. |
required |
data
|
PauliSum | list[int]
|
Hamiltonian or bitstring values to be qubitized. |
required |
ctrl
|
Qubits | int
|
Register to control the qubitization on. Defaults to |
0
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the compute. |
{}
|
BinaryTreeSelect ¶
Bases: Qubrick
Optimized select from Fig. 7 in "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).
compute ¶
Compute Select circuit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Qubit register determining which op in data to apply. |
required |
target_reg
|
Qubits
|
Qubit register to apply the data to. |
required |
data
|
PauliSum | list[int]
|
Hamiltonian terms expressed as a |
required |
ctrl
|
Qubits | int
|
Control register. Defaults to 0. |
0
|
ConditionallyCleanSelect ¶
Bases: Qubrick
Select utilizing conditionally clean construction as presented in "Rise of conditionally clean ancillae for efficient quantum circuit constructions" (arXiv:2407.17966 ⧉).
Notes
This should be called with the filter '>>toffoli-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.
compute ¶
Compute Select circuit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Qubit register determining which op in data to apply. |
required |
target_reg
|
Qubits
|
Qubit register to apply the data to. |
required |
data
|
(PauliSum, List[int])
|
Hamiltonian terms expressed as a
|
required |
ctrl
|
(int, Qubits)
|
Control register. Defaults to 0. |
0
|
SawtoothSelect ¶
Bases: Qubrick
Unoptimized select from Fig. 5 in "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).
compute ¶
Compute Select circuit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Qubit register determining which op in data to apply. |
required |
target_reg
|
Qubits
|
Qubit register to apply the data to. |
required |
data
|
PauliSum | list[int]
|
Hamiltonian terms expressed as a |
required |
ctrl
|
Qubits | int
|
Control register. Defaults to 0. |
0
|
SelectNaive ¶
Bases: Qubrick
Most naïve version of \(\text{SELECT}\) possible.
If the data to be loaded is given as a list of Hamiltonian terms, performs the transformation
If the data to be loaded as given as a list of bit values \(data\), performs the transformation
compute ¶
Compute Select circuit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Qubit register determining which op in data to apply. |
required |
target_reg
|
Qubits
|
Qubit register to apply the data to. |
required |
data
|
PauliSum | list[int]
|
Hamiltonian terms expressed as a |
required |
ctrl
|
Qubits | int
|
Control register. Defaults to 0. |
0
|
SelectOneAnc ¶
Bases: Qubrick
\(\text{SELECT}\) operator using a single, clean auxiliary qubit.
Circuit shown in Fig. 1A in "Trading T gates for dirty qubits in state preparation and unitary synthesis" (arXiv:1812.00954 ⧉).
compute ¶
Compute Select circuit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Qubit register determining which op in data to apply. |
required |
target_reg
|
Qubits
|
Qubit register to apply the data to. |
required |
data
|
PauliSum | list[int]
|
Hamiltonian terms expressed as a |
required |
ctrl
|
Qubits | int
|
Control register. Defaults to 0. |
0
|
BitonicSort ¶
Bases: Qubrick
Qubrick for performing a bitonic sort on a list of qubits.
unsort ¶
Uncompute sort a list of qubit registers.
This performs a measurement in the X basis for each record qubit. If the outcome is one, it will require a phase-fixup performed by a comparator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
regs_list
|
list[Qubits]
|
List of qubit registers to unsort. |
required |
ctrl
|
(int, Qubits)
|
Control qubit for the routine. |
0
|
compute ¶
Sort a list of qubit registers.
Sort in ascending order if direction = 0, and descending otherwise. See Wikipedia article on bitonic sorter ⧉.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
regs_list
|
list[Qubits] or VectorRegister
|
List of qubit registers to sort. |
required |
direction
|
int
|
Direction of the sort (0-ascending vs 1-descending). |
required |
ctrl
|
(int, Qubits)
|
Control qubit for the routine. Defaults to 0. |
0
|
Note
This assumes same size register for all registers in regs_list.
BinaryToUnaryUncomputation ¶
Bases: Qubrick
Circuit which undoes a binary to unary conversion.
Suppose we have an index register which encodes some integer \(i\) between zero and \(N - 1\) in binary, but we wish to convert this to unary. One way to do this would be to allocate \(N - 1\) auxiliary qubits (starting in the zero state), perform a Pauli X on the topmost auxiliary qubit, and "swap it down" to the \(i^{\text{th}}\) position (i.e. perform the dagger of SwapUp). This gives us a unary encoding of \(i\) on the auxiliary qubits entangled with a binary encoding of \(i\) on the index reg.
If we are later tasked with uncomputing/disentangling the auxiliary register from the index reg, we could simply use SwapUp to bring the ON bit back to the top auxiliary qubit, and then turn it back OFF with a Pauli X again. In this situation, by construction, we are returning all the auxiliary qubits back to zero. In this situation, we needn't use the canonical SwapUp circuit for the uncomputation; we can instead employ the use of measurement-based uncomputation, which instead uses right elbows and no non-Clifford gates. This method is discussed in Appendix C and depicted in Fig. 10 in "Qubitization of Arbitrary Basis Quantum Chemistry Leveraging Sparsity and Low Rank Factorization" (arXiv:1902.02134 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
permutation_qbk
|
Qubrick
|
Qubrick to implement the bitonic permutations. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute reversal of Binary to Unary conversion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Input number state. |
required |
target_reg
|
Qubits
|
Register we apply the swap network to. |
required |
reg_size
|
int
|
Number of bits in each output register. |
required |
ctrl
|
Optional[Qubits, int]
|
Qreg to control on. Defaults to 0. |
0
|
InjectOp ¶
Bases: Qubrick
Inject operation, defined as SwapUp \(^\dagger\) Op SwapUp.
This follows the construction introduced in Eq. 9 in "Exponentially faster implementations of Select(H) for fermionic Hamiltonians" (arXiv:2004.04170 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
swap_up
|
Qubrick
|
SwapUp implementation. |
required |
op
|
Qubrick
|
The unitary to inject. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute Inject circuit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Input number state. |
required |
target_reg
|
Qubits or VectorRegister
|
Register to apply the operation to. |
required |
reg_size
|
int
|
Number of bits in each item in the target register. |
required |
ctrl
|
Optional[Qubits, int]
|
Qreg to control on. Defaults to 0. |
0
|
Note
For single-qubit unitaries (reg_size = 1), you can pass Qubits as target_reg.
For multi-qubit unitaries (reg_size > 1), use VectorRegister as target_reg.
SwapUp ¶
Bases: Qubrick
Canonical SwapUp circuit that acts on arbitrary input states.
Assuming an already-loaded list of \(n\) items, each \(b\) bits long, this routine "swaps up" item with index \(x\) from the loaded items to the top position, i.e., to the top \(b\) qubits. The other items remain in positions \(1, ..., n - 1\), permuted in some order.
This follows the construction introduced in "Trading T gates for dirty qubits in state preparation and unitary synthesis" (arXiv:1812.00954 ⧉).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
permutation_qbk
|
Qubrick
|
Qubrick to implement the bitonic permutations. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
compute ¶
Compute SwapUp circuit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index_reg
|
Qubits
|
Input number state. |
required |
target_reg
|
Qubits
|
Register we apply the swap network to. |
required |
reg_size
|
int
|
Number of bits in each item in the target register. |
required |
ctrl
|
Optional[Qubits, int]
|
Qreg to control on. Defaults to 0. |
0
|
PauliSumTrotterStrategy ¶
Implementation of a TrotterStrategy for the simplest case of looping through Hamiltonian terms.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hamiltonian
|
PauliSum
|
PauliSum representation of the Hamiltonian to be Trotterized. The order of the terms in the PauliSum determines the order in which the Trotterized terms will be applied, with the coefficients determining their magnitude. |
required |
trotter_order
|
int
|
The order of the Trotterization. |
None
|
apply_trotter_terms ¶
Apply all the terms in the Hamiltonian, numerically or symbolically.
TrotterQuery ¶
TrotterQuery(trotter_strategy: TrotterStrategy | None = None, trotter_order: int | None = None, hamiltonian: PauliSum | None = None, **kwargs)
Bases: Qubrick
Qubrick for implementing a Suzuki-Trotter approximation of an exponentiated Hamiltonian.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trotter_strategy
|
TrotterStrategy | None
|
A class that implements a |
None
|
trotter_order
|
int
|
The order of Trotterization. |
None
|
hamiltonian
|
PauliSum
|
The Hamiltonian expressed as a PauliSum. |
None
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
trotter_strategy
property
¶
Set the trotter_strategy property so it can't be modified.
compute ¶
compute(system: Qubits, steps: int, evo_time: int, ctrl: Qubits | int = 0, trotter_order: int | None = None)
Execute the Suzuki-Trotter circuit.
Performs first and second order Trotterization directly. For higher orders, uses recursive calls to generate the appropriate product of operators.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
Qubits
|
Qubits the Hamiltonian is acting on. |
required |
steps
|
int
|
The number of Trotter steps. |
required |
evo_time
|
int
|
The total evolution time. |
required |
ctrl
|
(Qubits, int)
|
Qubit register to control evolution on. Defaults to 0. |
0
|
trotter_order
|
int
|
The order of Trotterization. If not set,
uses the Qubrick attribute |
None
|
TrotterStrategy ¶
Bases: Protocol
Interface for applying unitary terms in Trotterization.
apply_trotter_terms ¶
apply_trotter_terms(factor: int | float | complex, system: Qubits, reverse: bool = False, ctrl: Qubits | int = 0)
Method describing how to apply the terms in Trotterization, to be implemented in concrete implementations.
RealUSP ¶
Bases: Qubrick
Qubrick for performing Uniform State Preparation.
From "Even more efficient quantum computations of chemistry through tensor hypercontraction" (arXiv:2011.03494 ⧉).
Note
- This is the version based on the instructions (steps 1-7) under Eq. A15 of Appendix A.
- A circuit diagram showing a similar implementation (but over two target registers) is shown in Fig. (3).
compute ¶
compute(d, target_qreg, rotator=None, succ_reg=None, error_param=None, ctrl: int = 0, **kwargs) -> None
Prepare a uniformly distributed state.
Conceptually, starts by factoring \(d = 2^k L\), although this explicit calculation has been replaced by
the num_trailing_zeros and highest_bit functions for better performance.
Just applying Hadamard gates creates the desired equal superposition over k of the qubits.
For the remaining qubits we need to also perform amplitude amplification to keep only basis states with value < d.
Utilizes one auxiliary qubit, the 'rotator', such that CZ gates perform the required reflections.
This routine uses RY rotations, resulting in only real amplitudes.
If no error_param is provided, the rotations are treated as ideal and the probability of success is 1.0.
If an error_param is provided, the probability of success will be <=1.0 and a flag qubit will store the result via a comparator.
This qubit can be optionally provided via succ_reg.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
int
|
The number of nonzero terms required. |
required |
target_qreg
|
Qubits
|
The register to operate on. |
required |
rotator
|
Qubits
|
Register to perform rotation on. Defaults to |
None
|
succ_reg
|
Qubits
|
Qubit to herald success. Defaults to |
None
|
error_param
|
float
|
Parameter determining the accuracy of truncated rotation
angles. If |
None
|
ctrl
|
Qubits or int
|
Register to control the USP on. Defaults to |
0
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the compute. |
{}
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the register passed in is too small. |
Note
The effect of setting various default args has not been tested.
USP ¶
Bases: Qubrick
Qubrick for performing Uniform State Preparation.
From Fig. 12 in "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).
compute ¶
Prepare a uniformly distributed state.
Conceptually, starts by factoring \(d = 2^k L\), although this explicit calculation has been replaced by
the num_trailing_zeros and highest_bit functions for better performance.
Just applying Hadamard gates creates the desired equal superposition over k of the qubits.
For the remaining qubits we need to also perform amplitude amplification to keep only basis states with value < d.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
int
|
Desired number of uniform terms. |
required |
target_qreg
|
Qubits
|
The register to operate on. |
required |
error_param
|
float
|
Parameter determining the accuracy of truncated rotation
angles. If |
None
|
ctrl
|
Qubits or int
|
Register to control the USP on. Defaults to |
0
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the compute. |
{}
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the register passed in is too small. |
Note
The effect of setting various default args has not been tested. Creates desired state up to global phase.
ZeroAncillaUSP ¶
Bases: Qubrick
Qubrick for performing Uniform State Preparation without auxiliary qubits.
Adapted from "An efficient quantum algorithm for preparation of uniform quantum superposition states" (arXiv:2306.11747 ⧉).
compute ¶
Prepare a uniformly distributed state.
Utilizes binary decomposition of \(d\), controlled Ry and Hadamard gates to avoid auxiliary qubit usage.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
int
|
Desired number of uniform terms. |
required |
target_qreg
|
Qubits
|
The register to operate on. |
required |
ctrl
|
Qubits or int
|
Register to control the USP on. Defaults to |
0
|
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the compute. |
{}
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the register passed in is too small. |
AbsoluteDisplacement ¶
Bases: Qubrick
Qubrick for computing the reciprocal of the absolute value of the difference of two vectors.
Specifically, it computes
Note
Currently, it is on the user to set the constructor args for sub-Qubricks.
A consequence of this is that if you want to allow negative values, this must be
decided when you instantiate the square sub-Qubrick inside of orthogonal_dot_product
rather than in this Qubrick's constructor. Discussions on where this decision should be made
are ongoing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
orthogonal_dot_product
|
Qubrick
|
Qubrick for computing the square of a vector. |
required |
vector_sub
|
Qubrick
|
Adder Qubrick for subtracting Qubit registers. |
required |
rsqrt
|
Qubrick
|
Qubrick for performing the reciprocal square root operation. |
required |
kwargs
|
dict[str, Any]
|
Other keyword arguments for the Qubrick. |
{}
|
orthogonal_dot_product
instance-attribute
¶
compute ¶
Compute circuit for taking the absolute value of the difference between two vectors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q_vec1
|
list
|
List of registers encoding vector components for one vector. |
required |
q_vec2
|
list
|
List of registers encoding vector components for the other vector. |
required |
high_precision
|
(Optional, bool)
|
If True, returns high precision output from inverse square-root. Defaults to False. |
False
|
OrthogonalDotProduct ¶
Bases: Qubrick
Qubrick for squaring an n-component vector, then adding the squared results.
For example, for a 3-component vector this computes \(x^2 + y^2 + z^2\).
Note
Currently, it is on the user to set the constructor argumentss for sub-Qubricks.
A consequence of this is that if you want to allow squaring negative values,
this must be decided when you instantiate the square sub-Qubrick rather than
in this Qubrick's constructor. Discussions on where this decision should be made
are ongoing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
release_ancillae
|
bool
|
Whether to release auxiliary qubits in the squaring components. |
required |
square
|
Qubrick
|
Qubrick that computes the square of a qubit register. |
required |
add
|
Qubrick
|
Adder Qubrick. |
required |
**kwargs
|
dict[str, Any]
|
Other arguments to pass to the init. |
{}
|
VectorAddition ¶
Bases: Qubrick
Qubrick for adding (or subtracting) the components of two vectors of Qubits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
add
|
Qubrick
|
Adder Qubrick. |
required |
subtract_condition
|
(Optional, bool)
|
Whether to add or subtract the two vectors. Defaults to False (addition). |
False
|
kwargs
|
dict[str, Any]
|
Other keyword arguments for the Qubrick. |
{}
|
compute ¶
Compute circuit for computing the sum (or difference) of two vectors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q_vec1
|
list
|
List of registers encoding vector components for one vector. |
required |
q_vec2
|
list
|
List of registers encoding vector components for the other vector. |
required |
Note
The lengths of both vectors must be equal. Currently, this Qubrick cannot handle adding registers of different sizes correctly.
Currently, this method casts the results of addition to QInt objects in order to handle
negative signs. This will be generalized.
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. |
BinaryToUnaryComputation ¶
Factory function that creates a BinaryToUnaryUncomputation instance with dagger=True.
This is an alias to make the binary-to-unary conversion more intuitive by avoiding the double negative of "Uncomputation" with dagger=True. This function performs a binary-to-unary conversion by internally using BinaryToUnaryUncomputation with the dagger operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**kwargs
|
dict[str, Any]
|
Additional keyword arguments. The 'dagger' parameter will be set to True regardless of what is passed. |
{}
|
Returns:
| Type | Description |
|---|---|
BinaryToUnaryUncomputation
|
An instance configured for binary-to-unary conversion. |