workbench_algorithms.experimental.utils
Subpackage imports for experimental utility packages in Workbench Algorithms.
AliasSamplingStatePrepDataProtocol
Bases: Protocol
Protocol for alias sampling state preparation data containers.
is_positive_real
property
Determines whether coefficients are all positive, real values.
probabilities
property
Converts coefficients to corresponding probabilities.
validate_inputs
Check that all input coefficients and types are valid for alias sampling.
trim_register_if_needed
Trim register to appropriate size if too many qubits were provided.
combined_data_list
Helper to combine data output by QROM in alias sampling.
NumericAliasSamplingStatePrepData
dataclass
NumericAliasSamplingStatePrepData(
coeffs: Iterable[float | complex],
bits_of_precision: int | None = None,
lambda_val: int | None = None,
error_param: int | None = None,
)
Numeric implementation of alias sampling state preparation data.
is_positive_real
property
Determines whether self.coeffs are all positive, real values.
probabilities
cached
property
Converts self.coeffs to the corresponding probabilities.
validate_inputs
Check that all input coefficients and types are valid for alias sampling.
trim_register_if_needed
Trim register to appropriate size if too many qubits were provided.
combined_data_list
Helper to combine data output by QROM in alias sampling.
SymbolicAliasSamplingStatePrepData
dataclass
SymbolicAliasSamplingStatePrepData(
coeffs: SymbolicArray,
bits_of_precision: Parameter | None = None,
lambda_val: Parameter | None = None,
error_param: Parameter | None = None,
)
Symbolic implementation of alias sampling state preparation data.
is_positive_real
property
Determines whether self.coeffs are all positive, real values.
probabilities
cached
property
Converts self.coeffs to the corresponding probabilities.
validate_inputs
Check that all input coefficients and types are valid for alias sampling.
trim_register_if_needed
Trim register to appropriate size if too many qubits were provided.
combined_data_list
Helper to combine data output by QROM in alias sampling.
ArbitraryStatePrepData
dataclass
StatePrepData
dataclass
Data for specifying an arbitrary state to prepare.
SupportedOps
Bases: Enum
Specifies which rotation ops the multiplexed rotations support.
alias_sampling_get_b_from_epsilon
alias_sampling_get_b_from_epsilon(
inputs: Iterable[float],
epsilon: float,
b_upper_bound: int = 1000,
return_theory_bound_and_actual_diff: bool = False,
) -> int | tuple[int, float, float]
Get the number of bits of precision needed for alias sampling to achieve an accuracy epsilon.
Finds the minimum bit precision required such that the 2-norm difference between the normalized input and its discretized version is below an epsilon threshold.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
Iterable[float]
|
Input list of values to be normalized and discretized. |
required |
epsilon
|
float
|
Threshold for acceptable 2-norm difference. |
required |
b_upper_bound
|
int
|
Maximum bit precision to search. Default is 1000. |
1000
|
return_theory_bound_and_actual_diff
|
bool
|
a boolean the user to set if they want to return the theory bound and actual l2-norm difference |
False
|
Returns:
| Type | Description |
|---|---|
tuple
|
(bit_precision, norm_diff) if a suitable precision is found. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no suitable bit precision is found within the range. |
alias_sampling_state_prep_data
alias_sampling_state_prep_data(
coeffs: Iterable[float | complex] | SymbolicArray,
bits_of_precision: int | Parameter | None = None,
lambda_val: int | Parameter | None = None,
error_param: int | Parameter | None = None,
) -> AliasSamplingStatePrepDataProtocol
Create appropriate alias sampling state prep data based on input type.
discretized_prob_distribution_improved
discretized_prob_distribution_improved(
probabilities_list: Iterable[float], bit_precision: int
) -> np.array
Discretizes a probability distribution while preserving the total sum using a rounding correction.
Warning: this function now takes the input parameter in the form of the probabilities (amplitude square) rather than the state vector. This is compatible with the implementation in the experimental branch, and will cause conflict with the original Alias Sampling implementation
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probabilities_list
|
Iterable[float]
|
List of non-negative values representing probabilities of coefficients (don't have to be normalized) |
required |
bit_precision
|
int
|
Number of bits to determine the number of discrete levels. |
required |
Returns:
| Type | Description |
|---|---|
array
|
Discretized values that sum to the expected total. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If input contains negative values. |
LKS_get_b_from_epsilon
LKS_get_b_from_epsilon(
inputs: Iterable[float],
epsilon: float,
b_upper_bound: int = 1000,
return_theory_bound_and_actual_diff: bool = False,
) -> int | tuple[int, float, float]
Get a numerically-optimized number of bits of precision for LKS state prep.
Finds the minimum bit precision such that the L2-norm difference between the normalized input and its discretized version is below a given epsilon threshold.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
epsilon
|
float
|
Acceptable L2-norm threshold. |
required |
inputs
|
Iterable[float]
|
Real or complex input values. |
required |
b_upper_bound
|
int
|
Max bit precision to check. |
1000
|
return_theory_bound_and_actual_diff
|
bool
|
Whether to return (bit_precision, theory_eps, actual_eps) |
False
|
Returns:
| Type | Description |
|---|---|
int | tuple[int, float, float]
|
Best bit precision, or (bit_precision, expected_eps, norm_diff) |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no suitable bit precision is found. |
compute_ry_angle_array
Calculate rotation angles needed to prepare an arbitrary pure state.
In particular, for a state \(\frac{e^{i \theta}}{\|a\|_2}\sum_i a_i \ket{i}\), with complex coefflitudes \(a_i\), where \(e^{i \theta}\) is the global phase and \(\|a\|_2\) is the two-norm, this function finds angles for rotations which prepare the magnitude component of each coefflitude in the state vector.
We follow equation 8 in arXiv:0407010.
Note
The output rotations are in degrees to coincide with the convention used elsewhere in Workbench.
Returns:
| Type | Description |
|---|---|
list[list[float]]
|
Nested list of \(Y\) rotation angles that prepare the magnitudes per term in the input target coefficients. |
Notes
- The reference above actually presents the calculation of these angles with the inverse goal of state preparation; assume you start in an arbitrary state, and now must apply specific-angle + axis rotations to return to the all-zero state.
- This function corresponds to equations in the text for determining angles meant to zero out the magnitudes of an input arbitrary superposition state.
- We simply return the reverse-order list of the angles we calculate.
compute_rz_angle_array
Calculate rotation angles needed to prepare an arbitrary pure state.
In particular, for a state \(\frac{e^{i \theta}}{\|a\|_2}\sum_i a_i \ket{i}\), with complex coefflitudes \(a_i\), where \(e^{i \theta}\) is the global phase and \(\|a\|_2\) is the two-norm, this function finds angles for rotations which prepare the phase component of each coefflitude in the state vector.
We follow equation 5 in arXiv:0407010.
Note: rotations default to degrees, as it is now used in all the implementations here
Returns:
| Type | Description |
|---|---|
tuple[list[list[float]], float]
|
We return a tuple with two different items:
- A nested list of \(Z\) rotation angles that prepare the correct
phases for each coefficient in |
Notes
- The reference above actually presents the calculation of these angles with the inverse goal of state preparation; assume you start in an arbitrary state, and now must apply specific-angle + axis rotations to return to the all-zero state.
- This function corresponds to equations in the text for determining angles meant to equalize the phases in an input arbitrary superposition state.
- We simply return the reverse-order list of the angles we calculate.
get_amp_array_from_angle_array
Takes a list of angles used in Grover-Rudolph state prep and converts them to a list of resulting amplitudes.
Compute amplitude array from a 2D list of angles qubit by qubit, in a tree-like structure. For each qubit layer, we grab the previous layer amps and calculate the cos and sin values parameterized by the current qubit layer angles, and put the two values for each of the angles in the current qubit layer's amp_list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
angles_2d_list
|
list[list[float]]
|
Each sublist represents angles for a qubit layer. |
required |
Returns:
| Type | Description |
|---|---|
list[float]
|
The last computed amplitude list. |
get_approximated_weight_using_angle_truncation_function
get_approximated_weight_using_angle_truncation_function(
weights: Iterable[float], b: int
) -> np.ndarray
Computes the approximated weight using angle truncation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
weights
|
Iterable[float]
|
Input weight values (real or complex). |
required |
b
|
int
|
Truncation precision for the rotation angle. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Approximated weight after angle truncation. |
pauli_rotation_helper
pauli_rotation_helper(
angle: float,
opcode: SupportedOps,
target_reg: Qubits,
ctrl: Qubits | int = 0,
)
Parses the specification of an op given by opcode to a QPU rotation op which is applied on target_reg.
ppr_to_rz_compute
PPR as standard gates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
qc
|
QPU
|
QPU instance. |
required |
x_qbits
|
Qubits | int
|
Qubit register where Pauli Xs act (or zero if none). |
required |
z_qbits
|
Qubits | int
|
Qubit register where Pauli Zs act (or zero if none). |
required |
ctrl
|
Qubits | int
|
Qubits register to control the ppr on. |
0
|
generate_complex_array
generate_complex_array(
n: int,
real_range: tuple[int, int] = (-1, 1),
imag_range: tuple[int, int] = (-1, 1),
random_number_generator: np.random.Generator
| None = None,
) -> np.ndarray
Generate an array of n complex numbers.
The array is generated with real and imaginary parts sampled from uniform distributions within specified ranges.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of complex numbers to generate. |
required |
real_range
|
tuple[int, int]
|
Range (min, max) for real parts. |
(-1, 1)
|
imag_range
|
tuple[int, int]
|
Range (min, max) for imaginary parts. |
(-1, 1)
|
random_number_generator
|
Generator | None
|
Generator for the random numbers. |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of complex numbers. |
l1_normalize
Normalize an input list with respect to the L1-orm of the elements.
l2_norm_diff
Computes the L2-norm (Euclidean distance) between two real or complex arrays.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
arr1
|
ndarray
|
First input array (real or complex). |
required |
arr2
|
ndarray
|
Second input array (real or complex). |
required |
Returns:
| Type | Description |
|---|---|
float
|
L2-norm distance between arr1 and arr2. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If array shapes don't match or types don't match. |
l2_normalize
l2_normalize(
input_list: Iterable[float],
allow_complex: bool = False,
eps: float = 1e-15,
) -> np.ndarray
Normalize a 1D array so that the sum of squares equals 1 (L2 norm).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_list
|
Iterable[float]
|
Input array |
required |
allow_complex
|
bool
|
Whether to allow complex numbers |
False
|
eps
|
float
|
Tolerance for zero norm |
1e-15
|
Returns:
| Type | Description |
|---|---|
ndarray
|
L2-normalized array |