Quantum Registers¶
Quantum registers, or QReg
s, 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 QReg
s 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, synthesize, show
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,
)
qprog = synthesize(model.get_model())
show(qprog)
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
QReg
s; 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:
- The first category is whether the
QReg
is signed or unsigned. - 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
) andQReg
types without arithmetic expect the number of qubits as the parameter, e.g.,QReg[5]
signifies a type ofQReg
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-pointQReg
with 3 integer places and 2 fraction places (and a total size of 5).
Calling Arithmetic Functions¶
To call an arithmetic function:
- Create a
FunctionParams
object. - Call the function using the
model
.
Do it as follows:
from classiq import Model, QSInt, QUInt, synthesize
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,
# }
)
qprog = synthesize(model.get_model())