Numeric Assignment¶
Scalar variables (qnum
and qbit
) can be assigned the result of arithmetic/logical
expressions over other quantum variables using computational basis arithmetic. Expressions
comprise conventional arithmetic operators, numeric constants, and quantum scalar variables.
Single qubit variables can be assigned the result of an expression over other quantum variables, encoded into the amplitude of the \(ֿ|1\rangle\) state. Expressions supported for amplitude encoding include a number of useful math functions.
Computational-Encoding Assignment¶
Numeric assignment statements in the computational basis take two forms - out-of-place and in-place-xor. When assigning the result of an expression out-of-place, a new quantum object is allocated to store the result. For in-place-xor assignment the result bits are xor-ed with the current state of the target variable.
Syntax¶
target-var = quantum-expression
target-var ^= quantum-expression
target-var |= quantum-expression
target-var ^= quantum-expression
Note that |=
is used to represent the native =
since the operator =
cannot be overloaded in Python.
Semantics¶
- quantum-expression is a composition of operators over quantum variables, classical variables, and numeric constant literals. See below the list of supported operators.
- In the out-of-place (
=
) form, target-var must be uninitialized prior to the assignment and is subsequently initialized.- The size and numeric attributes of target-var are computed to tightly fit the range of possible result values of quantum-expression, based on variable sizes, constants, and operators.
- The numeric attributes of target-var must be left unspecified in the declaration or otherwise agree with the computed attributes. quantum-expression, or left unspecified and be inferred accordingly.
- In the in-place-xor (
^=
) form, target-var must be initialized prior to the assignment.- Each bit in target-var is xor-ed with the respective bit in the result of quantum-expression if any, or otherwise left unchanged.
- Bits in the result of quantum-expression with no counterpart in target-var are ignored.
- Currently, target-var is limited to non-negative integers (
qnum
with no sign bit nor fraction digits).
- The variables occurring in the expression can subsequently be used, with their states unmodified.
The following operators are supported:
- Add: +
- Subtract: - (binary)
- Negate: - (unary)
- Multiply: *
- Power ** (quantum base, positive classical integer exponent)
- Modulo: % limited for power of 2
- Bitwise Or: |
- Bitwise And: &
- Bitwise Xor: ^
- Bitwise Invert: ~
- Equal: ==
- Not Equal: !=
- Greater Than: >
- Greater Or Equal: >=
- Less Than: <
- Less Or Equal: <=
- Logical And: and (in Python
logical_and()
) - Logical Or: or (in Python
logical_or()
) - Logical Not: not (in Python
logical_not()
) - Max: max (n>=2 arguments)
- Min: min (n>=2 arguments)
Examples¶
Example 1: Out-of-place assignment¶
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 a superposition of 1 and 2.
The output is a superposition of 8 and 10.
qfunc main(output res: qnum) {
a: qnum;
b: qnum;
prepare_int<3>(a);
prepare_state<[0, 0.5, 0.5, 0], 0>(b);
res = (a + (2 * b)) + 3;
}
from classiq import Output, QBit, QNum, QArray, qfunc, prepare_int
@qfunc
def main(res: Output[QNum]) -> None:
a = QNum("a")
b = QNum("b")
prepare_int(3, a)
prepare_state([0, 0.5, 0.5, 0], 0, b) # b = superposition of 1 and 2
res |= a + 2 * b + 3 # should be 8
Note that the output size is 4 qubits, since the maximum value of this expression
is 15, given that a
and b
are two-qubit variables. Any other size declared for res
will result in an error.
Example 2: In-place assignment¶
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.
qfunc foo(res: qbit) {
a: qnum;
b: qnum;
prepare_int<3>(a);
prepare_int<1>(b);
res ^= (a + 2 * b + 3 == 8);
}
from classiq import QNum, qfunc, prepare_int, QBit
@qfunc
def foo(res: QBit) -> None:
a = QNum("a")
b = QNum("b")
prepare_int(3, a)
prepare_int(1, b)
res ^= a + 2 * b + 3 == 8 # expression is true so 'res' is flipped
Example 3: In-place assignment of a logical expression¶
In the example below, function my_oracle
serves as a quantum oracle that marks all states
satisfying the logical expression (x0 and x1) or (x2 and x3)
with a minus phase.
qfunc my_oracle(x0: qbit, x1: qbit, x2: qbit, x3: qbit) {
aux: qbit;
allocate<1>(aux);
within {
X(aux);
H(aux);
} apply {
aux ^= (x0 and x1) or (x2 and x3);
}
}
from classiq import QBit, qfunc, allocate, X, H, within_apply
from classiq.qmod.symbolic import logical_or, logical_and
@qfunc
def my_oracle(x0: QBit, x1: QBit, x2: QBit, x3: QBit) -> None:
aux = QBit("aux")
allocate(1, aux)
def assignment_stmt(var: QBit) -> None:
var ^= logical_or(logical_and(x0, x1), logical_and(x2, x3))
within_apply(lambda: (X(aux), H(aux)), lambda: assignment_stmt(aux))
Note that in Python, assignment statements are not allowed directly as lambda expressions.
Therefore, in this example the ^=
is factored out to an inner Python function.
Amplitude-Encoding Assignment¶
Amplitude encoding assignment loads the result of an expression over variable x into the amplitude of a target qubit.
Syntax¶
target-var *= expression
target-var *= expression
Semantics¶
- target-var must be initialized prior to the assignment.
- Only a single quantum variable is allowed in expression representing a number
between 0 and 1 (
qnum
with no sign bit and with all bits representing fraction digits). - If target-var is in \(|0\rangle\) state prior to the assignment, it will be in the state \(\sqrt{1-expressionֿ^2}ֿ|0\rangle+expressionֿ|1\rangle\) subsequently.