diff --git a/.internal/docs/qmod-reference/api-reference/functions/core_library/arithmetic.md b/.internal/docs/qmod-reference/api-reference/functions/core_library/arithmetic.md index 600f0d456..8bf86fec8 100644 --- a/.internal/docs/qmod-reference/api-reference/functions/core_library/arithmetic.md +++ b/.internal/docs/qmod-reference/api-reference/functions/core_library/arithmetic.md @@ -12,6 +12,7 @@ search: - unitary - multiply - multiply_constant + - canonical_add - canonical_multiply - canonical_multiply_constant diff --git a/.internal/docs/qmod-reference/api-reference/functions/core_library/exponentiation.md b/.internal/docs/qmod-reference/api-reference/functions/core_library/exponentiation.md index 6b656c29a..cc2fe43df 100644 --- a/.internal/docs/qmod-reference/api-reference/functions/core_library/exponentiation.md +++ b/.internal/docs/qmod-reference/api-reference/functions/core_library/exponentiation.md @@ -13,7 +13,7 @@ search: - commuting_paulis_exponent - suzuki_trotter - multi_suzuki_trotter - - unscheduled_suzuki_trotter + - sequential_suzuki_trotter - qdrift - exponentiate diff --git a/.internal/docs/qmod-reference/language-reference/expressions.md b/.internal/docs/qmod-reference/language-reference/expressions.md new file mode 100644 index 000000000..0756194aa --- /dev/null +++ b/.internal/docs/qmod-reference/language-reference/expressions.md @@ -0,0 +1,219 @@ +--- +search: + boost: 1.0 +--- + +# Expressions + +Expressions in Qmod have syntax, semantics, and use, similar to expressions in +conventional programming languages. +They comprise literal values, variables, and operators applied to them. +However, Qmod is unique in that variables can be of either [classical](https://docs.classiq.io/latest/qmod-reference/api-reference/classical-types) or +[quantum](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types) types, and quantum variables have states that can be a +superposition of values, entangled with the states of other variables. +Expressions over quantum variables evaluate to a superposition of correlated +values. +For example, if `x` is a [classical variable](https://docs.classiq.io/latest/qmod-reference/language-reference/classical-variables) +of type `CInt` (an integer), then `x + 1` is a classical expression of type +`CInt` comprising the operator `+` (plus) applied to `x` and the literal `1`. +Similarly, if `qarr` is a [quantum variable](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-variables) +of type `QArray[QNum[3]]`, then `qarr[0] > x` is a quantum expression of type +`QBit`. + +_Unary operators_ are applied to a single operand. For instance, you can apply +the unary operator `~` (bitwise-invert) to variable `x` and get the expression +`~x`. +_Binary operators_ are applied to two operands. For example, the operator `>` +(greater-than) in the expression `qarr[0] > x` is applied to two operands, +`qarr[0]` and variable `x`. +The expression `qarr[0]` comprises the _subscript operator_ `[]` applied to +variable `qarr` and the literal `0`. +Applications of subscript (`[]`) and field-access (`.`) operators to classical +and quantum variables are called _path expressions_, since they point to a +partial section of the variable along a certain access path. +In our case, for instance, `qarr[0]` represents the first (0) element of the +array `qarr`. + +## Qmod Operators + +You can apply operators to operand expressions to create composite expressions. +If at least one of the operands is quantum then the expression is quantum as +well; Otherwise, it is classical. + +Qmod supports the following operators: + +### Arithmetic operators + +You can apply arithmetic operators to classical numbers (`CInt` and `CReal`) and +quantum scalars (`QBit` and `QNum`) to create numeric expressions. + +- Add: + +- Subtract: - (binary) +- Negate: - (unary) +- Multiply: \* +- Power \*\* (quantum base, positive classical integer exponent) +- Modulo: % limited for power of 2 +- Max: max (n>=2 arguments) +- Min: min (n>=2 arguments) + +### Bitwise operators + +You can apply bitwise operators to classical numbers (`CInt` and `CReal`) and +quantum scalars (`QBit` and `QNum`) to create numeric expressions. + +- Bitwise Or: | +- Bitwise And: & +- Bitwise Xor: ^ +- Bitwise Invert: ~ + +### Relational operators + +You can apply relational operators to classical numbers (`CInt` and `CReal`) and +quantum scalars (`QBit` and `QNum`) to create Boolean expressions (of types +`CBool` and `QBit`). + +- Equal: == +- Not Equal: != +- Greater Than: > +- Greater Or Equal: >= +- Less Than: < +- Less Or Equal: <= + +### Logic operators + +You can apply logical operators to Boolean expressions (`CBool`, `QBit`, and +`QNum[1]`) to create Boolean expressions (of types `CBool` and `QBit`). + +- Logical And: `logical_and()` (in Qmod Native: and) +- Logical Or: `logical_or()` (in Qmod Native: or) +- Logical Not: `logical_not()` (in Qmod Native: not) + +### Path operators + +You can use path operators to access parts of classical and quantum variables of +aggregate types, namely, structs and arrays. + +- Field Access: _struct_ **.** _field-name_ +- Array Slice: _array_ **[** _start-index_ **:** _stop-index_ **]** + - In Python, _start-index_ and _stop-index_ may be omitted. + If _start-index_ is omitted, a `0` will be placed in its stead. + If _stop-index_ is omitted, `array.len` will be placed in its stead. +- Array Subscript: _array_ **[** _index_ **]** + - The index of a quantum subscript expression must be an [unsigned quantum integer](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types/#quantum-scalar-types) variable. + - In Python, if _array_ is a Python list and _index_ is a quantum variable, use the alternative syntax: **subscript(** _array_ **,** _index_ **)** + - Currently, quantum subscript expressions are not supported in [phase statements](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/phase/). + +## Quantum Expressions + +Quantum expressions are expressions that involve one or more quantum variables. +Quantum expressions can occur in the following contexts: + +- The right-value in [assignment](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/assignment) statements +- The condition in [control](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/control) statements +- The expression argument in [phase](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/phase) statements + +During computation, the value(s) of an expression are coherently correlated to +the evaluation of the operators over the computational-basis values of the +quantum variables it comprises, which may be in any specific superpositions and +entanglement. +Quantum expressions may include any combination of operators on any +classical and quantum variables and literals, with the following exceptions: + +- All classical variables must be [compile-time](https://docs.classiq.io/latest/qmod-reference/language-reference/classical-variables/#semantics). +- The right-hand side of the division (`/`) and power (`**`) operators must be + a classical expression. + +### Examples + +The following model includes qubit `q` and quantum numeric `n` of size three. +It uses a `control` statement with a quantum expression `n > 4` to apply +`X` to `q` only when `n` is greater than four. + +=== "Python" + + ```python + from classiq import qfunc, Output, QBit, QNum, allocate, control, hadamard_transform + + + @qfunc + def main(n: Output[QNum[3]], q: Output[QBit]): + allocate(n) + hadamard_transform(n) + allocate(q) + control(n > 4, lambda: X(q)) + ``` + +=== "Native" + + ``` + qfunc main(output n: qnum<3>, output q: qbit) { + allocate(n); + hadamard_transform(n); + allocate(q); + control(n > 4) { + X(q); + } + } + ``` + +After executing this model, you get $q=0$ for $n\in\{0, 1, 2, 3, 4\}$ and +$q=1$ for $n\in\{5, 6, 7\}$. + +See [additional examples](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/assignment/#examples) +on the Assignment documentation page. + +## Classical Expressions + +Classical expressions are expressions that involve classical variables and +constant literals, but no quantum variables. +Classical variables may have known values at [compile time, link time, or runtime]](https://docs.classiq.io/latest/qmod-reference/language-reference/classical-variables/#semantics). +Classical expressions with only compile-time variables are evaluated and +simplified during compilation. +This applies sub-expressions of quantum expressions too. +Qmod supports several built-in classical [constants and functions](https://docs.classiq.io/latest/qmod-reference/api-reference/symbolic-functions/), +such as `pi` and `sin`. + +### Example + +In the following model, function `foo` accepts quantum numeric `n` and a +classical integer `x`, and perform the in-place xor operation `n ^= x + 1`. +Function `foo` is called twice, once with `x=1` and once with `x=-1`. + +=== "Python" + + ```python + from classiq import qfunc, CInt, Output, QNum + + + @qfunc + def foo(n: QNum, x: CInt): + n ^= x + 1 + + + @qfunc + def main(n: Output[QNum]): + n |= 1 + foo(n, 1) # n ^= 2 + foo(n, -1) # n ^= 0 + ``` + +=== "Native" + + ``` + qfunc foo(n: qnum, x: int) { + n ^= x + 1; + } + + qfunc main(output n: qnum) { + n = 1; + foo(n, 1); // n ^= 2; + foo(n, -1); // n ^= 0; + } + ``` + +On the first call to `foo`, the Qmod compiler assigns `x=1` and simplifies the +expression `x + 1` into `2`. +Therefore, the first `foo` call applies a constant-value xor `n ^= 2`. +On the second call to `foo`, the expression `x + 1` is simplified to `0`. +Since the assignment `n ^= 0` has no effect, the Qmod compiler removes it from +the model. diff --git a/.internal/docs/qmod-reference/language-reference/quantum-variables.md b/.internal/docs/qmod-reference/language-reference/quantum-variables.md index 13171a0be..6b9304b0b 100644 --- a/.internal/docs/qmod-reference/language-reference/quantum-variables.md +++ b/.internal/docs/qmod-reference/language-reference/quantum-variables.md @@ -371,14 +371,14 @@ The _concatenation operator_ is used to combine a sequence of quantum objects **[** _path-expressions_ **]** _path-expressions_ is a comma-separated sequence of one or more quantum - [path expressions](http://docs.classiq.io/latest/qmod-reference/language-reference/statements/numeric-assignment/?h=path+expression#path-operators). + [path expressions](http://docs.classiq.io/latest/qmod-reference/language-reference/expressions). === "Native" **{** _path-expressions_ **}** _path-expressions_ is a comma-separated sequence of one or more quantum - [path expressions](http://docs.classiq.io/latest/qmod-reference/language-reference/statements/numeric-assignment/?h=path+expression#path-operators). + [path expressions](http://docs.classiq.io/latest/qmod-reference/language-reference/expressions). For example, the model below uses the concatenation operator to apply `hadamard_transform` to a specific set of qubits drawn from two quantum diff --git a/.internal/docs/qmod-reference/language-reference/statements/numeric-assignment.md b/.internal/docs/qmod-reference/language-reference/statements/assignment.md similarity index 76% rename from .internal/docs/qmod-reference/language-reference/statements/numeric-assignment.md rename to .internal/docs/qmod-reference/language-reference/statements/assignment.md index 875b277c9..40fa4bdd9 100644 --- a/.internal/docs/qmod-reference/language-reference/statements/numeric-assignment.md +++ b/.internal/docs/qmod-reference/language-reference/statements/assignment.md @@ -3,10 +3,13 @@ search: boost: 2.361 --- -# Numeric Assignment +# Assignment + +## Numeric Assignment Scalar quantum variables (`qnum` and `qbit`) can be assigned the result of arithmetic/logical -expressions over other scalar variables using computational basis arithmetic. Expressions +[expressions](https://docs.classiq.io/latest/qmod-reference/language-reference/expressions) +over other scalar variables using computational basis arithmetic. Expressions comprise conventional arithmetic operators, numeric constants, and quantum scalar variables. Numeric assignment statements in the computational basis take two forms - out-of-place @@ -14,7 +17,7 @@ and in-place. When assigning the result of an expression out-of-place, a new qua object is allocated to store the result. For in-place assignment, the result of the operation is stored back in the target variable. -## Syntax +### Syntax === "Python" @@ -49,7 +52,7 @@ of the operation is stored back in the target variable. _target-var_ **+=** _quantum-expression_ -## Semantics +### Semantics - _quantum-expression_ consists of quantum scalar variables, numeric constant literals, and classical scalar variables, composed using arithmetic operators. @@ -57,7 +60,7 @@ of the operation is stored back in the target variable. - The quantum variables occurring in the expression can subsequently be used, with their states unmodified. -### Out-of-place assignment (`=`/`|=`) +#### Out-of-place assignment (`=`/`|=`) - _target-var_ must be uninitialized prior to the assignment and is subsequently initialized. @@ -68,7 +71,7 @@ of the operation is stored back in the target variable. otherwise be compatible with the computed numeric attributes of _quantum-expression_, that is, fit the entire range of possible expression values. -### In-place XOR (`^=`) +#### In-place XOR (`^=`) - _target-var_ must be initialized prior to the assignment. - Each bit in _target-var_ is xor-ed with the @@ -76,7 +79,7 @@ of the operation is stored back in the target variable. unchanged. - Bits in the result of _quantum-expression_ with no counterpart in _target-var_ are ignored. -### In-place add (`+=`) +#### In-place add (`+=`) @@ -91,49 +94,63 @@ of the operation is stored back in the target variable. integer part (including the sign bit) without incurring additional qubits, following the two's complement method. -### Supported arithmetic operators +## Aggregate Type Assignment + +A struct or array quantum variable can be assigned to another variable of the +same type. +In addition, an array literal can be assigned to a `QArray[QBit]` variable. + +### Syntax + +=== "Python" -#### Arithmetic operators + -- Add: + -- Subtract: - (binary) -- Negate: - (unary) -- Multiply: \* -- Power \*\* (quantum base, positive classical integer exponent) -- Modulo: % limited for power of 2 -- Max: max (n>=2 arguments) -- Min: min (n>=2 arguments) + _target-var_ **|=** _assigned-var_
+ OR
+ **assign(**_assigned-var_**,** _target-var_**)** -#### Bitwise operators + _target-var_ **^=** _assigned-var_
+ OR
+ **inplace_xor(**_assigned-var_**,** _target-var_**)** -- Bitwise Or: | -- Bitwise And: & -- Bitwise Xor: ^ -- Bitwise Invert: ~ + _array-var_ **|=** _array-literal_
+ OR
+ **assign(**_array-literal_**,** _array-var_**)** -#### Relational operators + _target-var_ **^=** _array-literal_
+ OR
+ **inplace_xor(**_array-literal_**,** _array-var_**)** -- Equal: == -- Not Equal: != -- Greater Than: > -- Greater Or Equal: >= -- Less Than: < -- Less Or Equal: <= + #### Notes + + * The operator `|=` is used to represent the native `=` since the operator + `=` cannot be overloaded in Python. + * The operator syntax and the function call syntax are equivalent. The + operator syntax is typically easier to read, but it cannot be used + directly in lambda expressions, where the function call syntax should be + used. + +=== "Native" -#### Logic operators + _target-var_ **=** _assigned-var_ -- Logical And: and (in Python `logical_and()`) -- Logical Or: or (in Python `logical_or()`) -- Logical Not: not (in Python `logical_not()`) + _target-var_ **^=** _assigned-var_ -#### Path operators + _array-var_ **=** _array-literal_ -- Field Access: _struct_ **.** _field-name_ -- Array Slice: _array_ **[** _start-index_ **:** _stop-index_ **]** -- Array Subscript: _array_ **[** _index_ **]** - - The index of a quantum subscript expression must be an [unsigned quantum integer](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types/#quantum-scalar-types) variable. - - In Python, if _array_ is a Python list and _index_ is a quantum variable, use the alternative syntax: **subscript(** _array_ **,** _index_ **)** - - Currently, quantum subscript expressions are not supported in [phase statements](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/phase/). + _array-var_ **^=** _array-literal_ + +### Semantics + +- As with numeric assignments, _target-var_ must be uninitialized in + out-of-place assignments and initialized in in-place assignments. + _assigned-var_ must be initialized in both cases. +- _target-var_ and _assigned-var_ must have the same type. For example, + variable of type `QArray[QBit]` can be assigned into a `QArray[QBit]` + variable, but a `QArray[QNum]` variable cannot. +- _array-literal_ is a classical array of 0-s and 1-s. _array-var_ must be + a quantum variable of type `QArray[QBit]`. ## Examples @@ -376,3 +393,35 @@ Overall, the output variable `n` evaluates to 7 (10%), 3 (20%), 6 (30%), or 2 n = [7, 3, 6, 2][index]; // n is 7, 3, 6, or 2 with increasing probability } ``` + +### Example 7: Aggregate type assignments + +The following model demonstrate different kinds of quantum array assignments. +First, you assign the array literal `[0, 1, 1, 0]` into variable `qarr1` of type +`QArray[QBit]`. +This applies `X` to the second and third bits of the array. +Next, you initialize `qarr2` by assigning `qarr1` to it. +This applies `CX` to the qubits of `qarr1` and `qarr2` sequentially. + +=== "Python" + + ```python + from classiq import qfunc, Output, QArray, QBit, allocate + + + @qfunc + def main(qarr1: Output[QArray], qarr2: Output[QArray]) -> None: + allocate(4, qarr1) + qarr1 ^= [0, 1, 1, 0] + qarr2 |= qarr1 + ``` + +=== "Native" + + ``` + qfunc main(output qarr1: qbit[], output qarr2: qbit[]) { + allocate(4, qarr1); + qarr1 ^= [0, 1, 1, 0]; + qarr2 = qarr1; + } + ``` diff --git a/.internal/docs/support/index.md b/.internal/docs/support/index.md index e94bf1abe..db5d89159 100644 --- a/.internal/docs/support/index.md +++ b/.internal/docs/support/index.md @@ -87,7 +87,7 @@ Welcome to the Classiq Support Center. This page is designed to help you quickly Using `control`, you can define multi-qubit controls and gates. You can also use `if_` for classical control of quantum gates. See [Classical Control Flow](/latest/qmod-reference/language-reference/statements/classical-control-flow/). ??? note "How do I use controlled operations on multiple qubits instead of QArrays?" - There are two ways to work around this: either bind the qubits you want to a QArray (see [bind](/latest/qmod-reference/language-reference/statements/bind/)) or slice the QArrays (see [Path Operators](/latest/qmod-reference/language-reference/statements/numeric-assignment/#relational-operators)). + There are two ways to work around this: either bind the qubits you want to a QArray (see [bind](/latest/qmod-reference/language-reference/statements/bind/)) or slice the QArrays (see [Path Operators](/latest/qmod-reference/language-reference/expressions/#relational-operators)). ??? note "How do I apply a single-qubit gate to multiple qubits?" Use the `apply_to_all` function. See [Utility functions](/latest/qmod-reference/api-reference/functions/open_library/utility_functions/).