Quantum Types and Expressions in QMOD¶
In QMOD quantum variables can be assigned the result of expressions over other quantum variables. Expressions can be arithmetic, relational, or bitwise. The quantum variables in the expression have to be of one of the following numeric quantum types:
QInt
: A quantum (signed) integer. The constructorQInt(size)
can be used to declare aQInt
of a particular size (in qubits).QFixed
: A quantum (signed) fixed-point fractional number. The constructorQFixed(size, fraction_places)
can be used to declare aQFixed
of a particular size and fractional places (in qubits).
Expression assignment constructs¶
The assignment of quantum expressions takes one of the following forms:
<qvar> |= <expression>
- allocate a storage for the result of<expression>
and associate it<qvar>
, which has not been allocated<qvar> ^= <expression>
- xor the result of<expression>
in-place with the value of<qvar>
that has already been allocated/initialized<qvar> *= <expression>
- encode the result off(x) = <expression>
into the amplitude of<qvar>
, such that for an input quantum variable in the state \(|x\rangle\), you obtain an output qubit in the state \(\sqrt{1-f(x)^2}ֿ|0\rangle+f(x)ֿ|1\rangle\)
The expression itself is composed of quantum variables, native Python constants, and
(in most cases) native Python operators. The expression language is based on the Python
package Sympy
, and conforms to its construction rules. See more under
Sympy Docs.
Notes:
- The size of the newly allocated quantum variable in the
|=
form is calculated to tightly fit the possible result value, based on the expression variable sizes, constants, and operators. - The variables occurring in the expression can subsequently be used, with value unmodified.
- For equality (
==
), inequality (!=
), conjunction (and
) and disjunction (or
) use the respective Sympy classesEq
,Ne
,And
, andOr
. - Currently only single-bit variables can be used with the
^=
form, corresponding to the result of a relational expressions, or bitwise expressions over single-qubit variables - For the
*=
operator, several conditions have to be satisfied:- The
<expression>
should contain only a single variable. - The input variable should be a
QFixed
number between 0 and 1.
- The
Examples¶
The following is a model that computes the result of the expression a + 2 * b + 3
,
with a
initialized to 3 and b
initialized to equal superposition of 1 and 2.
The output is superposition of 8 and 10.
from classiq import Output, QBit, QInt, QArray, QFunc, prepare_int
@QFunc
def main(res: Output[QInt]) -> None:
a = QInt("a")
b = QInt("b")
prepare_int(3, a)
prepare_state([0, 0.5, 0.5, 0], 1e-4, b) # b = superposition of 1 and 2
res |= a + 2 * b + 3 # should be 8
Note that the size of the output is 4 qubits, since the maximum value of this expression
is 15, given a
and b
are two qubit variables. Any other size declared for res
will
result in an error.
In the next example the relational expression a + 2 * b + 3 == 8
is computed, with
a
initialized to 3 and b
initialized to 1. Calling function foo
will flip the
single variable res
, because the expression evaluates to 1, that is, true.
from sympy import Eq
from classiq import QBit, QInt, QFunc, prepare_int
@QFunc
def foo(res: QBit) -> None:
a = QInt("a")
b = QInt("b")
prepare_int(3, a)
prepare_int(1, b)
res ^= Eq(a + 2 * b + 3, 8) # should be 1..
In the next example function my_oracle
serves as a quantum oracle that marks all states
satisfying the expression x0 & x1 ^ x2 & x3
with a minus phase.
from classiq import QBit, QFunc, allocate, X, H, free
@QFunc
def my_oracle(x0: QBit, x1: QBit, x2: QBit, x3: QBit) -> None:
aux = QBit("aux")
allocate(1, aux)
X(aux)
H(aux)
aux ^= x0 & x1 ^ x2 & x3
H(aux)
X(aux)
free(aux)