Skip to content
Construct PsiQDK Algorithms

algorithms

algorithms

CondCleanBuild

CondCleanBuild(collect_from_msb: bool = False, **kwargs)

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.

collect_from_msb instance-attribute

collect_from_msb: Incomplete = collect_from_msb

n instance-attribute

n: Incomplete

anc instance-attribute

anc: Incomplete

compute

compute(val_reg: Qubits, avail_anc: Qubits = None, bit: int = None, use_elbows: bool = True)

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

CondCleanIncrementer(**kwargs)

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.

ctrl instance-attribute

ctrl: Incomplete

n instance-attribute

n: Incomplete

val_reg instance-attribute

val_reg: Incomplete

anc_reg instance-attribute

anc_reg: Incomplete

num_layers instance-attribute

num_layers: Incomplete

compute

compute(val_reg: Qubits, avail_anc: Qubits | None = None, ctrl: Qubits | int | None = None)

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

CondCleanLessThanConst(**kwargs)

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.

n instance-attribute

n: Incomplete

num_layers instance-attribute

num_layers: Incomplete

targ instance-attribute

targ: Incomplete

const_bin instance-attribute

const_bin: Incomplete

anc_reg instance-attribute

anc_reg: Incomplete

break_bit instance-attribute

break_bit: Incomplete

val_reg instance-attribute

val_reg: Incomplete

compute

compute(val_reg: QUInt | QUFixed, const: int, avail_anc: Qubits | None = None, flag_qubit: Qubits | None = None)

Perform comparison.

Parameters:

Name Type Description Default
val_reg QUInt | QUFixed

Register storing value to compare with classical constant.

required
const int

Constant integer to compare to.

required
avail_anc Qubits | None

Provide clean ancilla to utilize (requires log*(n)).

None

CondCleanSelect

CondCleanSelect(**kwargs)

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.

add_engine instance-attribute

add_engine: Incomplete = add_engine

expand_dest_qreg instance-attribute

expand_dest_qreg: Incomplete = expand_dest_qreg

release_ancillae instance-attribute

release_ancillae: Incomplete = release_ancillae

check_overflow

check_overflow(dst, rhs, ctrl, subtract_condition, do_warning: bool = True) -> None

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

ConditionallyCleanAdd(**kwargs)

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

CuccaroAdd(**kwargs)

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

CuccaroDepthOptimisedAdd(**kwargs)

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

CuccaroMultiplyAdd(params=None, routines=None, **kwargs)

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

GidneyAdd(**kwargs)

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.

GidneyLadder

GidneyLadder(**kwargs)

Bases: Qubrick

Basic tall-Toffoli-to-Gidney-elbow reduction.

compute

compute(ctrl=None, reduce_to: int = 2, condition=None) -> None

This reduces tall condition stacks using Gidney elbows.

Parameters:

Name Type Description Default
ctrl Qubits

Condition qubits to reduce

None
reduce_to int

Max number of conditions to output

2

GidneyMultiplyAdd

GidneyMultiplyAdd(**kwargs)

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

GidneySquare(params=None, routines=None, **kwargs)

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

add_engine instance-attribute

add_engine: Incomplete = add_engine

mul_engine instance-attribute

mul_engine: Incomplete = mul_engine

add instance-attribute

add: Incomplete = AddBase(add_engine=add_engine)

allow_negative_input instance-attribute

allow_negative_input: Incomplete = allow_negative_input

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

NaiveAdd(**kwargs)

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

NaiveMultiplyAdd(params=None, routines=None, **kwargs)

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

NaiveSquare(params=None, routines=None, **kwargs)

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

OptimizedGidneyMultiplyAdd(**kwargs)

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

OptimizedNaiveMultiplyAdd(params=None, routines=None, **kwargs)

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

add_engine instance-attribute

add_engine: Incomplete = add_engine

square_engine instance-attribute

square_engine: Incomplete = square_engine

allow_negative_input instance-attribute

allow_negative_input: Incomplete = allow_negative_input

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

ModularAdd(adder_qubrick=None, **kwargs)

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

adder_qubrick instance-attribute

adder_qubrick: Incomplete = adder_qubrick

compute

compute(dst: QUInt, rhs: QUInt | int, M: int, ctrl: Qubits | None = None)

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 dst.

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

QFTAdd(**kwargs)

Bases: Qubrick

Quantum adder implemented using QFT.

Follows the construction in "Quantum arithmetic with the Quantum Fourier Transform" (arxiv:1411.5949 ⧉).

compute

compute(lhs: QUInt, rhs: QUInt | int, ctrl: Qubits | None = None) -> None

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 lhs. If an int is passed, this defaults to calling QFTIncrement.

required
ctrl (Qubits, Optional)

Qubits the addition is conditioned on. Defaults to None.

None

QFTIncrement

QFTIncrement(**kwargs)

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(lhs: QUInt, rhs: QUInt | int = 1, ctrl: Qubits | None = None) -> None

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 lhs. If a Qubits is passed, this defaults to calling QFTAdd.

1
ctrl (Qubits, Optional)

Qubits the addition is conditioned on. Defaults to None.

None

QFTMultiply

QFTMultiply(**kwargs)

Bases: Qubrick

Quantum multiplier implemented using QFT.

Follows the construction in "Quantum arithmetic with the Quantum Fourier Transform" (arxiv:1411.5949 ⧉).

compute

compute(a: QUInt, b: QUInt, cond: Qubits | int = 0)

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

QFTSubtract(**kwargs)

Bases: Qubrick

Quantum subtractor implemented using QFT.

compute

compute(target_qubits: QUInt, subtraction_amount: QUInt | int, cond: int = 0)

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 target_qubits. If an int is passed, this defaults to calling QFTIncrement.

required
cond (Qubits, int)

Qubits the subtraction is conditioned on.

0

Reflect

Reflect(qc=None, **kwargs)

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).

adder instance-attribute

adder: Incomplete = adder

gate_efficient instance-attribute

gate_efficient: Incomplete = gate_efficient

do_label instance-attribute

do_label: Incomplete = do_label

bits_of_precision instance-attribute

bits_of_precision: Incomplete

finite_angle_int instance-attribute

finite_angle_int: Incomplete

finite_angle instance-attribute

finite_angle: Incomplete

compute_precision_bits staticmethod

compute_precision_bits(angle)

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

RossSelingerSynthesis(rs_engine=None, **kwargs)

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

rs_engine instance-attribute

rs_engine: Incomplete = rs_engine

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

Rotation(rotation_engine=None, qc=None)

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

rotation_engine instance-attribute

rotation_engine: Incomplete = rotation_engine

simulate_gate instance-attribute

simulate_gate: bool = True

qc instance-attribute

qc: Incomplete = qc

phase

phase(angle, target, error_param: int = 0, ctrl: int = 0) -> None

Compute phase gate.

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

0
ctrl Qubits or int

Quantum control

0

rz

rz(angle, target, error_param: int = 0, ctrl: int = 0) -> None

Compute Rz gate.

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

0
ctrl Qubits or int

Quantum control

0

rx

rx(angle, target, error_param: int = 0, ctrl: int = 0) -> None

Compute Rx gate.

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

0
ctrl Qubits or int

Quantum control

0

ry

ry(angle, target, error_param: int = 0, ctrl: int = 0) -> None

Compute Ry gate.

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

0
ctrl Qubits or int

Quantum control

0

ppr

ppr(angle, x_mask, z_mask, error_param: int = 0, ctrl: int = 0) -> None

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

compute(angle, target, error_param, rot_is_rz, ctrl) -> None

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

RotationCatalystHandler(qc, angle, size)

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 valid is 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

qc instance-attribute

qc: Incomplete = qc

angle instance-attribute

angle: Incomplete = angle

size instance-attribute

size: Incomplete = size

angles_catalyst instance-attribute

angles_catalyst: Incomplete = angles_catalyst

catalyst_state instance-attribute

catalyst_state: Incomplete

RotationCatalystStatePrep

RotationCatalystStatePrep(angle, size_of_catalyst_state, **kwargs: Any)

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"

angle instance-attribute

angle: Incomplete = angle

size_of_catalyst_state instance-attribute

size_of_catalyst_state: Incomplete = size_of_catalyst_state

compute

compute(ctrl: int = 0) -> None

Add

Add(**kwargs)

Bases: Qubrick

Basic adder.

compute

compute(dst, rhs, cond: int = 0) -> None

Compute dst += rhs, with optional conditions.

CompareEQ

CompareEQ(**kwargs)

Bases: Qubrick

Basic == (equality).

compute

compute(lhs: Qubits, rhs: Qubits | int)

Compute (lhs == rhs).

Parameters:

Name Type Description Default
lhs Qubits

Left-hand operand.

required
rhs Qubits | int

Right-hand operand.

required

CompareGE

CompareGE(restore_inputs: bool = False, **kwargs)

Bases: Qubrick

Basic Gidney >= (greater-than-or-equal).

restore_inputs instance-attribute

restore_inputs: Incomplete = restore_inputs

compute

compute(lhs: Qubits, rhs: Qubits | int | float)

Compute (lhs >= rhs).

Parameters:

Name Type Description Default
lhs Qubits

Left-hand operand

required
rhs Qubits or int or float

Right-hand operand

required

CompareGT

CompareGT(restore_inputs: bool = False, **kwargs)

Bases: Qubrick

Basic Gidney > (greater-than).

restore_inputs instance-attribute

restore_inputs: Incomplete = restore_inputs

compute

compute(lhs: Qubits, rhs: Qubits | int | float)

Compute (lhs > rhs).

Parameters:

Name Type Description Default
lhs Qubits

Left-hand operand.

required
rhs Qubits or int or float

Right-hand operand.

required

CompareLE

CompareLE(restore_inputs: bool = False, **kwargs)

Bases: Qubrick

Basic Gidney <= (less-than-or-equal).

restore_inputs instance-attribute

restore_inputs: Incomplete = restore_inputs

compute

compute(lhs: Qubits, rhs: Qubits | int | float)

Compute (lhs <= rhs).

Parameters:

Name Type Description Default
lhs Qubits

Left-hand operand.

required
rhs Qubits or int or float

Right-hand operand.

required

CompareLT

CompareLT(restore_inputs: bool = False, **kwargs)

Bases: Qubrick

Basic Gidney < (less-than).

restore_inputs instance-attribute

restore_inputs: Incomplete = restore_inputs

compute

compute(lhs: Qubits, rhs: Qubits | int | float)

Compute (lhs < rhs).

Parameters:

Name Type Description Default
lhs Qubits

Left-hand operand.

required
rhs Qubits or int or float

Right-hand operand.

required

CompareNE

CompareNE(**kwargs)

Bases: Qubrick

Basic != (inequality).

compute

compute(lhs: Qubits, rhs: Qubits | int)

Compute (lhs != rhs).

Parameters:

Name Type Description Default
lhs Qubits

Left-hand operand.

required
rhs Qubits | int

Right-hand operand.

required

CondInvert

CondInvert(**kwargs)

Bases: Qubrick

Basic ~ (bitwise inversion).

compute

compute(lhs: Qubits)

Compute ~lhs in-place.

Parameters:

Name Type Description Default
lhs Qubits

The register to invert.

required

CondXor

CondXor(**kwargs)

Bases: Qubrick

Basic XOR.

compute

compute(lhs: Qubits, rhs: Qubits)

Compute lhs = lhs ^ rhs.

Parameters:

Name Type Description Default
lhs Qubits

Left-hand operand of XOR.

required
rhs Qubits

Right-hand operand of XOR.

required

QFT

QFT(**kwargs)

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

Sqrt(**kwargs)

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(input_qreg: Qubits | QUInt)

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

AliasSampling(qrom: QROM, usp: UniformStatePreparation, **kwargs)

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.

{}

qrom instance-attribute

qrom: Incomplete = qrom

usp instance-attribute

usp: Incomplete = usp

compute_num_states staticmethod

compute_num_states(input_list)

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

compute(prep_reg, input_list, bit_precision, lambda_val=None, ctrl: int = 0, **kwargs) -> None

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 (default), then optimal lambda is calculated.

None
ctrl Qubits, SymbolicQubits, or int

Control register. Defaults to no control, i.e. ctrl=0.

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:

  1. If you know p_succ exactly a priori, you can realize the good state deterministically following the procedure in "Quantum Amplitude Amplification and Estimation" (arXiv:quant-ph/0005055 ⧉).
  2. 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 as p_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 determine p_succ exactly.
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 (vanilla).

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 1e-3.

0.001
use_radians bool

(Deprecated) True if angles in Radians.

False
**kwargs dict[str, Any]

Other arguments to pass to the init.

{}

init_refl instance-attribute

init_refl: Incomplete = init_refl

good_refl instance-attribute

good_refl: Incomplete = good_refl

eps instance-attribute

eps: Incomplete = eps

fixed_point instance-attribute

fixed_point: Incomplete = fixed_point

use_radians instance-attribute

use_radians: Incomplete = use_radians

compute

compute(sys_reg: Qubits, p_succ: float, ctrl: int | Qubits = 0, **kwargs)

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 fixed_point is set in the initalizer, this can be a lower bound on the success probability, if not it must be the exact success probability.

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.

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 1e-3.

0.001
use_radians bool

(Deprecated) True if angles in Radians.

False
**kwargs dict[str, Any]

Other arguments to pass to the init.

{}

base_qubrick instance-attribute

base_qubrick: Incomplete = base_qubrick

use_radians instance-attribute

use_radians: Incomplete = use_radians

amp_amp instance-attribute

amp_amp: Incomplete = AmpAmp(init_refl, good_refl, fixed_point=fixed_point, eps=eps, use_radians=use_radians)

compute

compute(sys_reg: Qubits, p_succ: float, ctrl: int | Qubits = 0, **kwargs)

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 fixed_point is set in the initalizer, this can be a lower bound on the success probability, if not it must be the exact success probability.

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

GoodReflectionBlockEncoding(**kwargs)

Bases: Qubrick

Reflection about a block encoded good state (i.e., all block encoding auxiliary qubits in \(\ket{0}\)).

Implements the reflection

\[(I - (1 - e^{i\phi})|0^m\rangle\langle 0^m|)\]
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(sys_reg: Qubits, ancillae: Qubits, angle: float = 180, ctrl: int | Qubits = 0, **kwargs)

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

GoodReflectionGrover(good_state: str, **kwargs)

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.

{}

good_state instance-attribute

good_state: Incomplete = good_state

compute

compute(sys_reg: Qubits, angle: float, 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.

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

GroverDiffuser(**kwargs)

Bases: Qubrick

Qubrick for Grover diffuser (reflection about the mean).

compute

compute(sys_reg: Qubits, angle: float = 180, 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
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

InitReflectionBlockEncoding(unitary, **kwargs)

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.

{}

unitary instance-attribute

unitary: Incomplete = unitary

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

InitReflectionFromUnitary(unitary, **kwargs)

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.

{}

unitary instance-attribute

unitary: Incomplete = unitary

compute

compute(sys_reg: Qubits, angle: float = 180, 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
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

Antisymmetrizer(prep_qbk, prob_knob=None, **kwargs)

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.

{}

bit_sort instance-attribute

bit_sort: Incomplete = BitonicSort()

prep_qbk instance-attribute

prep_qbk: Incomplete = prep_qbk

prob_knob instance-attribute

prob_knob: Incomplete = prob_knob

num_restarts instance-attribute

num_restarts: int = 0

compute

compute(system_reg: Qubits, ctrl: Qubits | int = 0)

Circuit for preparation of an antisymmetrized state.

The antisymmetrization procedure works as follows:

  1. We prepare an auxiliary "seed" register in an equal superposition state.
  2. We employ a sorting network on the seed register, keeping a record of all permutations made during the sort on another "record" register.
  3. 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.
  4. We apply Pauli Zs on each record qubit.
  5. 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.
  6. 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 ComputeHammingWeightGroupOfThrees with GidneyAdd will be used.

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.

n_hwp_batches instance-attribute

n_hwp_batches: Incomplete = n_hwp_batches

rot_is_rz instance-attribute

rot_is_rz: Incomplete = rot_is_rz

use_black_box instance-attribute

use_black_box: Incomplete = use_black_box

hamming_weight_qubrick property

hamming_weight_qubrick

Returns the Hamming weight qubrick used for computation.

Returns:

Type Description
Qubrick

The Hamming weight calculation Qubrick.

compute

compute(rz_rotation_angle: float, target_register: Qubits, ctrl: Qubits | int = 0)

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

LCU(state_prep: StatePreparation, select: Select, **kwargs: dict[str, Any])

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 (PREP) subroutine

required
select Select

A Qubrick implementing a select (SELECT) subroutine

required
**kwargs dict[str, Any]

Other arguments to pass to the init.

{}

state_prep instance-attribute

state_prep: Incomplete = state_prep

select instance-attribute

select: Incomplete = select

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 None.

0
**kwargs dict[str, Any]

Extra kwargs to maintain compatibility with other Qubricks.

{}

CompressionGadget

CompressionGadget(strategy: CompressionGadgetStrategy, adder: Qubrick = None, **kwargs)

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.

{}

adder instance-attribute

adder: Incomplete = adder if adder is not None else GidneyAdd()

strategy property

strategy

Set the strategy property so it can't be modified.

Returns:

Type Description
CompressionGadgetStrategy

The Compression gadget strategy.

compute

compute(system_reg, be_anc, idx_stop, idx_start: int = 0, counter=None, ctrl: int = 0) -> None

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.

{}

swap_up instance-attribute

swap_up: Incomplete = swap_up

select instance-attribute

select: Incomplete = select

fallback_read instance-attribute

fallback_read: Incomplete = fallback_read

symbolic_mode instance-attribute

symbolic_mode: Incomplete = symbolic_mode

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:

  1. 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.

  2. 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.

  3. 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 (default), then optimal lambda is calculated.

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

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

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

DataLookupDirtyNaive(select, swap_up, **kwargs)

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.

{}

swap_up instance-attribute

swap_up: Incomplete = swap_up

select instance-attribute

select: Incomplete = select

compute

compute(index_reg, b, data, lambda_val=None, ctrl: int = 0, **kwargs) -> None

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 (default), then optimal lambda is calculated.

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

DataLookupDirtyOptimized(select, swap_up, **kwargs)

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.

{}

swap_up instance-attribute

swap_up: Incomplete = swap_up

select instance-attribute

select: Incomplete = select

compute

compute(index_reg, b, data, lambda_val=None, ctrl: int = 0, **kwargs) -> None

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 (default), then optimal lambda is calculated.

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

MultiplexedSparseDataLookup(inner_qrom, outer_qrom, adder=None, **kwargs)

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 GidneyAdd.

None
**kwargs dict[str, Any]

Other keyword arguments to pass to the constructor.

{}

inner_qrom instance-attribute

inner_qrom: Incomplete = inner_qrom

outer_qrom instance-attribute

outer_qrom: Incomplete = outer_qrom

adder instance-attribute

adder: Incomplete = adder

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.

None
outer_lambda_val int

Power-of-two knob to trade off between gates and qubits. Defaults to None.

None

UnaryQROM

UnaryQROM(**kwargs)

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 Qubrick superclass.

{}

is_unary instance-attribute

is_unary: bool = True

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.

0
clean Qubits | None

Qubits encoding the output data. If left as None, the register is allocated on the fly.

None

DysonSeriesLCU

DysonSeriesLCU(prepare, select, **kwargs)

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.

{}

prepare instance-attribute

prepare: Incomplete = prepare

select instance-attribute

select: Incomplete = select

compute

compute(register, data, ctrl: int = 0) -> None

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.

0

DysonSeriesPrepareBinary

DysonSeriesPrepareBinary(prepare=None, sort=None, usp=None, **kwargs)

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 t^k/k!.

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

prepare: Incomplete = prepare

sort instance-attribute

sort: Incomplete = BitonicSort() if sort is None else sort

usp instance-attribute

usp: Incomplete = USP() if usp is None else usp

compute

compute(register: DysonSeriesBinaryIndex, data, ctrl: int = 0)

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.

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

DysonSeriesPrepareUnary(prepare=None, sort=None, usp=None, **kwargs)

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 t^k/k!.

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

prepare: Incomplete = PrepareClockState() if prepare is None else prepare

sort instance-attribute

sort: Incomplete = BitonicSort() if sort is None else sort

usp instance-attribute

usp: Incomplete = USP() if usp is None else usp

compute

compute(register: DysonSeriesUnaryIndex, data, ctrl: int = 0)

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.

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

DysonSeriesSelectBinary(strategy_cg: Qubrick, flag=None, adder=None, **kwargs)

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.

{}

strategy_cg instance-attribute

strategy_cg: Incomplete = strategy_cg

flag instance-attribute

flag: Incomplete = FlagCollisionsBinary() if flag is None else flag

adder instance-attribute

adder: Incomplete = NaiveAdd() if adder is None else adder

adder_cg instance-attribute

adder_cg: Incomplete = NaiveAdd() if adder is None else adder

compute

compute(register: CompositeRegister, data: DysonSeriesData, ctrl: Qubits | int = 0)

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.

0

DysonSeriesSelectUnary

DysonSeriesSelectUnary(fast_forward_exp, lcu, flag=None, **kwargs)

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.

{}

fast_forward_exp instance-attribute

fast_forward_exp: Incomplete = fast_forward_exp

lcu instance-attribute

lcu: Incomplete = lcu

flag instance-attribute

flag: Incomplete = FlagCollisionsUnary() if flag is None else flag

compute

compute(register: CompositeRegister, data: DysonSeriesData, ctrl: Qubits | int = 0)

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.

0

FlagCollisionsBinary

FlagCollisionsBinary(**kwargs)

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

compute(discret_reg: Qubits, trunc_reg: Qubits, ctrl: Qubits | int = 0)

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.

0
Note on convention

The resulting register, flag, stores 1 if at least one collision occured, 0 otherwise.

FlagCollisionsUnary

FlagCollisionsUnary(**kwargs)

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

compute(discret_reg: Qubits, trunc_reg: Qubits, ctrl: Qubits | int = 0)

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.

0
Note on convention

The resulting register, flag, stores 1 if at least one collision occured, 0 otherwise.

Rz

Rz(**kwargs)

Bases: Qubrick

Implementation of a direct Rz rotation using the built-in rz method.

This provides a simple interface for rotations that wraps the native rz gate.

compute

compute(rotation_encoding: Qubits | float, target_reg: Qubits, ctrl: Qubits | int = 0)

Compute the Qubrick.

Parameters:

Name Type Description Default
rotation_encoding Qubits | float

Rotation angle, either as a Qubits register or as a number in degrees.

required
target_reg Qubits

The register to apply rotation to.

required
ctrl Qubits | int

Control register.

0

RzAdder

RzAdder(adder: Adder = None, **kwargs)

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.

{}

adder instance-attribute

adder: Incomplete = adder

compute

compute(rotation_encoding: Qubits | float, target_reg: Qubits, ctrl: Qubits | int = 0)

Compute the Qubrick.

Parameters:

Name Type Description Default
rotation_encoding Qubits | float

Rotation angle, either as a Qubits register or as a number in degrees.

required
target_reg Qubits

The register to apply rotation to.

required
ctrl Qubits | int

Control register.

0

ComputeHammingWeightBinaryRecursion

ComputeHammingWeightBinaryRecursion(adder=None, **kwargs)

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.

{}

adder instance-attribute

adder: Incomplete = adder

anc_counter instance-attribute

anc_counter: int = 0

compute

compute(target_register: Qubits, ctrl: Qubits | int = 0)

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

This allocates a quantum register storing the Hamming weight.

ComputeHammingWeightGroupOfThrees

ComputeHammingWeightGroupOfThrees(use_black_box: bool = False, **kwargs)

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 ⧉).

anc_counter instance-attribute

anc_counter: int = 0

use_black_box instance-attribute

use_black_box: Incomplete = use_black_box

compute

compute(target_register: Qubits, ctrl: Qubits | int = 0)

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

ComputeHammingWeightNaive(adder=GidneyAdd(), **kwargs)

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.

{}

adder instance-attribute

adder: Incomplete = adder

compute

compute(target_register: Qubits, ctrl: Qubits | int = 0)

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

This allocates a new quantum register storing the Hamming weight.

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.

{}

use_black_box instance-attribute

use_black_box: Incomplete = use_black_box

hamming_weight_qubrick instance-attribute

hamming_weight_qubrick: Incomplete = hamming_weight_qubrick

use_catalyst_state instance-attribute

use_catalyst_state: Incomplete = use_catalyst_state

phasing_circuit instance-attribute

phasing_circuit: Incomplete = PhasingCircuit(_angle, use_black_box=use_black_box)

rot_is_rz instance-attribute

rot_is_rz: Incomplete = rot_is_rz

catalyst_state_reg instance-attribute

catalyst_state_reg: Incomplete = catalyst_state_reg

use_padding instance-attribute

use_padding: Incomplete = use_padding

angle property writable

angle

Angle specifying the angle of the rotations.

compute

compute(target_register: Qubits, ctrl: Qubits | int = 0)

Implement a stack of rotations using Hamming weight phasing.

Parameters:

Name Type Description Default
target_register Qubits

The register on which to apply the rotations.

required
ctrl int or Qubits

Control register.

0

PhasingCircuit

PhasingCircuit(base_angle, rot_is_rz: bool = False, use_black_box: bool = False, **kwargs)

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.

{}

rot_is_rz instance-attribute

rot_is_rz: Incomplete = rot_is_rz

counter instance-attribute

counter: int = 0

use_black_box instance-attribute

use_black_box: Incomplete = use_black_box

base_angle property writable

base_angle

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.

compute_subblock

compute_subblock(top, mid, bottom)

Compute half-adder-like block.

LKSMultiplexor

LKSMultiplexor(qrom, gate, **kwargs)

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.

{}

qrom instance-attribute

qrom: Incomplete = qrom

gate instance-attribute

gate: Incomplete = gate

compute

compute(index_reg, tgt, angles, bits_of_precision, lambda_val=None, **kwargs) -> None

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 (default), then optimal lambda is calculated and the clean decomposition will be used.

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:

\[\text{angle} = \frac{\frac{2\pi a_k}{2^{k + 1}}}{2} \times \frac{180}{\pi} = \frac{180 a_k}{2^{k + 1}}\]

LKSStatePrep

LKSStatePrep(coeffs, mplxr, **kwargs)

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.

{}

coeffs instance-attribute

coeffs: Incomplete = coeffs

mplxr instance-attribute

mplxr: Incomplete = mplxr

angles instance-attribute

angles: Incomplete

compute

compute(qbits, **mplxr_kwargs) -> None

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 None, then optimal lambda is calculated and the clean decomposition will be used.

MajoranaFermionOperator

MajoranaFermionOperator(operator, multiplexor_cls, **kwargs)

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 x or y method of a QPU instance.

required
multiplexor_cls Qubrick

The class for a Qubrick that implements multiplexing.

required
**kwargs dict[str, Any]

Additional Qubrick kwargs.

{}

operator instance-attribute

operator: Incomplete = operator

multiplexor instance-attribute

multiplexor: Incomplete = multiplexor_cls()

compute

compute(index_reg: Qubits, target_reg: Qubits, ctrl: Qubits | int = 0)

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 which performs the operation as if a control qubit were in the |1> state.

0

MultiplexedAliasSampling

MultiplexedAliasSampling(multiplexed_usp, multiplexed_qrom, **kwargs)

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:

  1. Superposition preparation:

    • MultiplexedUSP is 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.
  2. Computing alt and keep values:

    • We calculate the alt and keep values for each set of coefficients.
    • The size of the alt register is buffered to fit the largest value for all states in superposition.
    • This is managed by bit-shifting the keep values by this maximum value, similar to regular alias sampling.
  3. Multiplexor of multiplexors:

    • We load the alt and keep values in superposition using the construction from "Quantum computing enhanced computational catalysis" (arXiv:2007.14460 ⧉).
  4. Partitioning QROM output:

    • The multiplexed QROM output is partitioned into alt and keep registers.
  5. Creating a coin flip state:

    • Hadamards are applied to create a uniform superposition in the coin flip register.
  6. Conditional swapping:

    • A comparator checks whether coin_toss_reg is less than keep_reg.
    • If true, the input prep_reg is swapped with alt_reg.
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.

{}

multiplexed_usp instance-attribute

multiplexed_usp: Incomplete = multiplexed_usp

multiplexed_qrom instance-attribute

multiplexed_qrom: Incomplete = multiplexed_qrom

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 d values loaded in for computing the multiplexed USP.

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.

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.

None

Contiguizer

Contiguizer(**kwargs)

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(target_reg: Qubits, ctrl: Qubits | int = 0)

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 (no control).

0

MultiplexedRealUSP

MultiplexedRealUSP(multiplexor=None, contiguizer=None, **kwargs)

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 Contiguizer.

None
multiplexor Qubrick

Qubrick class to perform the multiplexing. Defaults to ZeroAncMultiplexor.

None
**kwargs dict[str, Any]

Other arguments to pass to the init.

{}

contiguizer instance-attribute

contiguizer: Incomplete = contiguizer

multiplexor instance-attribute

multiplexor: Incomplete = multiplexor

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:

\[\tfrac{1}{\sqrt{2}}(|0\rangle + |1\rangle)_{ind}\]

Then loading the data into the data_reg using QROM will yield the following state:

\[\tfrac{1}{\sqrt{2}}(|0\rangle_{ind}|2\rangle_{data} + |1\rangle_{ind}|3\rangle_{data})\]

And the goal of multiplexed USP is to prepare the multiplexed state

\[\tfrac{1}{\sqrt{2}} \left(|0\rangle_{ind}|2\rangle_{data} \tfrac{1}{\sqrt2} (|0\rangle + |1\rangle)_{target} + |1\rangle_{ind}|3\rangle_{data}\tfrac{1}{\sqrt3} (|0\rangle + |1\rangle + |2\rangle)_{target} \right)\]

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 d for the USP calls loaded in superposition.

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, in which case, it is allocated by the Qubrick.

None
succ_reg Qubits

Qubit to herald success. Defaults to None, in which case, it is allocated by the Qubrick.

None
error_param float or int

Parameter determining the accuracy of truncated rotation angles. If None (default), angles are exact and no success qubit is output.

None
ctrl Qubits or int

Optional register to control on. Defaults to 0 (no control).

0
Note

The effect of setting various default args has not been tested.

MultiplexedUSP

MultiplexedUSP(multiplexor=None, contiguizer=None, **kwargs)

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.

{}

contiguizer instance-attribute

contiguizer: Incomplete = contiguizer

multiplexor instance-attribute

multiplexor: Incomplete = multiplexor

compute

compute(psi, index_reg, data_reg=None, data=None, ctrl: int = 0, data_bits=None) -> 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:

\[\tfrac{1}{\sqrt{2}}(|0\rangle + |1\rangle)_{ind}\]

Then loading the data into the data_reg using QROM will yield the following state:

\[\tfrac{1}{\sqrt{2}}(|0\rangle_{ind}|2\rangle_{data} + |1\rangle_{ind}|3\rangle_{data})\]

And the goal of multiplexed USP is to prepare the multiplexed state

\[\tfrac{1}{\sqrt{2}} \left(|0\rangle_{ind}|2\rangle_{data} \tfrac{1}{\sqrt2} (|0\rangle + |1\rangle)_{target} + |1\rangle_{ind}|3\rangle_{data}\tfrac{1}{\sqrt3} (|0\rangle + |1\rangle + |2\rangle)_{target} \right)\]

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 d for the USP calls loaded in superposition.

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 (no control).

0
data_bits Qubits

Deprecated argument name for data_reg.

None
Note

The effect of setting various default args has not been tested.

BinaryTreeMultiplexor

BinaryTreeMultiplexor(**kwargs)

Bases: Qubrick

Optimized multiplexing based on Fig. 7 in "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).

index_reg instance-attribute

index_reg: Incomplete

multiplex_function instance-attribute

multiplex_function: Incomplete

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:

  1. There is no data to load (exit the routine).
  2. Loading a single item does not require this hefty machinery.
  3. Loading two items without a control is similarly cheap to the single-item-case.
  4. Loading n > 2 items without a control.
  5. 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

ConditionallyCleanMultiplexor(name=None, **kwargs)

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

OneAncMultiplexor(**kwargs)

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.

{}

basis_transformation instance-attribute

basis_transformation: Incomplete = basis_transformation

compute

compute(index_reg, target_reg, rotation_specs, config, ctrl: int = 0) -> None

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, in which case this routine has no control.

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.

{}

rot_qbk instance-attribute

rot_qbk: Incomplete = rot_qbk

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:

  1. All rotations must use the same rotation Qubrick.
  2. 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.

{}

rot_qbk instance-attribute

rot_qbk: Incomplete = rot_qbk

adder instance-attribute

adder: Incomplete = adder

qrom instance-attribute

qrom: Incomplete = qrom

bin_to_unary instance-attribute

bin_to_unary: Incomplete = BinaryToUnaryComputation()

first_qrom instance-attribute

first_qrom: Incomplete = deepcopy(qrom)

unary_index_reg instance-attribute

unary_index_reg: Incomplete

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:

  1. All rotations must use the same rotation Qubrick.
  2. 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 mux_data is not provided or contains invalid specifications.

GivensPPRs

GivensPPRs(**kwargs)

Bases: Qubrick

Applies the Givens rotation using Pauli Product Rotations.

This method implements the unitary:

\[ G(\theta) = e^{-i\frac{\theta}{2} (\mathbf{Y} \otimes \mathbf{X} - \mathbf{X} \otimes \mathbf{Y})} \]

which is equivalent to applying two single-qubit rotations, one with \( +\theta \) and the other with \( -\theta \).

compute

compute(rotation_encoding: float, target_reg: Qubits, ctrl: Qubits | int = 0) -> None

Apply the Givens rotation using Pauli Product Rotations.

Parameters:

Name Type Description Default
rotation_encoding float

Rotation angle in degrees.

required
target_reg Qubits

Two qubits to apply the rotation to.

required
ctrl Qubits | int

Control qubit (default: 0).

0

GivensRZs

GivensRZs(**kwargs)

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:

\[ G(\theta) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos(\theta) & \sin(\theta) & 0 \\ 0 & -\sin(\theta) & \cos(\theta) & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \]

This transformation can be decomposed into single-qubit RZ gates with Clifford conjugation:

  1. Apply a Clifford pre-rotation to transform the computational basis.
  2. Perform controlled RZ gates to introduce the phase shift.
  3. 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 Qubrick.

{}

compute

compute(rotation_encoding: float, target_reg: Qubits, ctrl: Qubits | int = 0) -> None

Apply the Givens rotation using Rz gates and Clifford basis change rotations.

Parameters:

Name Type Description Default
rotation_encoding float

Rotation angle in degrees.

required
target_reg Qubits

Two qubits to apply the rotation to.

required
ctrl Qubits | int

Control qubit (default: 0).

0

GivensRotationFusedAdder

GivensRotationFusedAdder(adder: Adder | None = None, **kwargs)

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 GidneyAdd(), but can be replaced with NaiveAdd() for alternative implementations.

None
**kwargs dict[str, Any]

Additional arguments passed to Qubrick.

{}

adder instance-attribute

adder: Incomplete = adder

compute

compute(rotation_encoding: Qubits, target_reg: Qubits, ctrl: Qubits | int = 0) -> None

Apply the Givens rotation using phase gradient addition with a single fused adder.

Parameters:

Name Type Description Default
rotation_encoding Qubits

Rotation angle in degrees.

required
target_reg Qubits

Two qubits to apply the rotation to.

required
ctrl Qubits | int

Control qubit (default: 0).

0

GivensRotationTwoAdders

GivensRotationTwoAdders(adder: Adder | None = None, **kwargs)

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 GidneyAdd(), but can be replaced with NaiveAdd() for alternative implementations.

None
**kwargs dict[str, Any]

Additional arguments passed to Qubrick.

{}

adder instance-attribute

adder: Incomplete = adder

compute

compute(rotation_encoding: Qubits, target_reg: Qubits, ctrl: Qubits | int = 0) -> None

Apply the Givens rotation using phase gradient addition with two adders.

Parameters:

Name Type Description Default
rotation_encoding Qubits

Rotation angle in degrees.

required
target_reg Qubits

Two qubits to apply the rotation to.

required
ctrl Qubits | int

Control qubit (default: 0).

0

SawtoothMultiplexor

SawtoothMultiplexor(max_index=None, **kwargs)

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

\[\text{SELECT}|l\rangle|\psi\rangle \rightarrow |l\rangle f(l)|\psi\rangle\]

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.

{}

max_index instance-attribute

max_index: Incomplete = max_index

index_reg instance-attribute

index_reg: Incomplete

set_max_index

set_max_index(index_val) -> None

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:

  1. There is no data to load (exit the routine).
  2. Loading a single item does not require this hefty machinery.
  3. Loading two items without a control is similarly cheap to the single-item-case.
  4. 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

ZeroAncMultiplexor(**kwargs)

Bases: Qubrick

Most naïve version of multiplexing possible.

For some function \(f\) which returns an operator associated with an integer index performs

\[\text{SELECT}|l\rangle|\psi\rangle \rightarrow |l\rangle f(l)|\psi\rangle\]

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

ArbitraryStatePrep(amps, multiplexor=None, **kwargs)

Bases: Qubrick

State preparation based on the routine in "Transformation of quantum states using uniformly controlled rotations" (arXiv:quant-ph/0407010 ⧉).

Realizes:

\[ \text{PREP}\ket{0} = \frac{\sum_i a_i}{\sum_i|a_i|^2}\ket{i} \]
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 NaiveMultiplexedRotations().

None
amps list or None

List of amplitudes to load into state.

required
**kwargs dict[str, Any]

Other arguments to pass to the init.

{}

multiplexor instance-attribute

multiplexor: Incomplete = multiplexor

amps instance-attribute

amps: Incomplete = amps

complex_amps instance-attribute

complex_amps: Incomplete

set_angles

set_angles(y_angles, z_angles=None) -> None

Set angles if none computed. Z angles defaults to None.

compute

compute(qbits, ctrl: int = 0, **kwargs) -> None

Compute the arbitrary state preparation circuit.

Parameters:

Name Type Description Default
qbits Qubits

Qubits to operate on.

required
ctrl Qubits or int

Register to control the on. Defaults to 0.

0
**kwargs dict[str, Any]

Other arguments to pass to the compute.

{}

EfficientMultiplexedRotations

EfficientMultiplexedRotations(gate=None, angles=None, **kwargs)

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.

{}

gate instance-attribute

gate: Incomplete = gate

angles instance-attribute

angles: Incomplete = angles

set_gate

set_gate(gate) -> None

Choose which unitary to multiplex (qc.op function).

set_angles

set_angles(angles) -> None

Choose angles for multiplexed unitaries (list).

compute

compute(index_reg, tgt, ctrl: int = 0, **kwargs) -> None

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.

0
**kwargs dict[str, Any]

Other arguments to pass to the compute.

{}

NaiveMultiplexedRotations

NaiveMultiplexedRotations(gate=None, angles=None, **kwargs)

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.

{}

gate instance-attribute

gate: Incomplete = gate

angles instance-attribute

angles: Incomplete = angles

set_gate

set_gate(gate) -> None

Choose which unitary to multiplex (qc.op function).

set_angles

set_angles(angles) -> None

Choose angles for multiplexed unitaries (list).

compute

compute(index_reg, tgt, ctrl: int = 0, **kwargs) -> None

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.

0
**kwargs dict[str, Any]

Other arguments to pass to the compute.

{}

PrepareNaive

PrepareNaive(coeffs, multiplexor=None, **kwargs)

Bases: Qubrick

State preparation based on the routine in "Transformation of quantum states using uniformly controlled rotations" (arXiv:quant-ph/0407010 ⧉).

Realizes:

\[\text{PREP}\ket{0} = \frac{\sum_i \sqrt{a_i}}{\sum_i|a_i|}\ket{i}\]
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 NaiveMultiplexedRotations().

None
coeffs list or None

List of coefficients to load into state.

required
**kwargs dict[str, Any]

Other arguments to pass to the init.

{}

multiplexor instance-attribute

multiplexor: Incomplete = multiplexor

coeffs instance-attribute

coeffs: Incomplete = coeffs

y_angles instance-attribute

y_angles: Incomplete

set_angles

set_angles(y_angles) -> None

Set angles if none computed.

compute

compute(qbits, ctrl: int = 0, **kwargs) -> None

Compute the state preparation circuit.

Parameters:

Name Type Description Default
qbits Qubits

Qubits to operate on.

required
ctrl (Qubits, int)

A register to control this operation on. Default to 0.

0
**kwargs dict[str, Any]

Other arguments to pass to the compute.

{}

BitonicPermutation

BitonicPermutation(**kwargs)

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 target_reg.

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

PhaseGradientAdder(**kwargs)

Bases: Qubrick

Optimized adder for use in phase gradient addition.

Parameters:

Name Type Description Default
**kwargs dict[str, Any]

Keyword arguments

{}

compute

compute(lhs: QUInt, rhs: QUInt, ctrl: Qubits | None = None)

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 None when rhs is a single qubit and the implicit one-qubit catalyst is dropped.

required
rhs QUInt

The register we are adding into the phase gradient register.

required
ctrl (Optional, int | Qubits)

Control register. Defaults to 0 (i.e. no control).

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 rhs two qubits and lhs one qubit shorter than rhs, the Fig.~13 chain collapses to three bilinear gates (no temporary elbow). With no adder control, those are lhs.z(rhs[0]), lhs.x(rhs[0]), rhs[1].z(). With a control register ctrl (e.g. bidirectional rotation tests), merge ctrl into each gate as lhs[0].z(rhs[0] | ctrl), lhs[0].x(rhs[0] | ctrl), rhs[1].z(cond=ctrl).
  • For lhs and rhs both a single qubit, only the closing segment remains (matching GidneyAdd on one-qubit lhs).

NaivePhaseGradient

NaivePhaseGradient(**kwargs)

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

PrepareClockState(**kwargs)

Bases: Qubrick

Prepares a clock state.

\[\text{PREP}|0\rangle^{\otimes n} = \sum_{k=0}^n \sqrt{p_k} |1\rangle^{\otimes k} |0\rangle^{\otimes n - k}\]
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

compute(target, probs, ctrl: int = 0) -> None

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

PrepareWState(khot_prep=None, wpower2_prep=None, **kwargs)

Bases: Qubrick

Prepares a W state.

\[\text{PREP}|0\rangle^{\otimes n} = \sum_{k=1}^n |0\rangle^{\otimes k-1}|1\rangle|0\rangle^{\otimes n - k}\]
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.

{}

k_hot instance-attribute

k_hot: Incomplete = PrepareClockState() if khot_prep is None else khot_prep

wpower_two instance-attribute

wpower_two: Incomplete = PrepareWStatePowerTwo() if wpower2_prep is None else wpower2_prep

compute

compute(target: Qubits, ctrl: Qubits | int = 0)

Prepares a W state.

Parameters:

Name Type Description Default
target Qubits

Target qubits.

required
ctrl (Qubits, int)

Control register. Default to 0.

0

PrepareWStatePowerTwo

PrepareWStatePowerTwo(**kwargs)

Bases: Qubrick

Prepares a W state for power of two target size.

\[\text{PREP}|0\rangle^{\otimes 2^n} =\sum_{k=1}^{2^n} |0\rangle^{\otimes k-1}|1\rangle|0\rangle^{\otimes 2^n - k}\]
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.

compute

compute(target: Qubits, ctrl: Qubits | int = 0)

Prepares a W state for power-of-two target size.

Parameters:

Name Type Description Default
target Qubits

Target qubits.

required
ctrl (Qubits, int)

Control register. Default to 0.

0

CosineWindow

CosineWindow(adder: Adder | None = None, **kwargs)

Bases: Qubrick

Cosine window from "Effects of Cosine Tapering Window on Quantum Phase Estimation" (arXiv:2110.09590 ⧉).

adder instance-attribute

adder: Incomplete = adder

compute

compute(phase_reg: Qubits, ctrl: Qubits | int = 0, **kwargs)

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

RectWindow(**kwargs)

Bases: Qubrick

Rectangular/Dirichlet window. This is the default window function for the textbook QPE.

compute

compute(phase_reg: Qubits, ctrl: Qubits | int = 0, **kwargs)

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

SineWindow(**kwargs)

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

compute(target_reg, flag_reg, ctrl: int = 0, use_real_amps: bool = False, **kwargs) -> None

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

SineWindowPhaseCatalysis(**kwargs)

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

compute(target_reg: Qubits, flag_reg: Qubits, ctrl: Qubits | int = 0, **kwargs)

Computes sine window function via phase catalyst state.

Note

Needs a round of amplitude amplification.

SineWindowQubitEfficient

SineWindowQubitEfficient(**kwargs)

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 ⧉).

compute

compute(phase_reg: Qubits, ctrl: Qubits | int = 0, **kwargs)

Computes sine window function.

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.

{}

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_func options.
  • 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 emulator_func.

None
**kwargs dict[str, Any]

Other arguments to pass to the init.

{}

emulator_func instance-attribute

emulator_func: Incomplete = emulator_func

emulator_func_kwargs instance-attribute

emulator_func_kwargs: Incomplete = emulator_function_options or {}

modifies_state_vector_directly instance-attribute

modifies_state_vector_directly: bool = True

uncompute

uncompute() -> None

Override the default uncomputation.

compute

compute(phase_reg, psi, ctrl: int = 0, **kwargs) -> None

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

WindowStatePrep(amps, state_prep=None, **kwargs)

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.

{}

amps instance-attribute

amps: Incomplete = amps

state_prep instance-attribute

state_prep: Incomplete = ArbitraryStatePrep(amps=amps)

compute

compute(phase_reg: Qubits, ctrl: Qubits | int = 0, **kwargs)

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.

RectWindow()
**kwargs dict[str, Any]

Other arguments to pass to the init.

{}

bits_of_precision instance-attribute

bits_of_precision: Incomplete = bits_of_precision

unitary instance-attribute

unitary: Incomplete = unitary

window_func instance-attribute

window_func: Incomplete = window_func

window_kwargs instance-attribute

window_kwargs: Incomplete = window_kwargs or {}

compute

compute(psi, phase_reg, ctrl: int = 0, **unitary_kwargs) -> None

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 unitary qubrick.

{}
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.

{}

bits_of_precision instance-attribute

bits_of_precision: Incomplete = bits_of_precision

unitary instance-attribute

unitary: Incomplete = unitary

window_func instance-attribute

window_func: Incomplete = window_func

window_kwargs instance-attribute

window_kwargs: Incomplete = window_kwargs or {}

qft instance-attribute

qft: Incomplete

compute

compute(psi, phase_reg, be_ancilla_reg, ctrl: int = 0, **kwargs) -> None

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 None. Note that we don't need to control the Hadamards or the inverse QFT as they will cancel on the branch that the controlled unitaries aren't applied on.

0
kwargs dict[str, Any]

Any additional kwargs that need to be passed to the unitary qubrick.

{}

IterativeQPE

IterativeQPE(bits_of_precision, unitary, window_kwargs=None, window_func=RectWindow(), **kwargs)

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.

RectWindow()
**kwargs dict[str, Any]

Other arguments to pass to the init.

{}

bits_of_precision instance-attribute

bits_of_precision: Incomplete = bits_of_precision

unitary instance-attribute

unitary: Incomplete = unitary

window_kwargs instance-attribute

window_kwargs: Incomplete = window_kwargs or {}

window_func instance-attribute

window_func: Incomplete = window_func

compute

compute(psi, phase_reg, ctrl: int = 0, **unitary_kwargs) -> None

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 unitary qubrick.

{}
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_precision bit 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:

  1. 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.
  2. Inspecting the naive DoublePhaseKickbackQPE circuit, 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.

{}

unitary instance-attribute

unitary: Incomplete = unitary

bits_of_precision instance-attribute

bits_of_precision: Incomplete = bits_of_precision

window_func instance-attribute

window_func: Incomplete = window_func

window_kwargs instance-attribute

window_kwargs: Incomplete = window_kwargs or {}

qft instance-attribute

qft: Incomplete

compute

compute(psi, phase_reg, be_ancilla_reg, ctrl: int = 0, **kwargs) -> None

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 None. Note that we don't need to control the Hadamards or the inverse QFT as they will cancel on the branch that the controlled unitaries aren't applied on.

0
kwargs dict[str, Any]

Any additional kwargs that need to be passed to the unitary qubrick.

{}

QPE

QPE(bits_of_precision, unitary, window_kwargs=None, window_func=RectWindow(), **kwargs)

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.

RectWindow()
**kwargs dict[str, Any]

Other arguments to pass to the init.

{}

bits_of_precision instance-attribute

bits_of_precision: Incomplete = bits_of_precision

unitary instance-attribute

unitary: Incomplete = unitary

window_func instance-attribute

window_func: Incomplete = window_func

window_kwargs instance-attribute

window_kwargs: Incomplete = window_kwargs or {}

qft instance-attribute

qft: Incomplete

compute

compute(psi, phase_reg, ctrl: int = 0, **unitary_kwargs) -> None

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 unitary qubrick.

{}
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

Qubitization(block_encoding: Qubrick, **kwargs: dict[str, Any])

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.

{}

block_encoding instance-attribute

block_encoding: Incomplete = block_encoding

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.

0
**kwargs dict[str, Any]

Other arguments to pass to the compute.

{}

QubitizedWalkOperator

QubitizedWalkOperator(state_prep: Qubrick, select: Qubrick, **kwargs: dict[str, Any])

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.

{}

state_prep instance-attribute

state_prep: Incomplete = state_prep

select instance-attribute

select: Incomplete = select

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.

0
**kwargs dict[str, Any]

Other arguments to pass to the compute.

{}

BinaryTreeSelect

BinaryTreeSelect(**kwargs)

Bases: Qubrick

Optimized select from Fig. 7 in "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).

multiplexor instance-attribute

multiplexor: Incomplete = BinaryTreeMultiplexor(**kwargs)

compute

compute(index_reg: Qubits, target_reg: Qubits, data: PauliSum | list[int], ctrl: Qubits | int = 0)

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 PauliSum to load or a list of bitvalues to load.

required
ctrl Qubits | int

Control register. Defaults to 0.

0

ConditionallyCleanSelect

ConditionallyCleanSelect(**kwargs)

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.

multiplexor instance-attribute

multiplexor: Incomplete = ConditionallyCleanMultiplexor(**kwargs)

compute

compute(index_reg: Qubits, target_reg: Qubits, data: PauliSum | list[int], ctrl: Qubits | int = 0)

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 PauliSum to load or a list of bitvalues to load.

required
ctrl (int, Qubits)

Control register. Defaults to 0.

0

SawtoothSelect

SawtoothSelect(**kwargs)

Bases: Qubrick

Unoptimized select from Fig. 5 in "Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity" (arXiv:1805.03662 ⧉).

multiplexor instance-attribute

multiplexor: Incomplete = SawtoothMultiplexor(**kwargs)

compute

compute(index_reg: Qubits, target_reg: Qubits, data: PauliSum | list[int], ctrl: Qubits | int = 0)

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 PauliSum to load or a list of bitvalues to load.

required
ctrl Qubits | int

Control register. Defaults to 0.

0

SelectNaive

SelectNaive(**kwargs)

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

\[|l\rangle |\psi\rangle \rightarrow |l\rangle U_l|\psi\rangle\]

If the data to be loaded as given as a list of bit values \(data\), performs the transformation

\[|l\rangle |\psi\rangle \rightarrow |l\rangle |\psi + data_l\rangle\]

multiplexor instance-attribute

multiplexor: Incomplete = ZeroAncMultiplexor(**kwargs)

compute

compute(index_reg: Qubits, target_reg: Qubits, data: PauliSum | list[int], ctrl: Qubits | int = 0)

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 PauliSum to load or a list of bitvalues to load.

required
ctrl Qubits | int

Control register. Defaults to 0.

0

SelectOneAnc

SelectOneAnc(**kwargs)

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 ⧉).

multiplexor instance-attribute

multiplexor: Incomplete = OneAncMultiplexor(**kwargs)

compute

compute(index_reg: Qubits, target_reg: Qubits, data: PauliSum | list[int], ctrl: Qubits | int = 0)

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 PauliSum to load or a list of bitvalues to load.

required
ctrl Qubits | int

Control register. Defaults to 0.

0

BitonicSort

BitonicSort(**kwargs)

Bases: Qubrick

Qubrick for performing a bitonic sort on a list of qubits.

unsort

unsort(regs_list, ctrl: int = 0) -> None

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

compute(regs_list: list[Qubits], direction: int, ctrl: Qubits | int = 0)

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

BinaryToUnaryUncomputation(permutation_qbk=None, **kwargs)

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.

{}

permutation_qbk instance-attribute

permutation_qbk: Incomplete = permutation_qbk

compute

compute(index_reg: Qubits, target_reg: Qubits, reg_size: int, ctrl: Qubits | int = 0)

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

InjectOp(swap_up, op, **kwargs)

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.

{}

swap_up instance-attribute

swap_up: Incomplete = swap_up

op instance-attribute

op: Incomplete = op

compute

compute(index_reg: Qubits, target_reg: Qubits, reg_size: int, ctrl: Qubits | int = 0)

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

SwapUp(permutation_qbk=None, **kwargs)

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.

{}

permutation_qbk instance-attribute

permutation_qbk: Incomplete = permutation_qbk

compute

compute(index_reg: Qubits, target_reg: Qubits, reg_size: int, ctrl: Qubits | int = 0)

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

PauliSumTrotterStrategy(hamiltonian: PauliSum, trotter_order: int = None)

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

hamiltonian instance-attribute

hamiltonian: Incomplete = hamiltonian

trotter_order instance-attribute

trotter_order: Incomplete = trotter_order

apply_trotter_terms

apply_trotter_terms(factor, system, reverse: bool = False, ctrl: int = 0)

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 TrotterStrategy for applying Trotter terms.

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_order instance-attribute

trotter_order: Incomplete = trotter_order

trotter_strategy property

trotter_strategy

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 self.trotter_order set at instantiation.

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

RealUSP(**kwargs)

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, in which case, it is allocated by the Qubrick.

None
succ_reg Qubits

Qubit to herald success. Defaults to None, in which case, it is allocated by the Qubrick.

None
error_param float

Parameter determining the accuracy of truncated rotation angles. If None (default), angles are exact and no success qubit is output.

None
ctrl Qubits or int

Register to control the USP on. Defaults to 0.

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

USP(**kwargs)

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

compute(d, target_qreg, 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.

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 (default), angles are exact and no success qubit is output.

None
ctrl Qubits or int

Register to control the USP on. Defaults to None.

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

ZeroAncillaUSP(qc=None, **kwargs)

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

compute(d, target_qreg, ctrl: int = 0, **kwargs) -> None

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 None.

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

AbsoluteDisplacement(orthogonal_dot_product, vector_sub, rsqrt, **kwargs)

Bases: Qubrick

Qubrick for computing the reciprocal of the absolute value of the difference of two vectors.

Specifically, it computes

\[\frac{1}{|r_1 - r_2|} = \frac{1}{\sqrt{(x_1-x_2)^2 + (y_1-y_2)^2 + (z_1-z_2)^2}}\]
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

orthogonal_dot_product: Incomplete = orthogonal_dot_product

vector_sub instance-attribute

vector_sub: Incomplete = vector_sub

rsqrt instance-attribute

rsqrt: Incomplete = rsqrt

compute

compute(q_vec1, q_vec2, high_precision: bool = False) -> None

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

OrthogonalDotProduct(release_ancillae, square, add, **kwargs)

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.

{}

square instance-attribute

square: Incomplete = square

add instance-attribute

add: Incomplete = add

release_ancillae instance-attribute

release_ancillae: Incomplete = release_ancillae

compute

compute(q_vec: list[Qubits] | Qubits)

Compute circuit for squaring an n-component vector.

Parameters:

Name Type Description Default
q_vec Qubits or list[Qubits]

List of Qubits each storing a component of the vector or one big Qubits object with each component (ex. x | y | z).

required

VectorAddition

VectorAddition(add, subtract_condition: bool = False, **kwargs)

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.

{}

add instance-attribute

add: Incomplete = add

subtract_condition instance-attribute

subtract_condition: Incomplete = subtract_condition

result_qregs instance-attribute

result_qregs: Incomplete

compute

compute(q_vec1: list[Qubits], q_vec2: list[Qubits])

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

get_default_multiplex_function(target_reg, data)

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

get_multiplex_function_of_indexed_callables(target_reg, data)

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

BinaryToUnaryComputation(**kwargs) -> BinaryToUnaryUncomputation

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.