> ## Documentation Index
> Fetch the complete documentation index at: https://prod-mint.classiq.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Assignment

## Numeric Assignment

Scalar quantum variables (`qnum` and `qbit`) can be assigned the result of arithmetic/logical

<Card title="expressions" href="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
and in-place. When assigning the result of an expression out-of-place, a new quantum
object is allocated to store the result. For in-place assignment, the result
of the operation is stored back in the target variable.

### Syntax

<Tabs>
  <Tab title="Python">
    *target-var* **|=** *quantum-expression* <br />
    OR <br />
    **assign(***quantum-expression***,** *target-var*\*\*)\*\*

    *target-var* **^=** *quantum-expression* <br />
    OR <br />
    **inplace\_xor(***quantum-expression***,** *target-var*\*\*)\*\*

    *target-var* **+=** *quantum-expression* <br />
    OR <br />
    **inplace\_add(***quantum-expression***,** *target-var*\*\*)\*\*

    #### 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.
  </Tab>

  <Tab title="Native">
    *target-var* **=** *quantum-expression*

    *target-var* **^=** *quantum-expression*

    *target-var* **+=** *quantum-expression*
  </Tab>
</Tabs>

### Semantics

* *quantum-expression* consists of quantum scalar variables, numeric constant
  literals, and classical scalar variables, composed using arithmetic operators.
  See below the set of supported operators.
* The quantum variables occurring in the expression can subsequently be used, with their
  states unmodified.

#### Out-of-place assignment (`=`/`|=`)

* *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 be compatible with the computed numeric attributes of *quantum-expression*,
  that is, fit the entire range of possible expression values.

#### In-place XOR (`^=`)

* *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.

#### In-place add (`+=`)

* *target-var* must be initialized prior to the assignment.
* The result of *quantum-expression* is added to the numeric value of
  *target-var* according to the

<Card title="two's complement" href="https://en.wikipedia.org/wiki/Two%27s_complement" />

method.

* Superfluous fraction digits in *quantum-expression* are ignored.
  Superfluous fraction digits in *target-var* remain untouched.
* When *target-var* overflows or underflows, its value is wrapped-around the
  integer part (including the sign bit) without incurring additional qubits,
  following the two's complement method.

## 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

<Tabs>
  <Tab title="Python">
    *target-var* **|=** *assigned-var* <br />
    OR <br />
    **assign(***assigned-var***,** *target-var*\*\*)\*\*

    *target-var* **^=** *assigned-var* <br />
    OR <br />
    **inplace\_xor(***assigned-var***,** *target-var*\*\*)\*\*

    *array-var* **|=** *array-literal* <br />
    OR <br />
    **assign(***array-literal***,** *array-var*\*\*)\*\*

    *target-var* **^=** *array-literal* <br />
    OR <br />
    **inplace\_xor(***array-literal***,** *array-var*\*\*)\*\*

    #### 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.
  </Tab>

  <Tab title="Native">
    *target-var* **=** *assigned-var*

    *target-var* **^=** *assigned-var*

    *array-var* **=** *array-literal*

    *array-var* **^=** *array-literal*
  </Tab>
</Tabs>

### 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

### 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.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from classiq import *


    @qfunc
    def main(a: Output[QNum], b: Output[QNum], res: Output[QNum]):
        a |= 3
        prepare_state([0, 0.5, 0.5, 0], 0, b)  # 'b' is in superposition of 1 and 2
        res |= a + 2 * b + 3  # 'res' is in superposition of 8 and 10
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc main(output a: qnum, output b: qnum, output res: qnum) {
      a = 3;
      prepare_state([0, 0.5, 0.5, 0], 0, b); // 'b' is in superposition of 1 and 2
      res = a + 2 * b + 3;  // 'res' is in superposition of 8 and 10
    }
    ```
  </Tab>
</Tabs>

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 XOR 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.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from classiq import QNum, qfunc, QBit


    @qfunc
    def foo(res: QBit):
        a = QNum()
        b = QNum()
        a |= 3
        b |= 1
        res ^= a + 2 * b + 3 == 8  # expression is true so 'res' is flipped
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc foo(res: qbit) {
      a: qnum;
      b: qnum;
      a = 3;
      b = 1;
      res ^= (a + 2 * b + 3 == 8);  // expression is true so 'res' is flipped
    }
    ```
  </Tab>
</Tabs>

### 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.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    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):
        aux = QBit()
        allocate(aux)

        def assignment_stmt(var: QBit):
            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.
  </Tab>

  <Tab title="Native">
    ```
    qfunc my_oracle(x0: qbit, x1: qbit, x2: qbit, x3: qbit) {
      aux: qbit;
      allocate(aux);
      within {
        X(aux);
        H(aux);
      } apply {
        aux ^= (x0 and x1) or (x2 and x3);
      }
    }
    ```
  </Tab>
</Tabs>

### Example 4: In-place add assignment

The following model initializes two quantum numeric variables `n` and `m`.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from classiq import *


    @qfunc
    def main(m: Output[QNum[3, SIGNED, 2]], n: Output[QNum[3, SIGNED, 1]]):
        allocate(m)
        apply_to_all(X, m)
        allocate(n)
        n += m
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc main(output m: qnum&lt;3, SIGNED, 2>, output n: qnum&lt;3, SIGNED, 1>) {
      allocate(m);
      apply_to_all(X, m);
      allocate(n);
      n += m;
    }
    ```
  </Tab>
</Tabs>

Variable `m` has three qubits, of which one is a sign qubit and two are fraction
digits.
By applying `X` (not) to `m`'s qubit, we set its value to `-0.25`.
When adding `m` to `n` (`n += m`), the variables do not align since variable `n`
has one less fraction digit than `m`:

```
n = 00.0
m =  1.11
```

First, we ignore the last fraction digit of `m`:

```
n = 00.0
m =  1.1
```

Then, we extend `m` to the size of `n` (3) by duplicating the sign bit in
accordance with the two's complement method:

```
n = 00.0
m = 11.1
```

Finally, adding `m` to `n` sets `n`'s state to `111`, whose interpretation is
the numeric value `-0.5`.

### Example 5: Overflowing in-place add assignment

The following model demonstrates what happens to the target variable when its
value overflows, i.e., extends beyond the variable domain.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from classiq import *


    @qfunc
    def main(n: Output[QNum[3, UNSIGNED, 1]], m: Output[QNum[3, SIGNED, 1]]):
        allocate(n)  # n = 0
        n += 3.5  # n = 3.5
        n += 1  # n = 0.5, n still has 3 qubits
        allocate(m)  # m = 0
        m += 1.5  # m = 1.5
        m += 1  # m = -1.5, m still has 3 qubits
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc main(output n: qnum&lt;3, UNSIGNED, 1>, output m: qnum&lt;3, SIGNED, 1>) {
      allocate(n);  // n = 0
      n += 3.5;  // n = 3.5
      n += 1;  // n = 0.5, n still has 3 qubits
      allocate(m);  // m = 0
      m += 1.5;  // m = 1.5
      m += 1;  // m = -1.5, m still has 3 qubits
    }
    ```
  </Tab>
</Tabs>

### Example 6: Quantum subscript expression

The following model demonstrate quantum subscript expression over a classical
list `[7, 3, 6, 2]` and a quantum variable `index`.
The quantum `index` is in superposition over the indices 0 (10%), 1 (20%), 2
(30%), and 3 (40%).
The quantum subscript expression `[7, 3, 6, 2][index]` is in superposition over the
items `[7, 3, 6, 2]` entangled to `index`.
Overall, the output variable `n` evaluates to 7 (10%), 3 (20%), 6 (30%), or 2
(40%).

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from classiq import *
    from classiq.qmod.symbolic import subscript


    @qfunc
    def main(n: Output[QNum]):
        index = QNum()
        prepare_state([0.1, 0.2, 0.3, 0.4], 0, index)
        n |= subscript(
            [7, 3, 6, 2], index
        )  # n is 7, 3, 6, or 2 with increasing probability
        drop(index)
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc main(output n: qnum) {
      index: qnum;
      prepare_state([0.1, 0.2, 0.3, 0.4], 0, index);
      n = [7, 3, 6, 2][index];
      drop(index);
    }
    ```
  </Tab>
</Tabs>

### 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.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from classiq import qfunc, Output, QArray, QBit, allocate


    @qfunc
    def main(qarr1: Output[QArray], qarr2: Output[QArray]):
        allocate(4, qarr1)
        qarr1 ^= [0, 1, 1, 0]
        qarr2 |= qarr1
    ```
  </Tab>

  <Tab title="Native">
    ```
    qfunc main(output qarr1: qbit[], output qarr2: qbit[]) {
      allocate(4, qarr1);
      qarr1 ^= [0, 1, 1, 0];
      qarr2 = qarr1;
    }
    ```
  </Tab>
</Tabs>
