Skip to content
Construct PsiQDK Workbench

Reference: Qubits Classes

Contents


Qubits

Qubits(num_qubits: int | None = None, name: str | None = None, qpu: QPU | None = None, overlay_offset: int | None = None, scatter: list[int] | None = None, cond_xor: int | None = 0, from_mask: int | None = None, cs_key: int | None = None, alloc_id: int | None = None, fallback_read: FallbackReadGenerator | None = None)

Bases: BaseQubits

Qubits is the base class for all qubit-based variables. Unlike classical bit-based variables, they may be any number of bits in length.

Qubits class has subclasses with high-level-language behaviors of quantum arithmetic data types:

  • QInt: Signed integer
  • QUInt: Unsigned integer
  • QFixed: Signed fixed-point (fractional) values
  • QUFixed: Unsigned fixed-point (fractional) values

When Qubits are used raw (just as type Qubits), they behave like unsigned integers. The gate count and behavior of arithmetic operations such as addition, multiplication and comparison are determined by the types.

For more details, see Quantum Arithmetic Data Types tutorial.

Qubits objects may be sliced and re-cast as needed to perform desired operations. For example:

  • a = b[-1]: get just the last (most significant) qubit
  • a = b[::-1]: endian-reversal (big-endian to little-endian or vice versa)
  • a = QUInt(b): change type to unsigned integer

Quantum gates generally should be performed on Qubits objects directly. For example, a.x() is preferred over qc.x(a).

Parameters:

Name Type Description Default
num_qubits int | None

Number of qubits to allocate. If zero or from_mask is 0, a zero-qubit register is created.

None
name str | None

Name for the qubit register, used in diagrams and labels.

None
qpu QPU | None

QPU instance to allocate the qubits from.

None
overlay_offset int | None

Deprecated and will be removed in WB 5.0.0; use scatter instead for specific qubit addresses.

None
scatter list[int] | None

Specifies specific qubit addresses that make up this object in order. Only used internally.

None
cond_xor int | None

Bits indicating conditional not-conditions for quantum control.

0
from_mask int | None

Global bits in the QPU for qubit addresses, overriding num_qubits. Only used internally.

None
cs_key int | None

If not None, associate a QubrickComputeState with this allocation. Only used internally.

None
alloc_id int | None

If not None, associate an allocation ID with this allocation. Only used internally.

None

Raises:

Type Description
ValueError

If trying to allocate negative or invalid number of qubits.

RuntimeError

If qpu is not specified.

fallback_read instance-attribute

fallback_read = fallback_read

op_flags instance-attribute

op_flags = 0

radix instance-attribute

radix = 0

num_qubits instance-attribute

num_qubits = num_qubits

name instance-attribute

name = name

qpu instance-attribute

qpu = qpu

cond_xor instance-attribute

cond_xor = cond_xor

cs_key instance-attribute

cs_key = cs_key

alloc_id instance-attribute

alloc_id = alloc_id

identifier property

identifier: int

Returns the unique identifier for Qubits class, a mask representing the qubits relative to the QPU instance (same as mask()).

is_signed property

is_signed

is_fixed property

is_fixed

check_value_fits_in_type

check_value_fits_in_type(value: int | float, do_warning: bool = True) -> bool

Check if the provided value can fit within the number of qubits available in the current register without overflow.

For example
  • The number 100 won't fit in a 4-qubit register.
  • The number 250 fits in an 8-qubit QUInt, but not in an 8-qubit QInt, since the sign bit takes up one of the qubits.
Notes
  • These checks do not inspect the state vector for actual zero values; they only consider the register size and type to determine if the value can fit.
  • Special case: For a 1-qubit QInt register (using 2's complement), only the values 0 and -1 are technically representable, but 1 is also allowed, as it is generally expected with a 1-qubit register.
  • For QFixed and QUFixed, approximate values (e.g., 0.1) will return True if they fit within the qubit capacity, even if they cannot be represented precisely.

Parameters:

Name Type Description Default
value int or float

The value to be checked.

required
do_warning bool

If True, issue a warning if the value does not fit. Defaults to True.

True

Returns:

Type Description
bool

True if the Qubits register can represent the value without overflow.

coerce_value

coerce_value(value: int | float, do_warning: bool = True) -> int | float

Convert a value to this type, and warn if it's not exact.

Parameters:

Name Type Description Default
value int or float

The value to be converted.

required
do_warning bool

If True, issue a warning if the value does not fit. Defaults to True.

True

qubit_indices

qubit_indices()

Get the indices of the qubits in the register.

Returns:

Type Description
tuple

Indices of the qubits in this register.

pull_state

pull_state(normalize: bool = True) -> np.ndarray

Pull the quantum state of the qubit register as a state vector directly from the full system state.

This method extracts the pure quantum state of a register from the full statevector when the register is not entangled with the rest of the system (the environment).

If the state of the register is entangled with the rest of the system, this function returns a normalized verison of the most populated state vector, with the most non-zero amplitudes for the given register among the other states in the system.

Mathematical Background

The global state can be assumed to be of the form:

\[ |\Psi\rangle = \sum_{i,j} c_{ij} \, |i\rangle_R \otimes |j\rangle_E \]

Here:

  • \(|i\rangle_R\) are basis states of the register,
  • \(|j\rangle_E\) are basis states of the environment (all other qubits),
  • \(c_{ij}\) are complex amplitudes in the full statevector.

If the system is in a product state, then all its amplitudes factor as \(c_{ij} = \alpha_i \beta_j\), and the state can be represented as follows:

\[ |\Psi\rangle = \left(\sum_i \alpha_i |i\rangle_R\right) \otimes \left(\sum_j \beta_j |j\rangle_E\right) \]

This does not hold if the register is entangled with other register. In this case, the state vector of the register is not fully separable, there may be different state vectors for different environments.

This method:

  1. Iterates over each environment
  2. For each term in the register's state vector
  3. Finds the amplitude of the combination of the environment and register terms
  4. Determines the probability of the isolated register state vector in the overall state.
  5. Determines the register state vector with the greatest probability and the greatest number of non-zero amplitudes.

This yields the register's state vector (up to normalization) for the greatest probability state vector among environments in the system.

Parameters:

Name Type Description Default
normalize bool

Whether to normalize the returned state vector. Defaults to True (normalize it).

True

Returns:

Type Description
ndarray

A normalized complex vector of length \(2^n\) representing the quantum state of the register, where \(n\) is the number of qubits in the register. The returned state is correct up to a global phase, which means it may differ from the expected state by a complex phase factor \(e^{i\phi}\).

To correct the phase when comparing with an expected state, you can use:

def correct_phase(state, expected_state):
    inner_product = np.vdot(expected_state, state)  # np.vdot does complex conjugate of first arg
    global_phase = np.angle(inner_product)
    phase_correction = np.exp(-1j * global_phase)
    return state * phase_correction

# Then compare the corrected state
corrected_state = correct_phase(state, expected_state)
assert np.allclose(corrected_state, expected_state)

is_allocated

is_allocated() -> bool

Check if the qubits of this register are currently allocated on the QPU.

Returns:

Type Description
bool

True if the qubits are allocated, False otherwise.

allocate

allocate(qpu: QPU | None = None)

Allocate qubits on the QPU for this Qubits object.

Parameters:

Name Type Description Default
qpu QPU | None

The QPU instance on which to allocate the qubits. If not provided, uses the assigned QPU.

None

Raises:

Type Description
RuntimeError

If allocation fails or if qubits are already allocated.

release

release(clear_to_zero: bool = False) -> None

Release the qubits associated with this Qubits object.

This method frees the allocated qubits, making them available for other operations. Releasing is idempotent: multiple calls to release() will have no additional effect after the first successful release.

Parameters:

Name Type Description Default
clear_to_zero bool

If True, resets the qubits to the 0 state before release. Defaults to False.

False
Notes
  • Releasing qubits associated with an overlay or scatter does not clear them to zero, as these qubits are managed separately.
  • If this Qubits object was the initial owner of the allocated qubits, releasing will reset the ownership flags and nullify the address references.

set_random

set_random()

Set the qubits register to a random quantum state.

This method generates a random quantum state and sets the register to that state using push_state. The random state is generated using numpy's random number generator.

Note
  • The randomness is controlled by numpy's random seed. Use np.random.seed(seed) or qc.random_seed(seed) to set a specific seed for reproducibility.

push_state

push_state(state_vector, normalize=True)

Push a quantum state to the qubits register.

This method uses a native optimized implementation to push the state. The destination register's qubits must be consecutively allocated in the QPU (this is the case by default with most Qubits objects).

Note

The qubits register is reset to |0⟩ before the state vector is pushed to it.

Parameters:

Name Type Description Default
state_vector list or ndarray

A state vector describing the desired quantum state. Can be provided as a list or numpy array. The length must be \(2^n\), where \(n\) is the number of qubits in the register. Will be converted to a complex numpy array internally.

required
normalize bool

Whether to normalize the state vector. Defaults to True.

True

Raises:

Type Description
ValueError

If the destination register is scattered (non-consecutive) qubits.

ValueError

If the state vector dimensions don't match the register size.

nop

nop()

Perform a no-operation (NOP) on the associated QPU. Typically used for timing or alignment purposes.

Example:

```python
qubits = Qubits(num_qubits=4, qpu=qpu_instance)
qubits.nop()  # Executes a no-operation on the QPU
```

mask

mask(base_mask: int | None = None) -> int

Calculate and return the binary mask representing the qubits relative to the QPU instance.

Parameters:

Name Type Description Default
base_mask int

Base bitmask to apply to the qubits in this register. Defaults to ~0 (all qubits in the register).

None

Returns:

Type Description
int

The bitmask representing the active qubits in the register, adjusted according to base_mask.

Raises:

Type Description
ValueError

If the Qubits instance has been released or is otherwise inaccessible.

Example
qubits = Qubits(num_qubits=4, qpu=qpu_instance)
qubits_mask = qubits.mask()  # Gets the mask for the qubits

box

box(label='', tgt_bits=None, cond=None, cond_zip=None, cond_reg=None)

Apply a labeled box operation on the qubits in this register.

This method uses the box operation on the qubits specified by tgt_bits, with optional conditions. The box label can be used to create regions in quantum diagrams, showing where operations begin and end.

Parameters:

Name Type Description Default
label str

A label for the box to distinguish it in a diagram. Defaults to an empty string.

''
tgt_bits int, list, or None

Target bits within the register or None to apply a gate to each qubit in the register.

None
cond int

Control qubits register for applying the same condition to all targets.

None
cond_zip Qubits

Control qubits register for applying a series of conditional gates with different control-target pairs.

None
cond_reg Qubits

Deprecated and will be removed in WB 5.0.0. Use cond_zip instead.

None

box_open

box_open(label='', tgt_bits=None, cond=None, cond_zip=None, cond_reg=None)

Start a labeled box region on the qubits in this register.

The box_open method defines the beginning of a region in a quantum diagram, encapsulating multiple operations within the specified qubits. Conditional execution can be applied if required.

Parameters:

Name Type Description Default
label str

A label for the box to distinguish it in a diagram. Defaults to an empty string.

''
tgt_bits int, list, or None

Target bits within the register or None to apply a gate to each qubit in the register.

None
cond int

Control qubits register for applying the same condition to all targets.

None
cond_zip Qubits

Control qubits register for applying a series of conditional gates with different control-target pairs.

None
cond_reg Qubits

Deprecated and will be removed in WB 5.0.0. Use cond_zip instead.

None

box_close

box_close(label='', tgt_bits=None, cond=None, cond_zip=None, cond_reg=None)

End a labeled box region on the qubits in this register.

The box_close method marks the end of a previously opened box region in a quantum diagram, encapsulating multiple operations within the specified qubits. Conditional execution can be applied if required.

Parameters:

Name Type Description Default
label str

A label for the box to distinguish it in a diagram. Defaults to an empty string.

''
tgt_bits int, list, or None

Target bits within the register or None to apply a gate to each qubit in the register.

None
cond int

Control qubits register for applying the same condition to all targets.

None
cond_zip Qubits

Control qubits register for applying a series of conditional gates with different control-target pairs.

None
cond_reg Qubits

Deprecated and will be removed in WB 5.0.0. Use cond_zip instead.

None

swap

swap(target: Qubits, cond: int = 0, condition_mask: int = 0) -> None

Apply a SWAP operation between this qubits register and another specified target register.

Parameters:

Name Type Description Default
target Qubits

The target qubits register to swap states with.

required
cond int

Control qubits register. Defaults to None.

0
condition_mask int

Deprecated and will be removed in WB 5.0.0. Use cond instead.

0

Raises:

Type Description
ValueError

If the size of the current register does not match the target register.

peek_probability

peek_probability(value)

Alias for Qubits.peek_read_probability. Deprecated and will be removed in WB 5.0.0. Use Qubits.peek_read_probability instead.

peek_read_probability

peek_read_probability(value: int, stop_at: float = 0.0) -> float

Get the probability that reading this register will return the given value.

This function acts via a non-projective inspection of the statevector and does not change the statevector.

Parameters:

Name Type Description Default
value int

The value whose read probability is to be queried.

required
stop_at float

If the probability is greater than stop_at, return the value stop_at or greater as quickly as possible (used for zero-checking).

0.0

peek_max_value

peek_max_value(probability_threshold: float = 1e-10, flush: bool = True) -> float

Efficiently find the maximum value represented in the state vector with a non-zero probability.

Parameters:

Name Type Description Default
probability_threshold float

Consider probabilities below that value to be zero.

1e-10
flush bool

If True, flush the pipeline before reading the probability. Defaults to True.

True

peek_min_value

peek_min_value(probability_threshold=1e-10)

Efficiently find the minumum value represented in the state vector with a non-zero amplitude

Parameters:

Name Type Description Default
probability_threshold float

Consider probabilities below that value to be zero.

1e-10

postselect

postselect(value: int, target_mask: int | None = None) -> None

Collapse the state to terms with the desired value.

Parameters:

Name Type Description Default
value int

Desired "read" value of the register.

required
target_mask int or None

If specified, which bits to "read".

None

max_value

max_value() -> int

Get the maximum representable value for the qubit register.

This function returns the maximum integer value that can be represented by the qubits in this register.

Returns:

Type Description
int

The maximum value based on the number of qubits.

min_value

min_value() -> int

Get the minimum representable value for the qubit register.

This function returns the minimum integer value that can be represented by the qubits in this register.

Returns:

Type Description
int

The minimum representable value.

step_value

step_value() -> int

Get the step value for iterating over the qubit register values.

This function returns the step size for iterating or incrementing values within the range representable by this qubit register.

Returns:

Type Description
int

The step value.

read_async

read_async(target_mask: int = ~0)

Perform an asynchronous read of the qubit register.

This method starts an asynchronous read operation on the qubits specified by target_mask, allowing other operations to proceed before the read result is available.

Parameters:

Name Type Description Default
target_mask int

Mask specifying the qubits to read. Defaults to all qubits.

~0

Returns:

Type Description
AsyncReadResult

Placeholder for the asynchronous read result.

read

read(target_mask: int = ~0) -> int

Perform a synchronous read of the classical value from the qubit register.

This method reads a classical binary representation of the current quantum state of the qubit register as an integer value. Only qubits specified by the target_mask are read, with the remainder ignored.

Parameters:

Name Type Description Default
target_mask int

Mask to specify which qubits to read. Defaults to all qubits in the register.

~0

Returns:

Type Description
int

Integer representation of the qubits' classical state.

write

write(value: int, target_mask: int = ~0) -> None

Write a classical value to the qubit register.

This method writes a specified integer value, represented as a computational basis state, into this register.

Parameters:

Name Type Description Default
value int

The integer value to write to the qubits.

required
target_mask int

Mask specifying which qubits to write to. Defaults to all qubits.

~0

add

add(rhs, cond=0, subtract_condition=False, qubrick_type=None, condition_mask=0)

Perform addition on the qubit register with optional conditional control and custom Qubrick type.

Deprecated and will be removed in WB 5.0.0. Use -= or adder Qubricks instead.

This method adds the value represented by rhs to the current qubit register, optionally controlled by a condition mask, and with an option to use a custom Qubrick type for the addition operation.

Parameters:

Name Type Description Default
rhs Qubits | int

The value to be added to the register. If rhs is a Qubits object, it represents a quantum value; if rhs is an int, it represents a classical integer value.

required
cond int

Optional control mask specifying which qubits to use as conditions for the operation. Defaults to 0, meaning no control conditions.

0
subtract_condition bool

If True, the operation performs subtraction instead of addition. Defaults to False.

False
qubrick_type class or None

Specifies a custom Qubrick type to perform the addition operation. Defaults to None, which uses the adder specified by QPU for "+=" operator.

None
condition_mask int

Deprecated and will be removed in WB 5.0.0. Use cond instead.

0
Example
qreg.add(3)  # Adds 3 to the quantum register.
qreg.add(other_qreg, cond=0b101)  # Adds another register to `qreg` conditionally.

subtract

subtract(rhs, cond=0, qubrick_type=None, condition_mask=0)

Perform subtraction on the qubit register with optional conditional control and custom Qubrick type.

Deprecated and will be removed in WB 5.0.0. Use -= or adder Qubricks instead.

This method subtracts the value represented by rhs from the current qubit register, optionally controlled by a condition mask, and with an option to use a custom Qubrick type for the subtraction operation.

Parameters:

Name Type Description Default
rhs Qubits | int

The value to be subtracted from the register. If rhs is a Qubits object, it represents a quantum value; if rhs is an int, it represents a classical integer value.

required
cond int

Optional control mask specifying which qubits to use as conditions for the operation. Defaults to 0, meaning no control conditions.

0
qubrick_type class or None

Specifies a custom Qubrick type to perform the subtraction operation. Defaults to None, which uses the adder specified by QPU for "-=" operator.

None
condition_mask int

Deprecated and will be removed in WB 5.0.0. Use cond instead.

0
Example
qreg.subtract(2)  # Subtracts 2 from the quantum register.
qreg.subtract(other_qreg, cond=0b100)  # Conditionally subtracts another register from `qreg`.

add_squared

add_squared(rhs, cond=0, reverse_to_subtract=False, condition_mask=0)

Add the square of a specified value to the qubit register with optional control conditions.

Deprecated and will be removed in WB 5.0.0. Use += and Square Qubricks instead.

This method calculates the square of rhs and then adds (or subtracts, if specified) it to the qubit register. The operation can be controlled by a condition mask, and it supports both quantum values and classical integers as input for rhs.

Parameters:

Name Type Description Default
rhs Qubits | int

The value to square and add to the register. If rhs is a Qubits object, the square of its quantum value is added; if rhs is an int, the square of the integer is added.

required
cond int

Optional control mask specifying which qubits to use as conditions for the operation. Defaults to 0, meaning no control conditions.

0
reverse_to_subtract bool

If True, the squared value of rhs is subtracted from the register. Defaults to False.

False
condition_mask int

Deprecated and will be removed in WB 5.0.0. Use cond instead.

0
Example
qreg.add_squared(3)  # Adds 9 (3^2) to the quantum register
qreg.add_squared(other_qreg, cond=0b11)  # Conditional add

addSquared

addSquared(rhs, cond=0, reverse_to_subtract=False, condition_mask=0)

Same as add_squared, provided for backward compatibility. Deprecated and will be removed in WB 5.0.0. Use += and Square Qubricks instead.

ppr

ppr(theta: float | RotationAngle | tuple[int, int], x_mask: int, z_mask: int, cond: int = 0, error_param: float = 0)

Apply a Pauli Product Rotation (PPR) on the qubit register.

The applied unitary operator is as follows:

\[ \text{PPR}(\theta) = \cos(\theta)I - i\sin(\theta) \left(\bigotimes_{j \in \text{x_mask}} X_j \right) \left(\bigotimes_{k \in \text{z_mask}} Z_k \right) \]

Here:

  • \(\theta\) is the rotation angle in degrees, radians, or fractions of \(\pi\).

  • \(X_j\) represents a Pauli-X operation on qubit j.

  • \(Z_k\) represents a Pauli-Z operation on qubit k.

The x_mask and z_mask define the qubits on which the Pauli-X and Pauli-Z operations are applied, respectively.

Parameters:

Name Type Description Default
theta float | RotationAngle | tuple[int, int]

The rotation angle in degrees (or (theta * units.rad) for radians, or (num,denom) for fraction of pi).

required
x_mask int

The bitmask specifying the qubits for Pauli-X operations.

required
z_mask int

The bitmask specifying the qubits for Pauli-Z operations.

required
cond int

Condition bit(s) for controlled execution. Defaults to 0 (unconditional).

0
error_param float

Error parameter for rotation synthesis.

0

ppm

ppm(sign: int, x_mask: int, z_mask: int) -> int

Apply a Pauli Product Measurement (PPM) on the qubit register.

The Pauli Product Measurement (PPM) measures the observable associated with the operator:

\[ M = \left(\bigotimes_{j \in \text{x_mask}} X_j \right) \left(\bigotimes_{k \in \text{z_mask}} Z_k \right) \]

Here:

  • \(X_j\) is the Pauli-X operator acting on qubit j.

  • \(Z_k\) is the Pauli-Z operator acting on qubit k.

Parameters:

Name Type Description Default
sign int

The sign of the operator measured. If -1, the eigenvalue measurement result is flipped.

required
x_mask int

Mask for Pauli-X on specific qubits.

required
z_mask int

Mask for Pauli-Z on specific qubits.

required

Returns:

Type Description
int

The result of the Pauli product measurement: either 0 (for +1 eigenvalue) or 1 (for -1 eigenvalue).

peek_ppm_probability

peek_ppm_probability(x_mask, z_mask, flush=True)

Peek at the probability result of a Pauli Product Measurement (PPM) for specified qubits.

This function computes the probability of a given PPM without collapsing the state, allowing you to inspect the likelihood of the specified measurement outcome. It works in a non-destructive manner, suitable only for simulation environments.

Parameters:

Name Type Description Default
x_mask int or list

Mask to specify qubits for X-basis measurements. This can be a bitfield, list of qubit indices, or another suitable format.

required
z_mask int or list

Mask to specify qubits for Z-basis measurements. This can be a bitfield, list of qubit indices, or another suitable format.

required
flush bool

If True, flushes the pipeline before reading the probabilities. Defaults to True.

True

Returns:

Type Description
float

The probability of the specified Pauli product measurement returning 0.

ppm_async

ppm_async(sign, x_mask, z_mask)

Perform an asynchronous Pauli Product Measurement (PPM) on specified qubits.

This function initiates a PPM and returns a placeholder for the result, allowing other operations to proceed without waiting for the measurement outcome. The PPM checks a specified Pauli product outcome over the specified qubits.

Parameters:

Name Type Description Default
sign int

The expected outcome sign of the measurement (+1 or -1).

required
x_mask int or list

Mask to specify qubits for X-basis measurements. This can be a bitfield, list of qubit indices, or another suitable format.

required
z_mask int or list

Mask to specify qubits for Z-basis measurements. This can be a bitfield, list of qubit indices, or another suitable format.

required

Returns:

Type Description
AsyncReadResult

Placeholder for the result of the asynchronous PPM operation.

print_state_vector

print_state_vector(line=-1, min_value_to_print=1e-10, max_num_values=1000, show_entangled=True, with_qreg_types=True, flush=True)

Print the state vector of the qubit register.

This function displays the state vector of the qubits, filtering out entries based on the minimum amplitude threshold (min_value_to_print) and limiting the number of entries displayed (max_num_values). This method is primarily for debugging and analysis, and it is only supported in simulation.

Parameters:

Name Type Description Default
line int

Deprecated and will be removed in WB 5.0.0. To get probability of a single basis state, use peek_read_probability instead.

-1
min_value_to_print float

Minimum amplitude magnitude to display. States with amplitudes below this threshold are not shown. Defaults to 1e-10.

1e-10
max_num_values int

Maximum number of states to display. Defaults to 1000.

1000
show_entangled bool

Whether to show qubits that are not included in the register, but are entangled with the register, in the state vector. Default is True.

True
with_qreg_types bool

Whether to show the state vector with the actual value of the register type, or only as an integer value representation, default is True.

True
flush bool

If True, flushes the pipeline before reading the state vector. Defaults to True.

True

print_probabilities

print_probabilities(line=-1, min_value_to_print=1e-10, max_num_values=1000, show_entangled=True, with_qreg_types=True, flush=True)

Print the probabilities of each of the basis states in the state vector of the qubit register.

This function displays the probabilities of each of the basis states in the state vector of the qubit register, filtering out entries based on the minimum amplitude threshold (min_value_to_print) and limiting the number of entries displayed (max_num_values). This method is primarily for debugging and analysis, and it is only supported in simulation.

Parameters:

Name Type Description Default
line int

Deprecated and will be removed in WB 5.0.0. To get probability of a single basis state, use peek_read_probability instead.

-1
min_value_to_print float

Minimum amplitude magnitude to display. States with amplitudes below this threshold are not shown. Defaults to 1e-10.

1e-10
max_num_values int

Maximum number of states to display. Defaults to 1000.

1000
show_entangled bool

Whether to show qubits that are not included in the register, but are entangled with the register, in the probabilities of the basis states. Default is True.

True
with_qreg_types bool

Whether to show the state vector with the actual value of the register type, or only as an integer value representation, default is True.

True
flush bool

If True, flushes the pipeline before reading the state vector. Defaults to True.

True

QUInt

QUInt(num_qubits=None, name=None, qpu=None)

Bases: Qubits

Represents an unsigned integer stored in a quantum register.

The QUInt class configures a quantum register to store non-negative integers using a specified number of qubits. Each qubit corresponds to a binary bit in the unsigned integer representation.

\[ b_{n-1} \cdots b_2 b_1 b_0 = b_{n-1} \cdot 2^{n-1} + b_{n-2} \cdot 2^{n-2} + \cdots + b_1 \cdot 2^1 + b_0 \cdot 2^0 \]

Here:

  • \(b_{n-1}\) is the most significant bit (MSB).
  • \(b_0\) is the least significant bit (LSB).

Features:

  • Unsigned Representation: All values are treated as non-negative integers.
  • Bit Masking: Supports bitwise masking for more flexible control over quantum operations.
  • Value Range: From 0 to \(2^{n} - 1\), where \(n\) is the number of qubits.

Attributes:

Name Type Description
num_qubits int

Number of qubits in the register.

name str

Human-readable identifier for the register.

qpu QPU

The quantum processor instance where this register resides.

Example
from psiqdk.workbench import QPU, QUInt

qc = QPU(num_qubits=4)

# Initialize a 4-qubit unsigned integer register
uint_reg = QUInt(4, name="uint_4", qpu=qc)
uint_reg.write(7)            # Stores the value 7
print(uint_reg.read())       # Output: 7

# Check max and min values for a 4-bit unsigned integer
print(uint_reg.max_value())  # Output: 15
print(uint_reg.min_value())  # Output: 0

# Example of bitwise operations
masked_value = uint_reg.mask(0b1010)  # Apply a bit mask
print(masked_value)  # Output will depend on the current state of the register
Notes
  • Use the mask method for bitwise operations such as ANDing specific bits.

Parameters:

Name Type Description Default
num_qubits int

Number of qubits allocated to the register.

None
name str

Identifier name for the register.

None
qpu QPU

The quantum processing unit to allocate the register on.

None

op_flags instance-attribute

op_flags = OP_QUBITS_flag_type_uint

radix instance-attribute

radix = 0

QInt

QInt(num_qubits=None, name=None, qpu=None)

Bases: Qubits

Represents a signed integer stored in a quantum register.

The QInt class provides a quantum register configured to store signed integers, using the specified number of qubits. The most significant bit (MSB) acts as the sign bit, following the two's complement convention for signed integer representation.

\[ b_{n-1} \cdots b_2 b_1 b_0 = - b_{n-1} \cdot 2^{n-1} + b_{n-2} \cdot 2^{n-2} + \cdots + b_1 \cdot 2^1 + b_0 \cdot 2^0 \]

Here:

  • \(b_{n-1}\) is the most significant bit (MSB), representing the sign.
  • \(b_0\) is the least significant bit (LSB).

Features:

  • Two's Complement Representation: Enables representation of both positive and negative values.
  • Value Range: From \(-2^{n-1}\) to \(2^{n-1} - 1\), where \(n\) is the number of qubits.

Attributes:

Name Type Description
num_qubits int

Number of qubits in the register.

name str

Human-readable identifier for the register.

qpu QPU

The quantum processor instance where this register resides.

Example
from psiqdk.workbench import QPU, QInt

qc = QPU(num_qubits=3)

# Initialize a 3-qubit signed integer register
int_reg = QInt(3, name="int_3", qpu=qc)
int_reg.write(-2)           # Stores the value -2
print(int_reg.read())       # Output: -2

# Check maximum and minimum values for a 3-bit signed integer
print(int_reg.max_value())  # Output: 3
print(int_reg.min_value())  # Output: -4
Note

The most significant bit (MSB) serves as the sign bit:

  • 0 indicates positive numbers.
  • 1 indicates negative numbers.

Parameters:

Name Type Description Default
num_qubits int

Number of qubits allocated to the register.

None
name str

Identifier name for the register.

None
qpu QPU

The quantum processing unit to allocate the register on.

None

op_flags instance-attribute

op_flags = OP_QUBITS_flag_type_int

radix instance-attribute

radix = 0

is_signed property

is_signed

max_value

max_value() -> int

Calculates the maximum representable value for the current number of qubits.

Returns:

Type Description
int

The maximum value representable by the register.

min_value

min_value() -> int

Calculates the minimum representable value for the current number of qubits.

Returns:

Type Description
int

The minimum value representable by the register.

read

read(target_mask=~0) -> int

Reads the current value stored in the register, converting from signed integer format.

Parameters:

Name Type Description Default
target_mask int

Mask to specify which qubits to read. Defaults to all qubits.

~0

Returns:

Type Description
int

The signed integer value stored in the register.

addSquared

addSquared(rhs, cond=0, reverse_to_subtract=False, condition_mask=0)

Adds the square of the given register rhs to the current register.

Deprecated and will be removed in WB 5.0.0. Use += and Square Qubricks instead.

Parameters:

Name Type Description Default
rhs QInt

The register to square and add.

required
cond int

Mask specifying the control qubits.

0
reverse_to_subtract bool

If True, subtracts the square of rhs instead of adding.

False
condition_mask int

Deprecated and will be removed in WB 5.0.0. Use cond instead.

0

QUFixed

QUFixed(num_qubits=None, radix=None, name=None, qpu=None)

Bases: Qubits

Represents an unsigned fixed-point number stored in a quantum register.

This class allows for the representation of non-integer values in a quantum register by specifying a radix, which determines the boundary between the integer and fractional parts of the fixed-point representation.

An unsigned fixed-point number with a radix \(r\) is given by:

\[ b_{n-1}b_{n-2} \cdots b_2b_1b_0 = b_{n-1} \cdot 2^{n-1-r} + b_{n-2} \cdot 2^{n-2-r} + \cdots + b_1 \cdot 2^{1-r} + b_0 \cdot 2^{-r} \]

Here:

  • \(b_{n-1}\) is the most significant bit (MSB).
  • \(b_0\) is the least significant bit (LSB).
  • The radix determines how many bits are allocated to the fractional part.

Features:

  • Radix: Controls the boundary between the integer and fractional parts:
    • A radix of 0 means all qubits are used for the integer part.
    • Higher values of radix dedicate qubits to fractional precision.
  • Value Range: The maximum and minimum values depend on num_qubits and radix.

Attributes:

Name Type Description
num_qubits int

Number of qubits to allocate for the register.

radix int

Specifies the number of qubits used for the fractional part.

name str

Identifier name for the register.

qpu QPU

QPU to allocate the register on.

Example
from psiqdk.workbench import QPU, QUFixed

qc = QPU(num_qubits=4)

# Example with radix = 2
ufixed_reg = QUFixed(4, radix=2, name="ufixed_2", qpu=qc)
ufixed_reg.write(2.75)         # Stores the value 2.75
print(ufixed_reg.read())       # Output: 2.75

# Check max and min values
print(ufixed_reg.max_value())  # Output: 3.75
print(ufixed_reg.min_value())  # Output: 0.0

Parameters:

Name Type Description Default
num_qubits int

Total number of qubits allocated to the register.

None
radix int

Number of qubits used to represent the fractional part.

None
name str

Identifier name for the register.

None
qpu QPU

The quantum processing unit to allocate the register on.

None

Raises:

Type Description
ValueError

If the radix is not provided or is invalid (negative or exceeding qubit count).

op_flags instance-attribute

op_flags = OP_QUBITS_flag_type_ufixed

radix instance-attribute

radix = radix

is_fixed property

is_fixed

max_value

max_value() -> float

Calculates the maximum representable value for the current number of qubits and radix.

Returns:

Type Description
float

The maximum value representable by the register.

min_value

min_value() -> float

Calculates the minimum representable value for the current number of qubits and radix.

Returns:

Type Description
float

The minimum value representable by the register, which is always 0 for unsigned types.

step_value

step_value() -> float

Determines the smallest representable step value in the register.

Returns:

Type Description
float

The step size between two consecutive representable values.

read

read() -> float

Reads the current value stored in the register, converting from fixed-point format.

Returns:

Type Description
float

The value stored in the register, as a fixed-point number.

write

write(value: int | float, warn_on_rounding: bool = False) -> None

Write a classical value into the computational basis.

Parameters:

Name Type Description Default
value int or float

The value to write (must be >= 0).

required
warn_on_rounding bool

Warn if radix is too small to represent value exactly.

False
Note

The value -1 is allowed as a special case, to accommodate the common expression ~0 (all bits on).

Raises:

Type Description
UserWarning

If rounding occurs due to limited radix.


QFixed

QFixed(num_qubits=None, radix=None, name=None, qpu=None)

Bases: Qubits

Represents a signed fixed-point number stored in a quantum register.

This class extends the fixed-point representation to include signed values. The most significant bit (MSB) is treated as a sign bit, enabling representation of both positive and negative values. The remaining bits encode the magnitude of the number using a fixed-point representation, where the radix specifies the boundary between the integer and fractional parts.

A signed fixed-point number with a radix \(r\) is given by:

\[ b_{n-1}b_{n-2} \cdots b_1b_0 = -b_{n-1} \cdot 2^{n-1-r} + b_{n-2} \cdot 2^{n-2-r} + \cdots + b_1 \cdot 2^{1-r} + b_0 \cdot 2^{-r} \]

Here:

  • \(b_{n-1}\) is the most significant bit (MSB), treated as the sign bit.
  • \(b_0\) is the least significant bit (LSB).
  • The radix determines the division of bits between integer and fractional parts.

Features:

  • Signed Representation: The MSB is treated as a sign bit:
    • 0 indicates a positive number.
    • 1 indicates a negative number.
  • Radix: Determines the boundary between integer and fractional parts.
  • Value Range: Depends on num_qubits and radix.

Attributes:

Name Type Description
num_qubits int

Number of qubits to allocate for the register.

radix int

Specifies the number of qubits used for the fractional part.

name str

Identifier name for the register.

qpu QPU

QPU to allocate the register on.

Example
from psiqdk.workbench import QPU, QFixed

qc = QPU(num_qubits=4)

# Example with radix = 2
fixed_reg = QFixed(4, radix=2, name="fixed_2", qpu=qc)
fixed_reg.write(-1.25)        # Stores the value -1.25
print(fixed_reg.read())       # Output: -1.25

# Check max and min values
print(fixed_reg.max_value())  # Output: 1.75
print(fixed_reg.min_value())  # Output: -2.0
Note

Signed fixed-point numbers are useful for representing positive and negative non-integer values without the overhead of floating-point representations.

Parameters:

Name Type Description Default
num_qubits int

Total number of qubits allocated to the register.

None
radix int

Number of qubits used to represent the fractional part.

None
name str

Identifier name for the register.

None
qpu QPU

The quantum processing unit to allocate the register on.

None

Raises:

Type Description
ValueError

If the radix is not provided.

op_flags instance-attribute

op_flags = OP_QUBITS_flag_type_fixed

radix instance-attribute

radix = radix

is_signed property

is_signed

is_fixed property

is_fixed

max_value

max_value() -> float

Calculates the maximum representable value for the current number of qubits and radix.

Returns:

Type Description
float

The maximum value representable by the register.

min_value

min_value() -> float

Calculates the minimum representable value for the current number of qubits and radix.

Returns:

Type Description
float

The minimum value representable by the register.

step_value

step_value() -> float

Determines the smallest representable step value in the register.

Returns:

Type Description
float

The step size between two consecutive representable values.

read

read() -> float

Reads the current value stored in the register, converting from fixed-point format.

Returns:

Type Description
float

The value stored in the register, as a fixed-point number.

write

write(value: int | float, warn_on_rounding: bool = False)

Writes a classical value to the qubits register, applying fixed-point conversion.

Parameters:

Name Type Description Default
value int or float

The value to write into the qubit register.

required
warn_on_rounding bool

Warns if the radix is too small for exact representation. Defaults to False.

False

Raises:

Type Description
UserWarning

If rounding occurs due to limited radix.


CompositeRegister dataclass

CompositeRegister()

Bases: Qubits, ABC

Base class for handling registers consisting of a fixed set of named Qubits objects.

CompositeRegister is a flexible way to group multiple quantum registers into a composite structure. Each component of the CompositeRegister is accessed by its defined name. This makes it ideal for application-specific designs where different sub-registers represent distinct aspects of a problem.

Key Features:

  • Acts like a dictionary for its constituent registers, which can be accessed by name.
  • Supports custom initialization via the initialize method, tailored to specific problem domains.
  • Prevents slicing to ensure that the intended structure is preserved.

Defining a CompositeRegister

Users need to subclass CompositeRegister, define the component registers as fields, and implement the initialize method that allocates the required registers. For example:

@dataclass(eq=False)
class MyCompositeRegister(CompositeRegister):
    qbts1: Qubits
    qbts2: Qubits
    qbts3: Qubits
    name: str

    @classmethod
    def initialize(cls, qc, name, param_1, param_2):
        qbts1 = Qubits(int(np.ceil(np.log2(param_1))), "qbts1", qc)
        qbts2 = Qubits(int(np.ceil(np.log2(param_2))), "qbts2", qc)
        qbts3 = Qubits(int(param_1 + param_2), "qbts3", qc)
        return cls(qbts1, qbts2, qbts3, name)

Optional Registers

Composite registers can include optional sub-registers, which may be initialized later:

@dataclass(eq=False)
class MyCompositeRegister(CompositeRegister):
    a: Qubits
    b: Qubits
    c: Optional[Qubits] = None

    @classmethod
    def initialize(cls, qc, name, num_a, num_b):
        a = Qubits(num_a, "a", qc)
        b = Qubits(num_b, "b", qc)
        return cls(a, b, name=name)

Example of using the optional register:

comp_reg = MyCompositeRegister.initialize(qc, "example", param_1, param_2)
comp_reg.c = Qubits(param_3, "c", qc)

Example Usage

CompositeRegisters behave like dictionaries, where sub-registers are accessed by their names:

qc = QPU()
qc.reset(9)

my_register = MyCompositeRegister.initialize(qc, "example", 3, 2)

# Access the whole register
my_register.x()
my_register.qbts1.x()
my_register.qbts1.y(ctrl)

For more details, see Quantum Arithmetic Data Types tutorial.

composite_reg property

composite_reg: Qubits | None

num_qubits property

num_qubits

qpu property

qpu

cond_xor property

cond_xor

get_components

get_components() -> tuple[Qubits, ...]

release

release(clear_to_zero=False)

Releases every Qubits object in the composite register.

initialize abstractmethod classmethod

initialize(qc, *args, **kwargs)

Method to construct a CompositeRegister instance.

You need to implement this method when defining your subclass to be able to use it!


VectorRegister

VectorRegister(name: str, registers: Sequence[T], owns_alloc: bool = False)

Bases: Generic[T, TQPU], BaseQubits[TQPU]

Base class for handling an array of qubits registers.

A VectorRegister simplifies implementation of an array-like structure of quantum registers. Each element of the vector is a qubit register, and the vector supports operations like arithmetic and slicing.

Note

Do not instantiate VectorRegister class directly! Use vector_register method instead. For more details, see Quantum Arithmetic Data Types tutorial.

Parameters:

Name Type Description Default
name str

Name of the vector register.

required
registers Sequence[T]

List of qubit registers.

required

name instance-attribute

name = name

owns_alloc instance-attribute

owns_alloc = owns_alloc

identifier property

identifier: int

registers property

registers

qubits_type property

qubits_type: type[T]

qpu property

qpu: TQPU

cond_xor property

cond_xor

num_qubits property

num_qubits

Total number of qubits in the vector.

composite_reg property

composite_reg: T

A single register containing all the registers in the vector.

index property

index: int

write

write(value: int | float | list | ndarray, target_mask: int | list[int] = ~0)

Write values into the vector register.

This method writes classical values into the computational basis of each element in the vector register. It can either write a single value across all registers or different values to each register in the vector.

Parameters:

Name Type Description Default
value int | float | list | ndarray

The value to write. If an integer or float, applies the value to all registers in the vector. If a list or array, each entry is written to a corresponding register.

required
target_mask int or list[int]

The mask(s) to apply for each write. If an integer, applies the same mask to all registers. If a list, each entry specifies a mask for a corresponding register.

~0

Raises:

Type Description
ValueError

If value is a list but its length does not match the vector length.

release

release()

Release all the qubits in the vector.

mask

mask(base_mask: int = ~0) -> int

allocate

allocate(qpu: TQPU | None = None) -> None

is_allocated

is_allocated() -> bool

ppr

ppr(theta: float | RotationAngle | tuple[int, int], x_mask: int, z_mask: int, cond: int = 0)

ppm

ppm(theta: float | RotationAngle | tuple[int, int], x_mask: int, z_mask: int) -> int

read

read(target_mask: int = ~0) -> int

swap

swap(target: T | VectorRegister[T], condition_mask: int = 0) -> None