Skip to content

Quantum Registers

Quantum registers, or QRegs, are objects that serve as a way of declaring registers in the Classiq Python SDK. They serve as a way to declare registers.

The syntax:

from classiq import QReg

x = QReg(size=3)

You can pass QRegs to functions as their inputs and as their outputs. The following example calls QFT twice, where the output of the first call is the input of the second call.

from classiq import Model
from classiq.builtin_functions import QFT

num_qubits = 3

model = Model()

qft_params = QFT(num_qubits=num_qubits)
# First call
first_qft_output = model.QFT(qft_params)["OUT"]

# Second call
model.QFT(
    qft_params,
    in_wires=first_qft_output,
)

circuit = model.synthesize()
circuit.show()

Functions with Multiple Inputs/Outputs

When a function requires only one input or output (like QFT in the above example), then pass a single QReg.

However, when functions require multiple inputs/outputs, pass them either by order or by name (similarly to most programming languages):

  • Sending by order requires an iterable of QRegs; e.g., in_wires=[QReg(size=3), QReg(size=4)].
  • Sending by name requires a dictionary of type Dict[str, QReg].

Quantum Registers - Arithmetic Types

A QReg can be thought of as a collection of qubits, with no particular meaning. Give meaning, for example, by calling this collection of qubits an integer, or QInt.

There are four new types: QUInt, QSInt, QUFixed, QSFixed, with U and S signifying "Unsigned" or "Signed", respectively.

The four new types have two categories:

  1. The first category is whether the QReg is signed or unsigned.
  2. The second category treats numbers as fixed points; i.e., a fractional number with a known number of digits of their fractional part. Thus, an integer is a fixed-point number with 0 fractional digits.

To initialize the types:

from classiq import QUInt, QSInt, QUFixed, QSFixed

my_quint = QUInt(size=1)
my_qsint = QSInt(size=2)
my_qufixed = QUFixed(size=3, fraction_places=1)
my_qsfixed = QSFixed(size=4, fraction_places=2)

You can also use the types as a type declaration in user-defined functions and in the composite functions create_inputs method. In this case, provide the type parametrization in square brackets:

  • Integer (QSInt, QUInt) and QReg types without arithmetic expect the number of qubits as the parameter, e.g., QReg[5] signifies a type of QReg of size 5.
  • Fixed-point types (QSFixed, QUFixed) expect two numbers: the number of integer places and the number of fraction places. E.g., QSFixed[3,2] signifies a signed, fixed-point QReg with 3 integer places and 2 fraction places (and a total size of 5).

Calling Arithmetic Functions

To call an arithmetic function:

  1. Create a FunctionParams object.
  2. Call the function using the model.

Do it as follows:

from classiq import Model, QSInt, QUInt
from classiq.builtin_functions import BitwiseAnd

x = QSInt(size=5)
y = QUInt(size=3)

params = BitwiseAnd(
    left_arg=x.to_register_user_input(), right_arg=y.to_register_user_input()
)
model = Model()
model.BitwiseAnd(
    params,
    out_wires=[x, y]
    # Alternatively, it is possible to pass it by order, as follows:
    # out_wires={
    #     "left_arg": x,
    #     "right_arg": y,
    # }
)
circuit = model.synthesize()