` should evaluate to an integer.
* The same variable cannot occur both in the condition and inside the statement block. This
restriction applies also to mutually exclusive slices of the same variable.
* Quantum variables declared outside the *control* statement and used in its condition or
inside its nested block must be initialized prior to it and remain initialized subsequently.
* Quantum variables declared inside the *control* statement, including in
nested function calls, must be uninitialized at the end of the statement.
## Examples
### Example 1: Single-qubit control
In the following example, `control` statement applies function `X` on the variable `target`
conditioned on a single qubit variable `qb`. Note that this is equivalent to using the
built-in gate-level function `CX`.
```python theme={null}
from classiq import *
@qfunc
def main(target: Output[QBit], ctrl: Output[QBit]):
allocate(ctrl)
H(ctrl)
allocate(target)
control(ctrl, lambda: X(target))
```
```
qfunc main(output target: qbit, output ctrl: qbit) {
allocate(ctrl);
H(ctrl);
allocate(target);
control (ctrl) {
X(target);
}
}
```
Synthesizing this model creates the quantum program shown below.
### Example 2: Multi-qubit control
The next example shows how `control` can be similarly used with multi-qubit control
variable. In this case `target` is rotated when the state of `qba` is the bit string 111.
```python theme={null}
from classiq.qmod.symbolic import pi
from classiq import *
@qfunc
def main(target: Output[QBit], ctrl: Output[QArray[QBit]]):
allocate(3, ctrl)
hadamard_transform(ctrl)
allocate(target)
control(ctrl, lambda: RX(pi / 2, target))
```
```
qfunc main(output target: qbit, output ctrl: qbit[]) {
allocate(3, ctrl);
hadamard_transform(ctrl);
allocate(target);
control (ctrl) {
RX(pi / 2, target);
}
}
```
Synthesizing this model creates the quantum program shown below.
### Example 3: Numeric equality condition
The following example demonstrates the use of `control` to rotate the state of a qubit
by an angle determined by another quantum variable. In this case the condition compares
the quantum variable with the repeat index.
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
@qfunc
def switch_rx(x: QNum, target: QBit):
repeat(4, lambda i: control(x == i, lambda: RX(pi / 2**i, target)))
@qfunc
def main(res: Output[QBit]):
allocate(res)
x = QNum()
allocate(2, x)
hadamard_transform(x)
switch_rx(x, res)
drop(x)
```
```
qfunc switch_rx(x: qnum, target: qbit) {
repeat (i: 4) {
control (x == i) {
RX(pi / (2 ** i), target);
}
}
}
qfunc main(output res: qbit) {
allocate(res);
x: qnum;
allocate(2, x);
hadamard_transform(x);
switch_rx(x, res);
drop(x);
}
```
Synthesizing this model creates the following quantum program. Note how `control`
is implemented as positive and negative controls in the respective numeric qubits.
### Example 4: Arithmetic condition
The following example demonstrates the use of `control` to rotate the state of a qubit
according to a condition imposed by another two quantum variables, `x` and `y`. Here, the condition
filters quantum states such that `y <= x[0] + x[1] + x[2]`.
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
@qfunc
def conditional_rx(x: QArray[QBit], y: QNum, target: QBit):
control(x[0] + x[1] + x[2] >= y, lambda: RX(pi / 3, target))
@qfunc
def main(res: Output[QBit]):
allocate(res)
x: QArray = QArray("x", QBit, 3)
y: QNum = QNum("y", 3, UNSIGNED, 0)
allocate(x)
allocate(y)
hadamard_transform(x)
hadamard_transform(y)
conditional_rx(x, y, res)
drop(x)
drop(y)
```
```
qfunc conditional_rx(x: qbit[], y: qnum, target: qbit) {
control (y <= ((x[0] + x[1]) + x[2])) {
RX(pi / 3, target);
}
}
qfunc main(output res: qbit) {
allocate(res);
x: qbit[3];
y: qnum<3, UNSIGNED, 0>;
allocate(x);
allocate(y);
hadamard_transform(x);
hadamard_transform(y);
conditional_rx(x, y, res);
drop(x);
drop(y);
}
```
Synthesizing this model creates the following quantum program. Note how `control`
is implemented as a result of an arithmetic computation. After applying the `control` operation,
the arithmetic operation is uncomputed.
### Example 5: Control else
The following example demonstrates the use of the `else` block in the `control` statement.
In this case, the `else` block applies an 'H' gate on the target qubit when the control
condition is not met, instead of the 'X' gate,
so when each qubit of the control variable is in state $|1\rangle$, the bit is flipped,
otherwise, the Hadamard gate is applied.
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QBit], ctrl: Output[QArray[QBit]]):
allocate(2, ctrl)
hadamard_transform(ctrl)
allocate(x)
control(ctrl, lambda: X(x), lambda: H(x))
```
```
qfunc main(output x: qbit, output ctrl: qbit[]) {
allocate(2, ctrl);
hadamard_transform(ctrl);
allocate(x);
control (ctrl) {
X(x);
} else {
H(x);
}
}
```
Synthesizing this model creates the following quantum program. Note how the `else` block
is implemented as a negation of the control condition, and the negation is uncomputed after
the `control` operation of the else block.
# Invert
Source: https://docs.classiq.io/qmod-reference/language-reference/statements/invert
The *invert* statement applies the adjoint (conjugate transpose) of the unitary operation
specified as a nested statement block. If the nested block specifies the unitary operation
$U$, *invert* applies $U^{\dagger}$.
## Syntax
[comment]: DO_NOT_TEST
```python theme={null}
def invert(stmt_block: QCallable) -> None:
pass
```
**invert** **\{** *statements* **}**
## Semantics
* The *invert* statement applies the adjoint of the operations specified in the nested
block, equivalent to the adjoint of each nested statement in reverse order.
* Quantum variables declared outside the *invert* statement and used inside its nested
block must be initialized prior to it and remain initialized subsequently.
* Quantum variables declared inside the *invert* statement, including in
nested function calls, must be uninitialized at the end of the statement.
## Example
The following example demonstrates the use of `invert` applied to a single gate-level
function call, and to a statement block in which a user-defined function `foo` is called twice.
```python theme={null}
from classiq.qmod.symbolic import pi
from classiq import *
@qfunc
def foo(target: QBit):
H(target)
X(target)
@qfunc
def main(qba: Output[QArray[QBit]]):
allocate(2, qba)
invert(lambda: RX(pi / 2, qba[0]))
invert(lambda: [foo(qba[0]), foo(qba[1])])
```
```
qfunc foo(target: qbit) {
H(target);
X(target);
}
qfunc main(output qba: qbit[]) {
allocate(2, qba);
invert {
RX(pi / 2, qba[0]);
}
invert {
foo(qba[0]);
foo(qba[1]);
}
}
```
Synthesizing this model creates the quantum program shown below. The inversion of
`RX` is simply negating the rotation angle. In the second `invert` statement each call to
`foo` is inverted, applying the gate-level functions in reverse but unchanged (as they
are hermitian).
# Phase
Source: https://docs.classiq.io/qmod-reference/language-reference/statements/phase
The *phase* statement is used to compute and encode the result of some
arithmetic computation in the phase of the respective quantum states. It applies
a relative phase to computational-basis states of quantum variables proportional
to the value of a specified expression over these variables. The *phase*
statement can also specify a fixed rotation angle, i.e., a "global" phase, using
an expression with no quantum variables. When a fixed phase rotation occurs
under a controlled context, it affects only the controlling states. Otherwise, a
fixed *phase* statement is undetectable.
*phase* statements with a quantum expression are often used to compute the cost
of an optimization problem. Applying a fixed *phase* is useful in expressing
phase oracles and reflections.
## Syntax
[comment]: DO_NOT_TEST
```python theme={null}
def phase(phase_expr: SymbolicExpr, coefficient: float = 1.0) -> None:
pass
```
**phase** **(** *phase-expression* \[ **,** *coefficient* ] **)**
## Semantics
* *phase-expression* may consist of quantum scalar variables, numeric constant
literals, and classical scalar variables, composed using arithmetic operators.
See below the set of supported operators.
* The *coefficient* expression is optional, and may include an execution
parameter. Note that an execution parameter cannot occur in *phase-expression* if it
contains quantum variables.
If not provided, the default coefficient value is 1.0.
* The operation rotates each computational basis state about the Z axis by an angle equal
to the value of *phase-expression*, multiplied by *coefficient* if specified.
* For *phase-expression* over quantum variable $x_1, x_2, \ldots, x_n$ that computes the
function $f(x_1, x_2, \ldots, x_n)$ and *coefficient* $=\theta$, the operation performed by
the statement is $|x\rangle \rightarrow e^{i\theta f(x_1, x_2, \ldots, x_n)} |x\rangle$.
* For *phase-expression* without quantum variables that evaluates to $\theta$, the operation
performed by the statement is $|x\rangle \rightarrow e^{i\theta} |x\rangle$.
* The expression must be a polynomial in the quantum variables. It is compiled into an Ising-model
Hamiltonian, which is evolved per the specified coefficient.
The following operators are supported:
* Add: `+`
* Subtract: `-` (binary)
* Negate: `-` (unary)
* Multiply: `*`
* Divide: `/` (by a classical value)
* Power: `**` (quantum base, positive classical integer exponent)
The following operators are supported only when applied to `QBit`, `QNum[1]`,
and the classical integers `0` and `1`:
* Bitwise Or: `|`
* Bitwise And: `&`
* Bitwise Xor: `^`
* Bitwise Not: `~`
Note that when the expression consists of a single one-qubit variable, *phase* statement
is equivalent to the core-library function `PHASE()`.
## Examples
### Example 1
In the following model phase $x^2$ is applied to variable $x$ with the coefficient $\frac{\pi}{4}$.
$x$ is initialized to a superposition of the values 0, 1, 2, and 3. After the *phase*
statement, state 1 is in phase $\frac{\pi}{4}$ relative to state 0, state 2
is rotated $\pi$ relative to state 0. State 3 is rotated $\frac{\pi}{4}$,
which is a full $2\pi$ + $\frac{\pi}{4}$ rotation, that is, the same phase as state 1.
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
@qfunc
def main(x: Output[QNum]):
allocate(2, x)
hadamard_transform(x)
phase(x**2, pi / 4)
```
```
qfunc main(output x: qnum) {
allocate(2, x);
hadamard_transform(x);
phase (x**2, pi/4);
}
```
Visualizing the synthesized quantum program, you can see how Z-rotations and controlled
Z-rotations are used to achieve the required rotation.
When executing this model using a state-vector simulator, the relative phases of the
different states can be observed. In
### Example 2
The following example demonstrates the use of *phase* statement to encode the cost of a
max-cut problem, as the implementation of the cost-layer in a QAOA ansatz. The qubit
array `v` represents the partition of the set of vertices in a graph into two, and
the expression inside the *phase* statement computes the number of edges that cross the
partition. Executing this model with the right set of parameter values will yield with
high probability an optimal solution.
```python theme={null}
from classiq import *
@qfunc
def main(
gammas: CArray[CReal, 4],
betas: CArray[CReal, 4],
v: Output[QArray[QBit, 3]],
):
allocate(v)
hadamard_transform(v)
for i in range(4):
phase(
(v[0] * (1 - v[1]) + v[1] * (1 - v[0])) # edge 0-1
+ (v[0] * (1 - v[2]) + v[2] * (1 - v[0])), # edge 0-2
gammas[i],
)
apply_to_all(lambda q: RX(betas[i], q), v)
```
```
qfunc main(gammas: real[4], betas: real[4], output v: qbit[3]) {
allocate(v);
hadamard_transform(v);
repeat (i: 4) {
phase(
(v[0] * (1 - v[1]) + v[1] * (1 - v[0])) // edge 0-1
+ (v[0] * (1 - v[2]) + v[2] * (1 - v[0])), // edge 0-2
gammas[i]
);
apply_to_all(lambda(q) {
RX(betas[i], q);
}, v);
}
}
```
### Example 3
The following model applies `phase` with an angle specified as a classical
expression, thus inserting a fixed phase under controlled contexts. In each
case, the states that satisfy the control condition rotate by $\frac{\pi}{4}$
relative to those that do not.
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
@qfunc
def main(qarr: Output[QArray[QBit, 2]]):
allocate(qarr)
hadamard_transform(qarr)
control(qarr[0], lambda: phase(pi / 4))
control(qarr, lambda: phase(pi / 4))
```
```
qfunc main(output qarr: qbit[2]) {
allocate(qarr);
hadamard_transform(qarr);
control (qarr[0]) {
phase (pi / 4);
}
control (qarr) {
phase (pi / 4);
}
}
```
The cumulative result of both statements revealed by running a state-vector
simulation is a uniform superposition of the four states with the following
phases:
$$
\begin{aligned}
|[0,0]\rangle&: 0 \\
|[0,1]\rangle&: 0 \\
|[1,0]\rangle&: \frac{\pi}{4} \\
|[1,1]\rangle&: \frac{\pi}{2} \\
\end{aligned}
$$
# Power
Source: https://docs.classiq.io/qmod-reference/language-reference/statements/power
The *power* statement applies the unitary operation raised to some integer power,
where the unitary is specified as a nested statement block.
## Syntax
[comment]: DO_NOT_TEST
```python theme={null}
def power(exponent: CInt, stmt_block: QCallable) -> None:
pass
```
**power** **(** *exponent* **)** **\{** *statements* **}**
## Semantics
* If the statement block specifies the unitary operation $U$ on some quantum object,
*power* applies $U^{exponent}$.
* In the general case, the statement block is iterated over *exponent* times, but in some important
special cases the operation is implemented more efficiently.
* Quantum variables declared outside the *power* statement and used inside its nested
block must be initialized prior to it and remain initialized subsequently.
* Quantum variables declared inside the *power* statement, including in
nested function calls, must be uninitialized at the end of the statement.
## Examples
In the following example `power` is applied 3 times - to gate-level functions `H` and `RX`,
and to a user-defined function `foo`. It demonstrates both special and general treatment
of the *power* operation.
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
@qfunc
def foo(p: CInt, q: QBit):
power(p, lambda: H(q))
power(p, lambda: PHASE(pi / 8, q))
@qfunc
def main(q: Output[QBit]):
allocate(q)
power(2, lambda: foo(5, q))
```
```
qfunc foo(p: int, q: qbit) {
power (p) {
H(q);
}
power (p) {
PHASE(pi / 8, q);
}
}
qfunc main() {
q: qbit;
allocate(q);
power (2) {
foo(5, q);
}
}
```
Synthesizing this model creates the quantum program shown below.
Because two consecutive applications of `H` cancel each other out, raising `H` to the power
of 5 is equivalent to applying `H` once. Raising `RX` with rotation angle $\pi / 8$ to the
power 5 is equivalent to applying `RX` with rotation angle $5 \times \pi / 8$. However, raising
`foo` to the power 2 requires 2 consecutive applications of `foo`.
# Skip Control
Source: https://docs.classiq.io/qmod-reference/language-reference/statements/skip-control
The *skip-control* statement designates a statement block that should be applied
unconditionally, even when the enclosing function is subject directly or
indirectly to a [quantum control operator](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/control/).
This construct is typically applied when the enclosing function involves
intermediate computation and uncomputation blocks in ways that cannot be
formulated using a simple conjugation (i.e., using the *within-apply* statement).
## Syntax
[comment]: DO_NOT_TEST
```python theme={null}
def skip_control(stmt_block: QCallable) -> None:
pass
```
**skip\_control** **\{** *statements* **}**
## Semantics
* All statements nested under a *skip-control* statement are applied
unconditionally, including in states where a control condition from above is
evaluated to `False`. It is the user's responsibility to ensure that the
combined effect of the *skip-control* blocks in the enclosing function is
functionally equivalent to NOP (identity).
* Using *skip-control* inside the *within* block of a *within-apply* statement
is redundant, since the *within* block is itself designated as a
*skip-control* block.
* Using *skip-control* directly inside the *apply* block of a *within-apply*
statement is not allowed.
## Example
The following example demonstrates the use of `skip_control`. Function `foo`
rotates a qubit in steps, applying a controlled flip of other qubits at each
step. The controlling qubit ultimately returns to its original state. The
rotations are marked with `skip_control` because they can be safely applied even
for states where the whole function is under a negative control condition, as
demonstrated by function `main`.
Note that the computation of `qarr[0]` within `foo` cannot be encapsulated in an
*apply* block of a *within-apply* statement.
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
@qfunc
def foo(qarr: QArray[QBit, 5]):
repeat(
4,
lambda i: [
CX(qarr[0], qarr[i + 1]),
skip_control(lambda: RX(pi / 2, qarr[0])),
],
)
@qfunc
def main(ctrl: Output[QBit], qarr: Output[QArray[QBit, 5]]):
allocate(qarr)
hadamard_transform(qarr[0])
allocate(ctrl)
hadamard_transform(ctrl)
control(ctrl, lambda: foo(qarr))
```
```
qfunc foo(qarr: qbit[5]) {
repeat (i: 4) {
CX(qarr[0], qarr[i+1]);
skip_control {
RX(pi/2, qarr[0]);
}
}
}
qfunc main(output ctrl: qbit, output qarr: qbit[5]) {
allocate(qarr);
hadamard_transform(qarr[0]);
allocate(ctrl);
hadamard_transform(ctrl);
control(ctrl) {
foo(qarr);
}
}
```
# Within-apply
Source: https://docs.classiq.io/qmod-reference/language-reference/statements/within-apply
The *within-apply* statement performs the common quantum pattern $U^{\dagger} V U$. It
operates on two nested statement blocks, the *within* block and the *apply* blocks,
and evaluates the sequence - *within*, *apply*, and *invert(within)*. Under conditions
described below, quantum objects that are allocated and prepared by the *within* block
are subsequently uncomputed and released.
## Syntax
[comment]: DO_NOT_TEST
```python theme={null}
def within_apply(within: Callable, apply: Callable) -> None:
pass
```
**within** **\{** *within-statements* **}** **apply** **\{** *apply-statements* **}**
## Semantics
* Unlike the case with other statements, the nested blocks of *within-apply* may initialize
outer context variables.
* Variables that are initialized inside the *within* block of a *within-apply* statement,
are returned to their uninitialized state after the statement completes.
* All quantum objects allocated directly or indirectly under the *within* block
are uncomputed, and their qubits are reclaimed for subsequent use after the statement
completes.
* In addition to the general restriction of local variables to *permutable* use contexts,
variables initialized inside the *within* block and their dependents can only be
used in *const* contexts inside the *apply* block. See more on uncomputation rules
under [Uncomputation](/qmod-reference/language-reference/uncomputation).
* The application of the *within* block and its inverse are not subjected to redundant control logic in
the case where the *within-apply* statement as a whole is subject to control.
* The application of the *within* block and its inverse are guaranteed to be strictly equivalent, including
in the case where *within* block involves non-deterministic implementation decisions by the
synthesis engine.
## Examples
### Example 1
The following example demonstrates how auxiliary qubits get used, uncomputed, and reused
at different steps of a computation, when scoped inside a *within-apply* statement.
Actual reuse is a decision the synthesis engine takes to satisfy width constraints.
```python theme={null}
from classiq import *
@qfunc
def main(res: Output[QBit]):
allocate(res)
ctrl = QNum()
within_apply(lambda: assign(3, ctrl), lambda: CCX(ctrl, res))
within_apply(lambda: assign(2, ctrl), lambda: CCX(ctrl, res))
```
```
qfunc main(output res: qbit) {
allocate(res);
ctrl: qnum;
within {
ctrl = 3;
} apply {
CCX(ctrl, res);
}
within {
ctrl = 2;
} apply {
CCX(ctrl, res);
}
}
```
Note how variable `ctrl` is initialized in the
*within* block, prior to being used for the `CCX` in the *apply* block.
Outside the *within-apply* statement the variable is reset to its uninitialized state,
and used again in the same way.
Visualizing the resulting quantum program, you can see how the same two auxiliary
qubits are reused across the two steps of the circuit, because of width optimization.
### Example 2
The code snippet below demonstrates the implementation of the phase kickback pattern
for an arbitrary quantum predicate. Function `my_phase_oracle` takes as parameter a
function that flips a qubit on the states of interest. Variable `aux` is prepared
in the $|1\rangle$ state and passed as the target to function `my_cond_phase_flip`. The
cumulative effect of `my_cond_phase_flip` is a conditional $\pi$ phase on `target`, controlled
on the states of interest. Since `aux` is subsequently uncomputed and released, a
relative $\pi$ phase remains between the states of interest and all others in the
superposition.
```python theme={null}
from classiq import *
@qperm(disable_perm_check=True, disable_const_checks=True)
def my_cond_phase_flip(predicate: QPerm[QBit], target: Const[QBit]):
H(target)
predicate(target)
H(target)
@qperm
def my_phase_oracle(predicate: QPerm[QBit]):
aux = QBit()
within_apply(
lambda: (allocate(aux), X(aux)), lambda: my_cond_phase_flip(predicate, aux)
)
```
```
@disable_perm_check
@disable_const_checks
qperm my_cond_phase_flip(predicate: qperm (qbit), const target: qbit) {
H(target);
predicate(target);
H(target);
}
qperm my_phase_oracle(predicate: qperm (qbit)) {
aux: qbit;
within {
allocate(aux);
X(aux);
} apply {
my_cond_phase_flip(predicate, aux);
}
}
```
Note that `my_cond_phase_flip` declares parameter `target` as `const` because, taken as
a whole, the function only applies phase changes to it. But because the implementation
uses non-cost operations, we disable const checks. For more on enforcement
of parameter restrictions see [Uncomputation](/qmod-reference/language-reference/uncomputation).
### Example 3
The code snippet below demonstrates the use of *within-apply* to define the Grover operator,
avoiding redundant control logic when called in higher-level contexts (for example, when
used as the unitary operand in a phase-estimation flow):
```python theme={null}
from classiq import *
@qfunc
def my_grover_operator(
oracle: QCallable[QArray[QBit]],
space_transform: QCallable[QArray[QBit]],
target: QArray[QBit],
):
oracle(target)
within_apply(
lambda: invert(lambda: space_transform(target)),
lambda: reflect_about_zero(target),
)
```
```
qfunc my_grover_operator(oracle: qfunc (qbit[]), space_transform: qfunc (qbit[]), target: qbit[]) {
oracle(target);
within {
invert {
space_transform(target);
}
} apply {
reflect_about_zero(target);
}
}
```
# Uncomputation
Source: https://docs.classiq.io/qmod-reference/language-reference/uncomputation
Uncomputation is the process of reversing the effects of quantum operations,
restoring the state of qubits to their initial $|0\rangle$ state and
disentangling them from other qubits. Failing to
properly uncompute intermediate results can lead to incorrect final measurement
results and wasted resources. In Qmod, intermediate results are typically
stored in local variables, which are scoped inside a function and are
inaccessible outside of it. Hence, local variables must be used in a way that
enables subsequent uncomputation. Specifically, their interactions with other
objects must be restrictive to be subsequently disentangled from them.
In Qmod, local variables are **automatically uncomputed**, lifting the burden
of manually uncomputing intermediate results. When finer-grained control is
required, allocate the variable inside the *within* block of a
[*within-apply*](/qmod-reference/language-reference/statements/within-apply) statement. Such variables are
subject to strict rules that guarantee their correct uncomputation.
In this way, Qmod abstracts away the implementation details of efficient quantum
storage management and prevents a class of functional bugs that are very
difficult to detect.
A fully manual uncomputation can be achieved by using [free](/qmod-reference/language-reference/quantum-variables#free),
as variables which are explicitly freed are not subject to these rules.
To enable these capabilities, quantum operations are classified into arbitrary
functions and *permutation*-only functions. In addition, each of an operation's
parameters is classified as either *const* or *non-const*.
* **permutation**: A quantum operation is a *permutation* if it maps
computational-basis states to computational-basis states (with possible
phase shifts). Such an operation neither introduces nor destroys quantum
superpositions, and its computation can be described classically.
* **const**: A parameter of a quantum operation is constant if it is
immutable up to a phase. That is, the magnitudes of its computational-basis
state components remain unchanged, while their phases may shift.
*permutation* functions are explicity declared using the keyword
`qperm`. *const* parameters are explicity declared using the keyword
`const`. See more under [Function Declarations](/qmod-reference/language-reference/functions).
* `Z` is a *permutation* and its parameter is *const* as it merely flips the phase
of the $|1\rangle$ state.
* `X` is a *permutation* but its parameter is not *const* as it flips between
$|0\rangle$ and $|1\rangle$.
* `H` is not a *permutation* and its parameter is not *const*, as it
introduces superposition.
* `SWAP` is a *permutation* but its two parameters are not *const*, as it
swaps between $|01\rangle$ and $|10\rangle$.
## Quantum operations classification
Each quantum operation is classified as either an arbitrary mutation of the quantum
state or strictly a *permutation* of computational-basis states, according to the
following rules:
* A function call is a *permutation* if the callee is declared as `qperm`.
* A numeric assignment (both out-of-place and in-place) is a *permutation*.
* Amplitude-encoding assignment is *non-permutation*.
* Phase statement is a *permutation*.
* A compound statement is a *permutation* if its body contains only *permutation*
operations. For example, a *control* statement is a *permutation* if all
statements inside its *then* and *else* clauses are *permutations*.
* Bind statement is considered a *permutation*, as are `allocate` and
`free`.
In addition, each use of a quantum variable is classified as either *const* or
*non-const*:
* An argument in a function call is classified according to the modifier used
in the matching parameter declaration.
* Use as right-value quantum expression is *const*. Right-value expressions
occur in the following contexts:
* On the right-hand side of a numeric assignment or amplitude-encoding assignment.
* As the condition in a *control* statement.
* As the argument of a *phase* statement.
* Use as left-value expression in numeric assignments (both out-of-place and
in-place) and amplitude-encoding assignments is *non-const*.
* Arguments to a *bind* statement are treated specially: they are not
immediately classified, but are instead bound together and assigned a
joint classification of either *const* or *non-const*.
### Enforcement of function classification
Generally, a `qperm` function is restricted to use only *permutation*
operations, and a `const` parameter is restricted to *const* use contexts.
Violation of these restrictions results in a compilation error.
However, flexibility is often required in the implementation of lower-level
building blocks. The cumulative effect of the function on the quantum
parameters in these cases satisfies its declared restrictions, but individual
operations violate it. Well known examples are the implementation of Toffoli gate,
and arithmetic addition in the Fourier bases. Both are permutation-only operations
taken as a whole, but internally use Hadamard gates and rotations.
It is not scalable to validate the correct cumulative effect of a description
automatically in the general case. However, you can suppress the fine-grained
enforcement of function classification with the `disable_perm_check` and
`disable_const_checks` specifiers using the following syntax:
The decorators `@qfunc` and `@qperm` have the optional parameters
`disable_perm_check` and `disable_const_checks` declared thus -
disable\_perm\_check: bool = False
disable\_const\_checks: Union\[list\[str], bool] = False
`disable_const_checks` may contain a list of parameter names, or a boolean
to disable the checks for all *const* parameters.
Before a function definition you may specify the following decorators:
**@disable\_perm\_check**
**@disable\_const\_checks** \[ **(** *parameters* **)** ]
Where *parameters* is an optional list of comma-separated parameter names (if
the list is omitted, the checks are disabled for all *const* parameters).
When `disable_perm_check` is used, the compiler does not enforce the usage of
*non-permutation* operations. When `disable_const_checks` is used, the compiler
does not enforce use context restrictions on the listed parameters (or all
parameters if none specified).
### Examples
#### Example 1 - Correct use of permutation and const parameters
In the example below, function `foo` is declared `qperm`, and its first
parameter `param1` is declared `const`. The definition of `foo` is consistent
with these declarations. Note that the restriction on `param1` is carried over
to its use in the lambda expression passed to `apply_to_all`.
```python theme={null}
from classiq import *
@qperm
def foo(param1: Const[QNum], param2: Output[QNum]):
param2 |= param1 + 1 # OK - assignment is a permutation and RHS is const
apply_to_all(lambda qb: Z(qb), param1) # OK - the parameter of 'Z' is const
```
```
qperm foo(const param1: qnum, output param2: qnum) {
param2 = param1 + 1; // OK - assignment is a permutation and RHS is const
apply_to_all(lambda(qb) {
Z(qb);
}, param1); // OK - the parameter of 'Z' is const
}
```
#### Example 2 - Incorrect use of permutation and const parameters
The example below demonstrates violations of the restrictions on the use of
parameters and operations. As in the previous example, the function `foo` is
declared `qperm` and its first parameter `param1` is declared `const`. However,
the use of `param1` violates the restriction, and the function uses a
*non-permutation* operation as well.
```python theme={null}
from classiq import *
@qperm
def foo(param1: Const[QNum], param2: Output[QNum]):
param1 += 2 # Error - LHS is non-const
hadamard_transform(param2) # Error - 'hadamard_transform' is non-permutation
```
```
qperm foo(const param1: qnum, output param2: qnum) {
param1 += 2; // Error - LHS is non-const
hadamard_transform(param2); // Error - 'hadamard_transform' is non-permutation
```
#### Example 3 - Disabling permutation check
In the example below, function `my_cx` implements the CX operation using a
simple equivalence - applying phase flip in the Hadamard basis. The cumulative
operation on the quantum state is a *permutation*, but individual calls to `H` are
not. The `disable_perm_check` is used to suppress compiler errors in this case.
```python theme={null}
from classiq import *
@qperm(disable_perm_check=True)
def my_cx(ctrl: Const[QBit], tgt: QBit):
H(tgt)
CZ(ctrl, tgt)
H(tgt)
```
```
@disable_perm_check
qperm my_cx(const ctrl: qbit, tgt: qbit) {
H(tgt);
CZ(ctrl, tgt);
H(tgt);
}
```
#### Example 4 - Disabling permutation check and const checks
In the example below, function `my_z` implements the Z operation using a
simple equivalence - applying bit flip in the Hadamard basis. The cumulative
operation on the quantum state is a *permutation*, but individual calls to `H` are
not. Also, the cumulative operation on the `tgt` is *const*, but individual
calls are not.
The `disable_perm_check` and `disable_const_checks` are used to suppress
compiler errors in this case.
```python theme={null}
from classiq import *
@qperm(disable_perm_check=True, disable_const_checks=True)
def my_z(tgt: Const[QBit]):
H(tgt)
X(tgt)
H(tgt)
```
```
@disable_perm_check
@disable_const_checks
qperm my_z(const tgt: qbit) {
H(tgt);
X(tgt);
H(tgt);
}
```
## Semantics of uncomputation
When a variable is initialized inside the *within* block of a [*within-apply*](/qmod-reference/language-reference/statements/within-apply)
statement, it is returned to its uninitialized state after the statement
completes. The newly allocated quantum object is uncomputed, and its qubits are
reclaimed by the compiler for subsequent use. Likewise, a variable declared locally
within a function is only accessible inside the function's scope. The quantum object
allocated inside the function may be uncomputed at some later point and its
qubits reclaimed.
Local variables are considered *uncomputation candidates* if they remain initialized at the
end of the function scope in which they were declared. Variables initialized inside a
*within* block of a *within-apply* statement are also considered uncomputation candidates
in the scope of the statement.
The following rules guarantee that uncomputation candidates can be handled
correctly:
* An uncomputation candidate must not be used in a *non-permutation* operation.
* A variable becomes a *dependency* of an uncomputation candidate when used
in an operation together with the candidate variable, and the latter is used in
a *non-const* context. From that point, the dependency variable is subject to
the same rules as the candidate variable, while the latter is in scope.
* An auto-uncomputation candidate must not be used in an operation together
with a non-local variable if both use contexts are *non-const*.
* An auto-uncomputation candidate must not become a *dependency*
of any variable that already (directly or indirectly) depends on it —
that is, circular dependencies are not allowed.
* A variable initialized inside a *within* block of a *within-apply* statement can
only be used in *const* contexts inside the *apply* block.
Violating these rules will result in a compilation error.
The operations [`free`](/qmod-reference/language-reference/quantum-variables#free) and
[`drop`](/qmod-reference/language-reference/quantum-variables#drop) return the variable to its
uninitialized state, so it is consequently not considered an uncomputation
candidate and therefore does not undergo automatic uncomputation or any
uncomputation validation.
### Examples
#### Example 1 - Automatic uncomputation
The example below demonstrates the use of a local variable and its automatic uncomputation.
Variable `aux` is initialized as the left-value expression of an assignment statement, which is a *permutation*
operation. Subsequently, it is used as the condition of a *control*
statement, which is a *const* context. Both uses are valid, and the variable is
automatically uncomputed and freed correctly at the end of the function.
```python theme={null}
from classiq import *
@qperm
def foo(qn: QNum, res: QBit):
aux = QBit()
aux |= qn > 1
control(aux, lambda: X(res))
@qfunc
def main(qn: Output[QNum], res: Output[QBit]):
allocate(2, qn)
hadamard_transform(qn)
allocate(res)
foo(qn, res)
foo(qn, res)
```
```
qperm foo(qn: qnum, res: qbit) {
aux: qbit;
aux = qn > 1;
control(aux) {
X(res);
}
}
qfunc main(output qn: qnum, output res: qbit) {
allocate(2, qn);
hadamard_transform(qn);
allocate(1, res);
foo(qn, res);
foo(qn, res);
}
```
In the synthesized quantum program, variable `aux` is uncomputed and reused across the multiple calls to `foo`,
as can be seen in the visualization:
#### Example 2 - Illegal use of local variable
The example below demonstrates illegal use of a local variable in a function
which outputs only one qubit of a Bell pair, making it impossible to uncompute
the other qubit. Specifically, the local variable `q2` undergoes a *non-permutation*
operation, which is flagged as an error.
```python theme={null}
from classiq import *
@qfunc
def main(q1: Output[QBit]):
q2 = QBit()
allocate(q1)
allocate(q2)
H(
q2
) # Error - The local variable 'q2' cannot be automatically uncomputed because it is mutated by a non-permutation operation.
CX(q2, q1)
```
```
qfunc main(output q1: qbit) {
q2: qbit;
allocate(q1);
allocate(q2);
H(q2); // Error - The local variable 'q2' cannot be automatically uncomputed because it is mutated by a non-permutation operation.
CX(q2, q1);
}
```
#### Example 3 - Illegal use of local variable due to parameter mutation
The example below demonstrates an illegal use of a local variable `aux`, as it is used as an argument
in a call to function `x_transform` together with the variable `p`, where both parameters
of `x_transform` are declared *non-const*.
```python theme={null}
from classiq import *
@qperm
def x_transform(q1: QBit, q2: QBit):
X(q1)
X(q2)
@qfunc
def main(p: Output[QBit]):
aux = QBit()
allocate(p)
allocate(aux)
x_transform(
p, aux
) # Error - The local variable 'aux' cannot be automatically uncomputed because it is mutated by an operation which also mutates the parameter 'p'.
```
```
qperm x_transform(q1: qbit, q2: qbit) {
X(q1);
X(q2);
}
qfunc main(output p: qbit) {
aux: qbit;
allocate(p);
allocate(aux);
x_transform(p, aux); // Error - The local variable 'aux' cannot be automatically uncomputed because it is mutated by an operation which also mutates the parameter 'p'.
}
```
#### Example 4 - Illegal use of local variable due to circular dependency
The example below demonstrates an illegal use of the local variable `aux`, as
the two calls to the function `CX` create a circular dependency between it and
the variable `p`.
```python theme={null}
from classiq import *
@qfunc
def main(p: Output[QBit]):
aux = QBit()
allocate(p)
allocate(aux)
CX(
p, aux
) # Error - The local variable 'aux' cannot be automatically uncomputed because it forms a circular dependency with the variable 'p'.
CX(aux, p)
```
```
qfunc main(output p: qbit) {
aux: qbit;
allocate(p);
allocate(aux);
CX(p, aux); // Error - The local variable 'aux' cannot be automatically uncomputed because it forms a circular dependency with the variable 'p'.
CX(aux, p);
}
```
#### Example 5 - Correct uncomputation in within-apply
The example below demonstrates the use of a local variable initialized inside a
*within* block of a *within-apply* statement. Variable `aux` is initialized as
the left-value expression of an assignment statement, which is a *permutation*
operation. In the *apply* block, it is used as the condition of a *control*
statement, which is a *const* context. Both uses are valid, and the variable is
uncomputed and freed correctly after the *within-apply* statement.
```python theme={null}
from classiq import *
@qfunc
def main(qn: Output[QNum], res: Output[QBit]):
allocate(2, qn)
hadamard_transform(qn)
allocate(res)
aux = QBit()
within_apply(
within=lambda: assign(qn > 1, aux), apply=lambda: control(aux, lambda: X(res))
)
```
```
qfunc main(output qn: qnum, output res: qbit) {
allocate(2, qn);
hadamard_transform(qn);
allocate(1, res);
aux: qbit;
within {
aux = qn > 1;
} apply {
control (aux) {
X(res);
}
}
}
```
#### Example 6 - Illegal use of local variable in within-apply
The code below is a modification of *Example 1* above, with a couple of lines
added to demonstrate violations of the rules for correct use of a variable
initialized inside the *within* block of a *within-apply* statement. Here,
variable `aux` is also used as the argument of function `H` in the *within*
block. This is an arbitrarily *non-permutation* operation (indeed `H` introduces
superposition between computational-basis states). In addition, `aux` is used
as the argument of function `X` in the *apply* block, which is *non-const*
context. Both uses are illegal, and both are reported as errors by the
compiler.
```python theme={null}
from classiq import *
@qfunc
def main(qn: Output[QNum], res: Output[QBit]):
allocate(2, qn)
hadamard_transform(qn)
allocate(res)
aux = QBit()
within_apply(
within=lambda: (
assign(qn > 1, aux),
H(aux),
),
apply=lambda: (
control(aux, lambda: X(res)),
X(aux),
),
)
```
```
qfunc main(output qn: qnum, output res: qbit) {
allocate(2, qn);
hadamard_transform(qn);
allocate(1, res);
aux: qbit;
within {
aux = qn > 1;
H(aux);
} apply {
control (aux) {
X(res);
}
X(aux);
}
}
```
#### Example 7 - Illegal use of dependent variable in within-apply
The following example demonstrates a violation of the rules for correct use of
a dependent variable inside a *within-apply* statement. Here, variable `aux` is
initialized inside a *within* block, and is subsequently entangled with `q1`
which is not an uncomputation candidate. From that point, the same restrictions
that hold for `aux` apply to `q1`. Therefore, using it as an argument to
function `H` is illegal, and is reported as an error. Indeed, if `foo` would
execute as specified, `aux` would not be uncomputed correctly.
```python theme={null}
from classiq import *
@qfunc
def foo(q1: QBit, q2: QBit):
aux = QBit()
within_apply(
within=lambda: (
allocate(aux),
CX(q1, aux),
H(q1),
),
apply=lambda: (CX(aux, q2), Z(q1)),
)
```
```
qfunc foo(q1: qbit, q2: qbit) {
aux: qbit;
within {
allocate(1, aux);
CX(q1, aux);
H(q1);
} apply {
CX(aux, q2);
Z(q1);
}
}
```
# qDrift
Source: https://docs.classiq.io/qmod-reference/library-reference/core-library-functions/hamiltonian_evolution/qdrift/qdrift
Open this notebook in GitHub to run it yourself
The `qdrift` function implements the qDrift Trotter evolution of Ref.[ \[1\] ](#qdrift).
Function: `qdrift`
Arguments:
* `pauli_operator`: `CArray[PauliTerm]`,
* `evolution_coefficient`: `CReal`,
* `num_qdrift`: `CInt`,
* `qbv`: `QArray[QBit]`,
## Example
```python theme={null}
from classiq import *
@qfunc
def main(qba: Output[QArray[QBit]]):
allocate(2, qba)
qdrift(
Pauli.X(0) * Pauli.Y(1) + 0.5 * Pauli.Z(0),
evolution_coefficient=2.0,
num_qdrift=5,
qbv=qba,
)
qprog = synthesize(main)
```
## References
\[1] E. Campbell, Random Compiler for Fast Hamiltonian Simulation, (2019). [https://arxiv.org/abs/1811.08017](https://arxiv.org/abs/1811.08017)
# Suzuki Trotter
Source: https://docs.classiq.io/qmod-reference/library-reference/core-library-functions/hamiltonian_evolution/suzuki_trotter/suzuki_trotter
Open this notebook in GitHub to run it yourself
The `suzuki_trotter` function produces the Suzuki-Trotter product for a given order and repetitions.
Given a Hamiltonian as a sum of Pauli strings
$$
H = \sum^L_{k=1} \alpha_k H_k,
$$
the Suzuki-Trotter formula of order $o$ and repetitions $r$ approximates the Hamiltonian simulation $U = e^{-iHt}$ according to the following:
* Each order $ST^{(o)}(H,t)$ is defined recursively:
* The first order is : $ST^{(1)}(H,t) = \Pi^L_{k=1} e^{-iH_k t}$
* The second order is : $ST^{(2)}(H,t) = \Pi^L_{k=1} e^{-iH_k t/2} \Pi^1_{k=L} e^{-iH_k t/2}$
* Recursion formula for order $2m$ with $m>1$ is given in Eq. (5) of Ref. \[[2](#childs)]
* For a given order, repetitions refers to
$$
ST^{(o,r)}(H,t) = [ST^{(o)}(H,t/r)]^r.
$$
Function: `suzuki_trotter`
Arguments:
* `pauli_operator`: `CArray[PauliTerm]`
* `evolution_coefficient`: `CReal`
* `order`: `CInt`,
* `repetitions`: `CInt`,
* `qbv`: `QArray[QBit]`
## Example
```python theme={null}
from classiq import *
@qfunc
def main(x: CReal, qba: Output[QArray[QBit]]):
allocate(3, qba)
suzuki_trotter(
[
PauliTerm(pauli=[Pauli.X, Pauli.X, Pauli.Z], coefficient=1.5),
PauliTerm(pauli=[Pauli.Y, Pauli.X, Pauli.Z], coefficient=0.5),
],
evolution_coefficient=x,
order=1,
repetitions=1,
qbv=qba,
)
qprog = synthesize(main)
```
## References
\[1] N. Hatano and M. Suzuki, Finding Exponential Product Formulas of Higher Orders, (2005). [https://arxiv.org/abs/math-ph/0506007](https://arxiv.org/abs/math-ph/0506007)
\[2] Childs, et al., Toward the first quantum simulation with quantum speedup, (2018). [https://arxiv.org/abs/1711.10980](https://arxiv.org/abs/1711.10980)
# State Preparation
Source: https://docs.classiq.io/qmod-reference/library-reference/core-library-functions/prepare_state_and_amplitudes/prepare_state_and_amplitudes
Open this notebook in GitHub to run it yourself
Most quantum applications start with preparing a state in a quantum register.
For example, in finance the state may represent the price distribution of some assets.
In chemistry, it may be an initial guess for the ground state of a molecule, and in
a quantum machine learning, a feature vector to analyze.
The state preparation functions creates a quantum program that
outputs either a probability distribution $p_{i}$ or a real amplitudes
vector $a_{i}$ in the computational basis, with $i$ denoting the corresponding
basis state.
The amplitudes take the form of list of float numbers.
The probabilities are a list of positive numbers.
This is the resulting wave function for probability:
$$
\left|\psi\right\rangle = \sum_{i}\sqrt{p_{i}}
\left|i\right\rangle,
$$
and this is for amplitude:
$$
\left|\psi\right\rangle = \sum_{i}a_{i}
\left|i\right\rangle.
$$
In general, state preparation is hard.
Only a very small portion
of the Hilbert space can be prepared efficiently (in $O(poly(n))$
steps) on a quantum program. Therefore, in practice, an approximation
is often used to lower the complexity.
The approximation is specified
by an error bound, using the [$L_2$ norm](https://en.wikipedia.org/wiki/Lp_space).
The higher the specified error tolerance, the smaller the output
quantum program.
For exact state preparation, specify an error bound of $0$.
The state preparation algorithm can be tuned depending on whether the
probability distribution is sparse or dense.
The synthesis engine will
automatically select the parameterization based on the given constraints and
optimization level.
Function: `prepare_state`
Parameters:
* `probabilities: CArray[CReal]`
* Probabilities to load.
Should be non-negative and sum to
1.
* `bound: CReal`
* Approximation Error Bound, in the $L_2$ metric (with respect to the given probabilies vector).
* `out: Output[QArray[QBit]]`
Function: `inplace_prepare_state`
Parameters:
* `probabilities: CArray[CReal]`
* `bound: CReal`
* `out: QArray[QBit]`
* Should of size exactly $\log_2$(\`\`probabilities.len\`)
The `inplace_prepare_state` works the same, but for a given allocated `QArray`.
Function: `prepare_amplitudes`
Parameters:
* `amplitudes: CArray[CReal]`
* Amplitudes of the loaded state.
Each should be real and the vector norm should be equal to
1.
* `bound: CReal`
* Approximation Error Bound, in the $L_2$ metric (with respect to the given amplitudes vector).
* `out: Output[QArray[QBit]]`
Function: `inplace_prepare_amplitudes`
Parameters:
* `amplitudes: CArray[CReal]`
* Amplitudes of the loaded state.
Each should be real and the vector norm should be equal to
1.
* `bound: CReal`
* Approximation Error Bound, in the $L_2$ metric (with respect to the given amplitudes vector).
* `out: QArray[QBit]`
* Should of size exactly $\log_2$(`amplitudes.len`)
The `inplace_prepare_amplitudes` works the same, but for a given allocated `QArray`.
## Example 1: Loading Point Mass (PMF) Function
This example generates a quantum program whose output state probabilities are an approximation to the PMF given.
That is, the probability of measuring the state $|000\rangle$ is $0.05$, $|001\rangle$ is $0.11$,...
, and the probability to measure $|111\rangle$ is $0.06$.
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QNum]):
probabilities = [0.05, 0.11, 0.13, 0.23, 0.27, 0.12, 0.03, 0.06]
prepare_state(probabilities=probabilities, bound=0.01, out=x)
qmod = create_model(main)
```
```python theme={null}
qprog = synthesize(qmod)
```
Print the resulting probabilities:
```python theme={null}
import numpy as np
result = execute(qprog).result_value()
probs = np.zeros(8)
for sample in result.parsed_counts:
probs[int(sample.state["x"])] = sample.shots / result.num_shots
print("Resulting probabilities:", probs)
```
**Output:**
```
Resulting probabilities: [0.032 0.118 0.141 0.217 0.282 0.107 0.031 0.072]
```
## Example 2
* Preparating Amplitudes
This example loads a normalized linear space between -1 to
1. The load
state has an accuracy of 99 present under the L2 norm.
```python theme={null}
from classiq.execution import ClassiqBackendPreferences, ExecutionPreferences
@qfunc
def main(x: Output[QNum]):
amps = np.linspace(-1, 1, 8)
amps = amps / np.linalg.norm(amps)
prepare_amplitudes(amplitudes=amps.tolist(), bound=0, out=x)
qmod = create_model(main)
qmod = set_execution_preferences(
qmod,
num_shots=1,
backend_preferences=ClassiqBackendPreferences(backend_name="simulator_statevector"),
)
```
```python theme={null}
qprog = synthesize(qmod)
```
Print the resulting amplitudes:
```python theme={null}
import numpy as np
result = execute(qprog).result_value()
amps = np.zeros(8, dtype=complex)
for sample in result.parsed_state_vector:
amps[int(sample.state["x"])] = sample.amplitude
# remove global phase
global_phase = np.angle(amps[0])
amps = np.real(amps / np.exp(1j * global_phase))
print("Resulting amplitudes:", amps)
```
**Output:**
```
Resulting amplitudes: [ 0.54006172 0.38575837 0.23145502 0.07715167 -0.07715167 -0.23145502
-0.38575837 -0.54006172]
```
# Standard Gates
Source: https://docs.classiq.io/qmod-reference/library-reference/core-library-functions/standard_gates/standard_gates
Open this notebook in GitHub to run it yourself
The Classiq platform provides many standard gates.
Some key standard gates are shown here in detail.
All gates are covered in the [reference manual](https://docs.classiq.io/latest/sdk-reference/#classiq.interface.generator.standard_gates).
```python theme={null}
from classiq import *
```
## Single Qubit Gates
An example is given for $X$ gate.
The gates $I$, $X$, $Y$, $Z$, $H$, $T$ are used in the same way.
#
## For Example: X
Function: `X`
Arguments:
* `target`: `QBit`
```python theme={null}
@qfunc
def main(q: Output[QBit]):
allocate(q)
X(q)
qmod = create_model(main)
qprog = synthesize(qmod)
```
## Single Qubit Rotation Gates
An example is given for $RZ$ gate.
The gates $RX$, $RY$, $RZ$ are used in the same way except for parameter name.
#
### Parameter Names for Different Rotation Gates
* `RX`: `theta`
* `RY`: `theta`
* `RZ`: `phi`
#
## For Example: RZ
$$
\begin{split}RZ(\theta) = \begin{pmatrix}
{e^{-i\frac{\theta}{2}}} & 0 \\
0 & {e^{i\frac{\theta}{2}}} \\
\end{pmatrix}\end{split}
$$
Function: `RZ`
Arguments:
* `theta`: `CReal`
* `target`: `QBit`
```python theme={null}
@qfunc
def main(q: Output[QBit]):
allocate(q)
theta = 1.9
RZ(theta, q)
qmod = create_model(main)
qprog = synthesize(qmod)
```
#
## R Gate
Rotation by $\theta$ around the $cos(\phi)X + sin(\phi)Y$ axis.
$$
\begin{split}R(\theta, \phi) = \begin{pmatrix}
cos(\frac{\theta}{2}) & -ie^{-i\phi}sin(\frac{\theta}{2}) \\
-ie^{i\phi}sin(\frac{\theta}{2}) & cos(\frac{\theta}{2}) \\
\end{pmatrix}\end{split}
$$
Parameters:
* `theta`: `CReal`
* `phi`: `CReal`
* `target`: `QBit`
```python theme={null}
@qfunc
def main(q: Output[QBit]):
allocate(q)
theta = 1
phi = 2
R(theta, phi, q)
qmod = create_model(main)
qprog = synthesize(qmod)
```
#
## Phase Gate
Rotation about the Z axis by $\lambda$ with global phase of $\frac{\lambda}{2}$.
$$
\begin{split}PHASE(\lambda) = \begin{pmatrix} 1 & 0 \\ 0 & e^{i\lambda} \end{pmatrix}\end{split}
$$
Parameters:
* `theta`: `CReal`
* `target`: `QBit`
```python theme={null}
@qfunc
def main(q: Output[QBit]):
allocate(q)
theta = 1
PHASE(theta, q)
qmod = create_model(main)
qprog = synthesize(qmod)
```
## Double Qubits Rotation Gates
An example is given for $RZZ$ gate.
The gates $RXX$, $RYY$, $RZZ$ are used in the same way.
#
## RZZ Gate
Rotation about ZZ.
$$
\begin{split}RZZ(\theta) = \begin{pmatrix}
{e^{-i\frac{\theta}{2}}} & 0 & 0 & 0 \\
0 & {e^{i\frac{\theta}{2}}} & 0 & 0 \\
0 & 0 & {e^{i\frac{\theta}{2}}} & 0 \\
0 & 0 & 0 & {e^{-i\frac{\theta}{2}}} \\
\end{pmatrix}\end{split}
$$
Parameters:
* `theta`: `CReal`
* `target`: `QArray[QBit]`
```python theme={null}
@qfunc
def main(q: Output[QArray]):
allocate(2, q)
theta = 1
RZZ(theta, q)
qmod = create_model(main)
qprog = synthesize(qmod)
```
## Controlled Gates
An example is given for $CX$ gate.
The gates $CX$, $CY$, $CZ$, $CH$, $CSX$, $CCX$ are used in a similar way.
In $CCX$ Gate the `ctrl_state` parameter receives a value suitable for 2 control qubits. for example: `"01"`.
#
## CX Gate
The Controlled $X$ gate.
Applies $X$ Gate on the target qubit, based on the state of the control qubit
(by default if the controlled state is $|1\rangle$).
$$
\begin{split}CX = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1 \\
0 & 0 & 1 & 0 \\
\end{pmatrix}\end{split}
$$
Parameters:
* `control`: `QBit`
* `target`: `QBit`
```python theme={null}
@qfunc
def main(q_target: Output[QBit], q_control: Output[QBit]):
allocate(q_target)
allocate(q_control)
CX(q_control, q_target)
qmod = create_model(main)
qprog = synthesize(qmod)
```
## Controlled Rotations
An example is given for $CRX$ gate.
The gates $CRX$, $CRY$, $CRZ$, CPhase are used in the same way.
#
## CRX Gate
Controlled rotation around the X axis.
$$
\begin{split}CRX(\theta) = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & \cos(\frac{\theta}{2}) & -i\sin(\frac{\theta}{2}) \\
0 & 0 & -i\sin(\frac{\theta}{2}) & \cos(\frac{\theta}{2}) \\
\end{pmatrix}\end{split}
$$
Parameters:
* `theta`: `CReal`
* `control`: `QBit`
* `target`: `QBit`
```python theme={null}
@qfunc
def main(q_target: Output[QBit], q_control: Output[QBit]):
allocate(q_target)
allocate(q_control)
theta = 1
CRX(theta, q_control, q_target)
qmod = create_model(main)
qprog = synthesize(qmod)
```
## Swap Gate
Swaps between two qubit states.
$$
\begin{split}SWAP = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1 \\
\end{pmatrix}\end{split}
$$
Parameters:
* `qbit0`: `QBit`
* `qbit1`: `QBit`
```python theme={null}
@qfunc
def main(q1: Output[QBit], q2: Output[QBit]):
allocate(q1)
allocate(q2)
SWAP(q1, q2)
qmod = create_model(main)
qprog = synthesize(qmod)
```
## U Gate
The single-qubit gate applies phase and rotation with three Euler angles.
Matrix representation:
$$
U(\gamma,\phi,\theta,\lambda) = e^{i\gamma}\begin{pmatrix}
\cos(\frac{\theta}{2}) & -e^{i\lambda}\sin(\frac{\theta}{2}) \\
e^{i\phi}\sin(\frac{\theta}{2}) & e^{i(\phi+\lambda)}\cos(\frac{\theta}{2}) \\
\end{pmatrix}
$$
Parameters:
* `theta`: `CReal`
* `phi`: `CReal`
* `lam`: `CReal`
* `gam`: `CReal`
* `target`: `QBit`
```python theme={null}
@qfunc
def main(q: Output[QBit]):
allocate(q)
theta = 1
phi = 2
lam = 1.5
gam = 1.1
U(theta, phi, lam, gam, q)
qmod = create_model(main)
qprog = synthesize(qmod)
```
# Unitary Function
Source: https://docs.classiq.io/qmod-reference/library-reference/core-library-functions/unitary/unitary
Open this notebook in GitHub to run it yourself
Given a $2^{n}\times2^{n}$ unitary matrix, the unitary-gate function constructs an
equivalent unitary function that acts on $n$ qubits accordingly.
For $n>2$, the
synthesis process implementation is based on [\[1\]](#1).
Function: `unitary`
Arguments:
* `elements: CArray[CArray[CReal]]`
* A 2d array of complex numbers representing the unitary matrix.
* `target: QArray[QBit]`
* The quantum state to apply the unitary on.
Should be of corresponding size.
## Example
This example shows a $2$-qubit unitary function application in the formed $4$-dimensional space.
```python theme={null}
from classiq import *
UNITARY = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1j, 0], [0, 0, 0, 1j]]
@qfunc
def main(x: Output[QArray[QBit]]):
allocate(2, x)
unitary(UNITARY, x)
```
```python theme={null}
qprog = synthesize(main)
```
## References
\[1] R. Iten et al, Quantum Circuits for Isometries, Phys. Rev. A 93 (2016). [https://link.aps.org/doi/10.1103/PhysRevA.93.032318](https://link.aps.org/doi/10.1103/PhysRevA.93.032318)
# Exact Amplitude Amplification
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/amplitude_amplification/exact_amplitude_amplification
Open this notebook in GitHub to run it yourself
The following is a usage example for the `exact_amplitude_amplification` function.
We will amplify the state $|1\rangle$ out of the state $\sqrt{0.07}|0\rangle + \sqrt{0.93}|1\rangle$.
We provide the function with the following parameters:
* `amplitude`: $\sqrt{0.07}$, the original amplitude of the wanted state.
* `oracle`: $Z$, that will apply a $(-1)$ phase on the $|1\rangle$ state.
* `space_transform`: the state preparation function of the original state.
* `packed_vars`: `x`, the quantum variable to apply on.
Notice that knowledge of the amplitude of the "good" state is need.
```python theme={null}
import numpy as np
from classiq import *
GOOD_STATE_PROB = 0.07
@qfunc
def prepare_initial_state(x: QBit):
inplace_prepare_state([1
- GOOD_STATE_PROB, GOOD_STATE_PROB], 0, x)
@qfunc
def main(x: Output[QBit]):
allocate(x)
exact_amplitude_amplification(
np.sqrt(GOOD_STATE_PROB), Z, prepare_initial_state, x # amplify the |1> state
)
qprog = synthesize(main)
show(qprog)
res = execute(qprog).get_sample_result()
res.dataframe
```
**Output:**
```
Quantum program link: https://platform.classiq.io/circuit/31bCC7kOsCvsDd0UpFNHlHQnXXb
```
| | x | count | probability | bitstring |
| - | - | ----- | ----------- | --------- |
| 0 | 1 | 2048 | 1.0 | 1 |
```python theme={null}
assert sum(res.dataframe[res.dataframe.x == 1]["counts"]) == res.num_shots
```
The concept in the implementation is to reduce the initial angle between the `good` and `bad` states to be an exact division of 1 by a integer:
```python theme={null}
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.lines import Line2D
# angles
theta = np.arcsin(np.sqrt(GOOD_STATE_PROB))
k = int(np.ceil((np.pi / (4 * theta)) - 0.5))
theta_prime = np.pi / (4 * k + 2)
# basis axes (Good on +x, Bad on +y)
GOOD = np.array([1.0, 0.0])
BAD = np.array([0.0, 1.0])
# initial states measured from the +x (GOOD) axis
psi = np.array([np.sin(theta), np.cos(theta)]) # standard
psi_prime = np.array([np.sin(theta_prime), np.cos(theta_prime)]) # ancilla-tuned
def R(a):
return np.array([[np.cos(a), np.sin(a)], [-np.sin(a), np.cos(a)]])
# each Grover iterate rotates by +2*theta in the GOOD/BAD plane
steps = range(k + 1)
states = [R(2 * k * theta) @ psi for k in steps]
states_prime = [R(2 * k * theta_prime) @ psi_prime for k in steps]
# ---- plot ----
plt.figure(figsize=(10, 10))
ax = plt.gca()
ax.set_aspect("equal")
# axes
plt.axhline(0, color="gray", lw=1)
plt.axvline(0, color="gray", lw=1)
plt.text(1.25, 0, "|Good>", ha="left", va="center", fontsize=12)
plt.text(0, 1.25, "|Bad>", ha="center", va="bottom", fontsize=12)
# standard Grover trajectory (blue)
for k, v in enumerate(states):
plt.arrow(
0,
0,
v[0],
v[1],
head_width=0.05,
length_includes_head=True,
color="blue",
alpha=0.7,
)
plt.text(v[0] * 1.08, v[1] * 1.08, f"{k}", color="blue")
# exact (ancilla-tuned) trajectory (red)
for k, v in enumerate(states_prime):
plt.arrow(
0,
0,
v[0],
v[1],
head_width=0.05,
length_includes_head=True,
color="red",
alpha=0.7,
)
plt.text(v[0] * 1.08, v[1] * 1.08, f"{k}'", color="red")
# legend handles
legend_elements = [
Line2D([0], [0], color="blue", lw=2, label="amplitude amplification"),
Line2D([0], [0], color="red", lw=2, label="exact amplitude amplification"),
]
plt.legend(handles=legend_elements, loc="upper right")
plt.xlim(-1, 1.6)
plt.ylim(-1, 1.4)
plt.show()
```
# Grover Operator
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/grover_operator/grover_operator
Open this notebook in GitHub to run it yourself
The Grover operator is a unitary used in amplitude estimation and amplitude
amplification algorithms [\[1\]](#1).
The Grover operator is given by
$$
Q = Q(A,\chi) = -AS_0A^{-1}S_\chi
$$
where $A$ is a state preparation operator,
$$
A|0 \rangle= |\psi \rangle
$$
$S_\chi$ marks good states and is called an oracle,
$$
S_\chi\lvert x \rangle =
\begin{cases}
-\lvert x \rangle & \text{if } \chi(x) = 1 \\
\phantom{-} \lvert x \rangle & \text{if } \chi(x) = 0
\end{cases}
$$
and $S_0$ is a reflection about the zero state.
$$
S_0 = I - 2|0\rangle\langle0|
$$
Function: `grover_operator`
Arguments:
* `oracle: QCallable[QArray[QBit]]`
* Oracle representing $S_{\chi}$, accepting quantum state to apply on.
* `space_transform: QCallable[QArray[QBit]]`
* State preparation operator $A$, accepting quantum state to apply on.
* `packed_vars: QArray[QBit]`
* Packed form of the variable to apply the grover operator on.
#
## Example
The following example implements a grover search algorithm using the grover operator for a specific oracle, with a uniform superposition over the search space.
The circuit starts with a uniform superposition on the search space, followed by 2 applications of the grover operator.
```python theme={null}
from classiq import *
VAR_SIZE = 2
class GroverVars(QStruct):
x: QNum[VAR_SIZE]
y: QNum[VAR_SIZE]
@qperm
def my_predicate(vars: Const[GroverVars], res: QBit) -> None:
res ^= (vars.x + vars.y < 4) & ((vars.x * vars.y) % 4 == 2)
@qfunc
def main(vars: Output[GroverVars]):
allocate(vars)
hadamard_transform(vars)
power(
2,
lambda: grover_operator(
lambda vars: phase_oracle(
predicate=my_predicate,
target=vars,
),
hadamard_transform,
vars,
),
)
qprog = synthesize(
main, auto_show=True, constraints=Constraints(optimization_parameter="width")
)
```
**Output:**
```
Quantum program link: https://platform.classiq.io/circuit/3FmUIpJrkfaPVo4zCO3c6VT6jUL
```
And the next is a verification of the amplification of the solutions to the oracle:
```python theme={null}
result = execute(qprog).result_value()
df = result.dataframe
df["predicate"] = (df["vars.x"] + df["vars.y"] < 4) & (
(df["vars.x"] * df["vars.y"]) % 4 == 2
)
df
```
| | vars.x | vars.y | counts | probability | bitstring | predicate |
| -- | ------ | ------ | ------ | ----------- | --------- | --------- |
| 0 | 1 | 2 | 985 | 0.480957 | 1001 | True |
| 1 | 2 | 1 | 949 | 0.463379 | 0110 | True |
| 2 | 2 | 2 | 13 | 0.006348 | 1010 | False |
| 3 | 0 | 3 | 13 | 0.006348 | 1100 | False |
| 4 | 3 | 3 | 13 | 0.006348 | 1111 | False |
| 5 | 3 | 0 | 10 | 0.004883 | 0011 | False |
| 6 | 2 | 3 | 9 | 0.004395 | 1110 | False |
| 7 | 1 | 1 | 8 | 0.003906 | 0101 | False |
| 8 | 0 | 2 | 8 | 0.003906 | 1000 | False |
| 9 | 0 | 0 | 7 | 0.003418 | 0000 | False |
| 10 | 1 | 0 | 7 | 0.003418 | 0001 | False |
| 11 | 2 | 0 | 6 | 0.002930 | 0010 | False |
| 12 | 0 | 1 | 6 | 0.002930 | 0100 | False |
| 13 | 3 | 1 | 5 | 0.002441 | 0111 | False |
| 14 | 3 | 2 | 5 | 0.002441 | 1011 | False |
| 15 | 1 | 3 | 4 | 0.001953 | 1101 | False |
## References
\[1] G. Brassard, P. Hoyer, M. Mosca, and A. Tapp, "Quantum
Amplitude Amplification and Estimation," arXiv:quant-ph/0005055, vol. 305, pp.
53-74, 2002, doi: 10.1090/conm/305/05215.
# Hadamard Transform
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/hadamard_transform/hadamard_transform
Open this notebook in GitHub to run it yourself
The Hadamard transform function applies an H gate on each qubit of the register inputted to the function.
Function: `hadamard_transform`
Arguments:
* `target`: `QArray[QBit]`
The `target` quantum argument is the quantum state on which we apply the Hadamard Transform.
## Example
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QArray[QBit]]):
allocate(3, x)
hadamard_transform(x)
```
```python theme={null}
qprog = synthesize(main)
```
# Linear Pauli Rotations
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/linear_pauli_rotations/linear_pauli_rotations
Open this notebook in GitHub to run it yourself
This function performs a rotation on a series of $m$ target qubits,
where the rotation angle is a linear function of an $n$-qubit
control register, as follows:
$$
\left|x\right\rangle _{n}\left|q\right\rangle
_{m}\rightarrow\left|x\right\rangle
_{n}\prod_{k=1}^{m}\left(\cos\left(\frac{a_{k}}{2}x+\frac{b_{k}}{2}\right)-
i\sin\left(\frac{a_{k}}{2}x+\frac{b_{k}}{2}\right)P_{k}\right)\left|q_{k}\right\rangle
$$
where $\left|x\right\rangle$ is the control register,
$\left|q\right\rangle$ is the target register, each $P_{k}$ is one of
the three Pauli matrices $X$, $Y$, or $Z$, and $a_{k}$, $b_{k}$ are
the user given slopes and offsets, respectively.
For example, the operation of a linear $Y$ rotation on a zero-input
qubit is
$$
\left|x\right\rangle _{n}\left|0\right\rangle
\rightarrow\left|x\right\rangle _{n}\left(
\cos\left(\frac{a}{2}x+\frac{b}{2}\right)\left|0\right\rangle
+\sin\left(\frac{a}{2}x+\frac{b}{2}\right)\left|1\right\rangle \right)
$$
Such a rotation can be realized as a series of controlled rotations
as follows:
$$
\left[R_{y}\left(2^{n-1}a\right)\right]^{x_{n-1}}\cdots
\left[R_{y}\left(2^{1}a\right)\right]^{x_{1}}
\left[R_{y}\left(2^{0}a\right)\right]^{x_{0}}R_{y}\left(b\right)
$$
Function: `linear_pauli_rotations`
Arguments:
* `bases: CArray[int]`
* List of Pauli Enums.
* `slopes: CArray[float]`
* Rotation slopes for each of the given Pauli bases.
* `offsets: CArray[float]`
* Rotation offsets for each of the given Pauli bases.
* `x: QArray[QBit]`
* Quantum state to apply the rotation based on its value.
* `q: QArray[QBit]`
* List of indicator qubits for each of the given Pauli bases.
Notice that `bases`, `slopes`, `offset` and `q` should be of the same size.
## Example: Three Y Rotations Controlled by a 6-Qubit State
This example generates a quantum program with a $6$-qubit control
state and $3$ target qubits, acted upon by Y rotations with different slopes and offsets.
```python theme={null}
from classiq import *
NUM_STATE_QUBITS = 6
BASES = [Pauli.Y.value] * 3
OFFSETS = [0.1, 0.3, 0.33]
SLOPES = [2.1, 1, 7.0]
@qfunc
def main(x: Output[QArray[QBit]], ind: Output[QArray[QBit]]):
allocate(NUM_STATE_QUBITS, x)
allocate(len(BASES), ind)
linear_pauli_rotations(BASES, SLOPES, OFFSETS, x, ind)
```
```python theme={null}
qprog = synthesize(main)
```
# Quantum Sine and Cosine Transforms
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/qct_qst/qct_qst
Open this notebook in GitHub to run it yourself
The quantum Sine and Cosine transforms functions are the quantum analog for the discrete Sine and Cosine transforms.
The **unitary** versions of the type I and type II transforms are defined as follows:
$$
{\rm DCT}^{(1)}_{jk}(N) = \alpha_{jk}\sqrt{\frac{2}{N-1}} \cos\left(\frac{\pi j k}{N-1}\right), \qquad
\alpha_{jk} = \left\{ \begin{array}{l l}
\frac{1}{\sqrt{2}} & j = 0,N-1 ,\\
\frac{1}{\sqrt{2}} & k = 0,N-1 ,\\
1 & \text{else}
\end{array}
\right.,
\qquad j,k = 0\dots,N-1
$$
$$
{\rm DST}^{(1)}_{jk}(N) = \sqrt{\frac{2}{N+1}} \sin\left(\frac{\pi j k}{N+1}\right), \qquad j,k = 0\dots,N-1
$$
$$
{\rm DCT}^{(2)}_{jk}(N) = \alpha_{jk}\sqrt{\frac{2}{N}} \cos\left(\frac{\pi (j+1/2) k }{N}\right), \qquad
\alpha_{jk} = \left\{ \begin{array}{l l}
\frac{1}{\sqrt{2}} & k = 0 ,\\
1 & \text{else}
\end{array}
\right.,
\qquad j,k = 0\dots,N-1
$$
$$
{\rm DST}^{(2)}_{jk}(N) = \alpha_{jk} \sqrt{\frac{2}{N}} \sin\left(\frac{\pi (j+1/2) (k+1)}{N}\right), \qquad
\alpha_{jk} = \left\{ \begin{array}{l l}
\frac{1}{\sqrt{2}} & k = N-1 ,\\
1 & \text{else}
\end{array}
\right.,
\qquad j,k = 0\dots,N-1
$$
The open library includes four functions, following the implementation in Ref. \[[1](#qcst)]:
## QCT and QST of Type I
Function: `qct_qst_type1`
Arguments:
* `x`: `QArray[QBit]`
The `x` quantum argument is the quantum state on which we apply the transforms, according to the following unitary on $n\equiv$`x.len` qubits:
$$
\left(
\begin{array}{ccc|c}
{} &{} &{} \\
{}&{\rm DCT}^{(1)}(2^{n-1}+1) & {}& 0\\
{} &{} &{} \\
\hline
{} & 0 & {} & i{\rm DST}^{(1)}(2^{n-1}-1)
\end{array}
\right)
$$
#
## Example
```python theme={null}
import numpy as np
from classiq import *
NUM_QUBITS = 4
execution_preferences = ExecutionPreferences(
num_shots=1,
backend_preferences=ClassiqBackendPreferences(
backend_name=ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR
),
)
np.random.seed(123)
cos_data = np.random.rand(2 ** (NUM_QUBITS - 1) + 1)
cos_data = cos_data / np.linalg.norm(cos_data)
sin_data = np.random.rand(2 ** (NUM_QUBITS - 1) - 1)
sin_data = sin_data / np.linalg.norm(sin_data)
combined_data = np.append(cos_data / np.sqrt(2), sin_data / np.sqrt(2))
```
```python theme={null}
@qfunc
def main(x: Output[QNum]):
prepare_amplitudes(combined_data.tolist(), 0.0, x)
qct_qst_type1(x)
qmod = create_model(main, execution_preferences=execution_preferences)
```
```python theme={null}
qprog = synthesize(qmod)
```
```python theme={null}
result = execute(qprog).result_value()
```
```python theme={null}
qct_data = np.zeros(2 ** (NUM_QUBITS - 1) + 1).astype(complex)
qst_data = np.zeros(2 ** (NUM_QUBITS - 1) - 1).astype(complex)
for sample in result.parsed_state_vector:
value = int(sample.state["x"])
if value < 2 ** (NUM_QUBITS - 1) + 1:
qct_data[value] += sample.amplitude
else:
qst_data[int(value - 2 ** (NUM_QUBITS - 1) - 1)] += sample.amplitude
```
```python theme={null}
def dct1(n):
dct = np.array(
[
[
np.cos(np.pi * j * k / (n - 1))
* (np.sqrt(1 / 2) if j == 0 or j == n - 1 else 1)
* (np.sqrt(1 / 2) if k == 0 or k == n - 1 else 1)
for j in range(n)
]
for k in range(n)
]
) / np.sqrt((n - 1) / 2)
return dct
def dst1(n):
dst = np.array(
[
[np.sin(np.pi * (j + 1) * (k + 1) / (n + 1)) for j in range(n)]
for k in range(n)
]
) / np.sqrt((n + 1) / 2)
return dst
```
```python theme={null}
global_phase = np.exp(1j * np.angle(qct_data[0]))
measured_cos_res = np.real(qct_data / global_phase)
expected_cos_res = (dct1(2 ** (NUM_QUBITS - 1) + 1) @ cos_data) / np.sqrt(2)
print("measured result:", measured_cos_res)
print("expected result:", expected_cos_res)
assert np.allclose(measured_cos_res, expected_cos_res, atol=0.01)
```
**Output:**
```
measured result: [ 0.64936034 -0.13662084 0.02159456 0.08089956 0.06722088 0.18669631
0.02254746 -0.01198615 0.1123771 ]
expected result: [ 0.64936034 -0.13662084 0.02159456 0.08089956 0.06722088 0.18669631
0.02254746 -0.01198615 0.1123771 ]
```
```python theme={null}
global_phase = np.exp(1j * np.angle(qst_data[0]))
measured_sin_res = np.real(qst_data / global_phase)
expected_sin_res = (dst1(2 ** (NUM_QUBITS - 1) - 1) @ sin_data) / np.sqrt(2)
print("measured result:", measured_sin_res)
print("expected result:", expected_sin_res)
assert np.allclose(measured_sin_res, expected_sin_res, atol=0.01)
```
**Output:**
```
measured result: [ 0.57556991 0.04712138 0.22433696 -0.27513447 0.17796799 0.07685908
0.05378552]
expected result: [ 0.57556991 0.04712138 0.22433696 -0.27513447 0.17796799 0.07685908
0.05378552]
```
## QCT and QST of Type II
Function: `qct_qst_type2`
Arguments:
* `x`: `QArray[QBit]`,
* `q`: `QBit`
The `x` quantum argument is the quantum state on which we apply the transforms, whereas the single `q` qubit indicates the block, according to the following unitary on $n+1\equiv$ `x.len` $+1$ qubits:
$$
\left(
\begin{array}{c|c}
{\rm DCT}^{(2)}(2^{n-1}) & 0\\
\hline
0 & -{\rm DST}^{(2)}(2^{n-1})
\end{array}
\right)
$$
Function: `qct_type2`
Arguments:
* `x`: `QArray[QBit]`: the quantum state on which we apply ${\rm DCT}^{(2)}$.
Function: `qst_type2`
Arguments:
* `x`: `QArray[QBit]`: the quantum state on which we apply ${\rm DST}^{(2)}$.
#
## Example
```python theme={null}
NUM_QUBITS = 4
cos_sin_data = np.random.rand(2 ** (NUM_QUBITS - 1))
cos_sin_data = cos_sin_data / np.linalg.norm(cos_sin_data)
```
```python theme={null}
@qfunc
def main(x: Output[QNum], q: Output[QBit]):
prepare_amplitudes(cos_sin_data.tolist(), 0.0, x)
allocate(q)
H(q)
qct_qst_type2(x, q)
qmod = create_model(main, execution_preferences=execution_preferences)
```
```python theme={null}
qprog = synthesize(qmod)
```
```python theme={null}
result = execute(qprog).result_value()
```
```python theme={null}
qct_data = np.zeros(2 ** (NUM_QUBITS - 1)).astype(complex)
qst_data = np.zeros(2 ** (NUM_QUBITS - 1)).astype(complex)
for sample in result.parsed_state_vector:
if sample.state["q"] == 0:
qct_data[int(sample.state["x"])] += sample.amplitude
else:
qst_data[int(sample.state["x"])] += sample.amplitude
```
```python theme={null}
def dct2(n):
dct = np.array(
[
[
np.cos(np.pi * j * (k + 1 / 2) / n) * (np.sqrt(1 / 2) if j == 0 else 1)
for j in range(n)
]
for k in range(n)
]
) / np.sqrt(n / 2)
return dct.T
def dst2(n):
dst = np.array(
[
[
np.sin(np.pi * (j + 1) * (k + 1 / 2) / n)
* (np.sqrt(1 / 2) if j == n - 1 else 1)
for j in range(n)
]
for k in range(n)
]
) / np.sqrt(n / 2)
return dst.T
```
```python theme={null}
global_phase = np.exp(1j * np.angle(qct_data[0]))
measured_cos_res = np.real(qct_data / global_phase)
expected_cos_res = (dct2(2 ** (NUM_QUBITS - 1)) @ cos_sin_data) / np.sqrt(2)
print("measured result:", measured_cos_res)
print("expected result:", expected_cos_res)
assert np.allclose(measured_cos_res, expected_cos_res, atol=0.01)
```
**Output:**
```
measured result: [ 0.65104654 -0.23305325 -0.11473439 0.02595719 -0.04930425 0.03323495
0.06553173 0.01252819]
expected result: [ 0.65104654 -0.23305325 -0.11473439 0.02595719 -0.04930425 0.03323495
0.06553173 0.01252819]
```
```python theme={null}
global_phase = np.exp(1j * np.angle(qst_data[0]))
measured_sin_res = np.real(qst_data / global_phase)
expected_sin_res = (dst2(2 ** (NUM_QUBITS - 1)) @ cos_sin_data) / np.sqrt(2)
print("measured result:", measured_sin_res)
print("expected result:", expected_sin_res)
assert np.allclose(measured_sin_res, expected_sin_res, atol=0.01)
```
**Output:**
```
measured result: [ 0.63981132 -0.2180174 0.13530848 -0.08552637 0.02796936 -0.03450769
0.12370004 -0.01455965]
expected result: [ 0.63981132 -0.2180174 0.13530848 -0.08552637 0.02796936 -0.03450769
0.12370004 -0.01455965]
```
```python theme={null}
@qfunc
def main(x: Output[QNum]):
prepare_amplitudes(cos_sin_data.tolist(), 0.0, x)
qct_type2(x)
qmod = create_model(main, execution_preferences=execution_preferences)
qprog = synthesize(qmod)
result = execute(qprog).result_value()
qct_data = np.zeros(2 ** (NUM_QUBITS - 1)).astype(complex)
for sample in result.parsed_state_vector:
qct_data[int(sample.state["x"])] += sample.amplitude
global_phase = np.exp(1j * np.angle(qct_data[0]))
measured_cos_res = np.real(qct_data / global_phase)
expected_cos_res = dct2(2 ** (NUM_QUBITS - 1)) @ cos_sin_data
print("measured result:", measured_cos_res)
print("expected result:", expected_cos_res)
assert np.allclose(measured_cos_res, expected_cos_res, atol=0.01)
```
**Output:**
```
measured result: [ 0.92071884 -0.32958707 -0.16225893 0.03670901 -0.06972674 0.04700132
0.09267587 0.01771754]
expected result: [ 0.92071884 -0.32958707 -0.16225893 0.03670901 -0.06972674 0.04700132
0.09267587 0.01771754]
```
```python theme={null}
@qfunc
def main(x: Output[QNum]):
prepare_amplitudes(cos_sin_data.tolist(), 0.0, x)
qst_type2(x)
qmod = create_model(main, execution_preferences=execution_preferences)
qprog = synthesize(qmod)
result = execute(qprog).result_value()
qst_data = np.zeros(2 ** (NUM_QUBITS - 1)).astype(complex)
for sample in result.parsed_state_vector:
qst_data[int(sample.state["x"])] += sample.amplitude
global_phase = np.exp(1j * np.angle(qst_data[0]))
measured_sin_res = np.real(qst_data / global_phase)
expected_sin_res = dst2(2 ** (NUM_QUBITS - 1)) @ cos_sin_data
print("measured result:", measured_sin_res)
print("expected result:", expected_sin_res)
assert np.allclose(measured_sin_res, expected_sin_res, atol=0.01)
```
**Output:**
```
measured result: [ 0.90482984 -0.30832317 0.19135509 -0.12095255 0.03955464 -0.04880124
0.17493827 -0.02059046]
expected result: [ 0.90482984 -0.30832317 0.19135509 -0.12095255 0.03955464 -0.04880124
0.17493827 -0.02059046]
```
## References
\[1]: [Klappenecker, A., & Rotteler M., "Discrete Cosine Transforms on Quantum Computers".](https://arxiv.org/abs/quant-ph/0111038)
# Quantum Fourier Transform
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/qft/qft
Open this notebook in GitHub to run it yourself
The quantum Fourier transform (QFT) function is the quantum analog for
discrete Fourier transform. It is applied on the quantum register state vector.
The state vector `x` is transformed to `y` in the following manner:
$$
y_{k} = \frac{1}{\sqrt{N}} \sum_{j=0}^{N-1} x_j e^{2\pi i \frac{jk}{N}}
$$
Function: `qft`
Arguments:
* `target`: `QArray[QBit]`
The `target` quantum argument is the quantum state on which we apply the QFT.
## Example
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QArray[QBit]]):
allocate(4, x)
qft(x)
```
```python theme={null}
qprog = synthesize(main)
```
# Quantum Phase Estimation
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/qpe/qpe
Open this notebook in GitHub to run it yourself
The quantum phase estimation (QPE) function estimates the phase of an eigenvector of a unitary function.
More precisely, given a unitary function $F$ and an input containing a quantum variable with a state $|\psi\rangle$ such that $F(|\psi\rangle)=e^{2\pi i\nu}|\psi\rangle$,
the phase estimation function outputs an estimation of $\nu$ as a fixed-point binary number.
Phase estimation is frequently used as a subroutine in other quantum algorithms such as Shor's algorithm and quantum algorithms for solving linear systems of equations (HHL algorithm).
Theoretical details are in Ref. [\[1\]](#1).
Function: `qpe`
Arguments:
* `unitary: QCallable`
* The unitary operation for which the qpe estimation the eigenvalues
* `phase: QNum`
* The output of the qpe, holding the phase as a number in the range $[0, 1)$
Function: `qpe_flexible`
The function is suitable when one wants to specialize the way the power of a unitary is defined, other than using the naive power.
For example it can be used to obtain the time evolution of hamiltonians or for Shor's algorithm.
Arguments:
* `unitary_with_power: QCallable[CInt]`
* Power of a unitary.
Accepts as argument the power of the unitary to apply.
* `phase: QNum`
## Examples
#
## Example 1: QPE of a Function
This example shows how to perform a simple phase estimation:
1. Initialize the state $|3\rangle$ over two qubits.
2. Apply a phase estimation on the the controlled-RZ gate, represeneted by the unitary matrix:
$$
\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & e^{-i\frac{\lambda}{2}} & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & e^{i\frac{\lambda}{2}}
\end{pmatrix}
$$
The expected phase variable should encode $\frac{\lambda}{4\pi}$, the phase of the eigenvalue of the $|3\rangle$ state.
Choosing $\lambda = \pi$, the expected result is $\frac{1}{4}$, represented in binary by `01`.
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
QPE_RESOLUTION = 2
@qfunc
def main(
state: Output[QArray[QBit]],
phase: Output[QNum[QPE_RESOLUTION, UNSIGNED, QPE_RESOLUTION]],
):
allocate(phase)
allocate(2, state)
X(state[0])
X(state[1])
qpe(unitary=lambda: CRZ(pi, state[0], state[1]), phase=phase)
qmod = create_model(main)
```
```python theme={null}
qprog = synthesize(qmod)
```
Show the actual results:
```python theme={null}
result = execute(qprog).result_value()
print("Results:", result.parsed_counts)
```
**Output:**
```
Results: [{'state': [1, 1], 'phase': 0.25}: 2048]
```
#
## Example 2: Flexible QPE
The following examples will specifiy directly how to take powers in the QPE.
The unitary function is `suzuki_trotter`, where the number of repetitions will be
1. In the case of diagonal hamiltonian it be exact exponentiation of the hamiltoian.
Take the following matrix:
$$
\begin{pmatrix}
0 & 0 & 0 & 0 \\
0 & \tfrac{1}{4} & 0 & 0 \\
0 & 0 & \tfrac{1}{2} & 0 \\
0 & 0 & 0 & \tfrac{3}{4} \\
\end{pmatrix}
$$
Represented by the hamiltonian:
$H = -\frac{1}{8}Z_0I_1 - \frac{1}{4}I_0Z_1 + \frac{3}{8}I_0I_1$
```python theme={null}
QPE_RESOLUTION = 2
HAMILTONIAN = [
PauliTerm(pauli=[Pauli.I, Pauli.Z], coefficient=-0.125),
PauliTerm(pauli=[Pauli.Z, Pauli.I], coefficient=-0.25),
PauliTerm(pauli=[Pauli.I, Pauli.I], coefficient=0.375),
]
@qfunc
def main(
state: Output[QArray[QBit]],
phase: Output[QNum[QPE_RESOLUTION, UNSIGNED, QPE_RESOLUTION]],
):
allocate(2, state)
allocate(phase)
hadamard_transform(state)
qpe_flexible(
lambda power: suzuki_trotter(
HAMILTONIAN,
evolution_coefficient=-2 * pi * (power),
order=1,
repetitions=1,
qbv=state,
),
phase,
)
qmod = create_model(main)
```
```python theme={null}
qprog = synthesize(qmod)
```
Show the actual results:
```python theme={null}
result = execute(qprog).result_value()
print("Results:", result.parsed_counts)
```
**Output:**
```
Results: [{'state': [0, 0], 'phase': 0.0}: 554, {'state': [1, 1], 'phase': 0.75}: 517, {'state': [1, 0], 'phase': 0.25}: 516, {'state': [0, 1], 'phase': 0.5}: 461]
```
## References
\[1] A. Yu.
Kitaev Barenco et al, Quantum Measurements and the Abelian Stabilizer Problem,
(1995). [https://doi.org/10.48550/arXiv.quant-ph/9511026](https://doi.org/10.48550/arXiv.quant-ph/9511026)
# QSVT
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/qsvt/qsvt
Open this notebook in GitHub to run it yourself
The Quantum Singlar Value Transformation (QSVT) [\[1\]](#qsvt) is an algorithmic framework, used to apply polynomial transformation on the singular values of a block encoded matrix. It has wide range of applications such as matrix inversion, amplitude amplification and hamiltonian simulation.
Given a unitary $U$, a list of phase angles $\phi_1, \phi_2, ..., \phi_{d+1}$ and 2 projector-controlled-not operands $C_{\Pi}NOT,C_{\tilde{\Pi}}NOT$ , the QSVT sequence is as follows:
$$
\tilde{\Pi}_{\phi_{d+1}}U \prod_{k=1}^{(d-1)/2} (\Pi_{\phi_{d-2k}} U^{\dagger}\tilde{\Pi}_{\phi_{d - (2k+1)}}U)\Pi_{\phi_{1}}
$$
for odd $d$, and:
$$
\prod_{k=1}^{d/2} (\Pi_{\phi_{d-(2k-1)}} U^{\dagger}\tilde{\Pi}_{\phi_{d-2k}}U)\Pi_{\phi_{1}}
$$
for even $d$.
Each of the projector-controlled-phase unitaries $\Pi$ consists of a $Z$ rotation of an auxilliary qubit wrapped by the $C_{\Pi}NOT$s, NOTing the auxilliary qubit:
$$
\Pi_{\phi} = (C_{\Pi}NOT) e^{-i\frac{\phi}{2}Z}(C_{\Pi}NOT)
$$
The transformation will result with a polynomial of order $d$.
Function: `qsvt`
Arguments:
* `phase_seq: CArray[CReal]` - a $d+1$ sized sequence of phase angles.
* `proj_cnot_1: QCallable[QArray[QBit], QBit]` - projector-controlled-not unitary that locates the encoded matrix columns within $U$.
Accepts quantum variable of the size of `qvar`, and a qubit that is set to $|1\rangle$ when the state is in the block.
* `proj_cnot_2: QCallable[QArray[QBit], QBit]` - projector-controlled-not unitary that locates the encoded matrix rows within $U$.
Accepts quantum variable of the size of `qvar`, and a qubit that is set to $|1\rangle$ when the state is in the block.
* `u: QCallable[QArray[QBit]]` - $U$ a block encoding unitary of a matrix $A$, such that $A = \tilde{\Pi}U\Pi$.
* `qvar: QArray[QBit]` - the quantum variable on which $U$ applies, which resides in the entire block encoding space.
* `aux: QBit` - a zero auxilliary qubit, used for the projector-controlled-phase rotations.
Given as an input so that qsvt can be used as a building-block in a larger algorithm.
```python theme={null}
!pip install -qq "classiq[qsp]"
```
#
## Example: Polynomial Transformation on a $\sqrt(x)$ Block Encoding
The following example implements a random polynomial transformation on a given block, based on [\[2\]](#qsvt-derivative).
The unitary $U$ here is a square-root transformation: $U|x\rangle_n|0\rangle_{n+1} = |x\rangle_n(\sqrt{x}|\psi_0\rangle_{n}|0\rangle + \sqrt{1-x}|\psi_1\rangle_{n}|1\rangle)$ where $x$ is a fixed-point variable in the range $[0, 1)$.
The example samples a random odd-polynomial, calculates the necessary phase sequence, then applies the qsvt and verifies the results.
There are 2 distinct projector-controlled-not unitaries - one is applying on the entire $(n+1)$ variable, and the second is on the 1-qubits auxilliary in the image.
```python theme={null}
from typing import Dict, Tuple
import numpy as np
from numpy.polynomial import Polynomial
from classiq import *
from classiq.qmod.symbolic import logical_and
NUM_QUBITS = 4
@qfunc
def u_sqrt(state: QNum, ref: QNum, ind: QBit) -> None:
hadamard_transform(ref)
ind ^= state <= ref
@qfunc
def qsvt_sqrt_polynomial(
qsvt_phases: list[float], state: QNum, ref: QNum, ind: QBit, qsvt_aux: QBit
) -> None:
qsvt(
qsvt_phases,
lambda _aux: inplace_xor(ref == 0, _aux),
lambda _aux: inplace_xor(ind == 0, _aux),
lambda: u_sqrt(state, ref, ind),
qsvt_aux,
)
```
```python theme={null}
import matplotlib.pyplot as plt
from classiq.applications.qsp import qsvt_phases
def sample_random_chebyshev_polynomial(degree):
# Generate random coefficients
coefficients = np.random.uniform(-1, 1, degree + 1)
# take care for parity
coefficients[int(degree + 1) % 2 :: 2] = 0
# Create the polynomial
p = np.polynomial.Chebyshev(coefficients)
# Evaluate the polynomial over the interval [-1, 1]
x = np.linspace(-1, 1, 500)
y = p(x)
# Normalize the polynomial
poly = p / (np.max(np.abs(y)) + 0.001)
print(poly)
return poly
def parse_qsvt_results(result) -> Tuple[np.ndarray, np.ndarray]:
parsed_state_vector = result.parsed_state_vector
d: Dict = {x: [] for x in range(2**NUM_QUBITS)}
for parsed_state in parsed_state_vector:
if (
parsed_state["qsvt_aux"] == 0
and parsed_state["ind"] == 0
and np.linalg.norm(parsed_state.amplitude) > 1e-15
and (DEGREE % 2 == 1 or parsed_state["ref"] == 0)
):
d[parsed_state["state"]].append(parsed_state.amplitude)
d = {k: np.linalg.norm(v) for k, v in d.items()}
values = [d[i] for i in range(len(d))]
x = np.sqrt(np.linspace(0, 1 - 1 / (2**NUM_QUBITS), 2**NUM_QUBITS))
measured_poly_values = np.sqrt(2**NUM_QUBITS) * np.array(values)
target_poly_values = np.abs(POLY(x))
plt.scatter(x, measured_poly_values, label="measured", c="g")
plt.plot(x, target_poly_values, label="target")
plt.xlabel(r"$\sqrt{x}$")
plt.ylabel(r"$P(\sqrt{x})$")
plt.legend()
return measured_poly_values, target_poly_values
```
```python theme={null}
DEGREE = 5
np.random.seed(1)
# choosing in purpose odd polynomial
POLY = sample_random_chebyshev_polynomial(DEGREE)
QSVT_PHASES = qsvt_phases(POLY.coef)
```
**Output:**
```
0.0 + 0.33582085·T₁(x) + 0.0·T₂(x) - 0.30128672·T₃(x) + 0.0·T₄(x) -
0.62136169·T₅(x)
```
```python theme={null}
@qfunc
def main(
state: Output[QNum[NUM_QUBITS]],
ref: Output[QNum[NUM_QUBITS]],
ind: Output[QBit],
qsvt_aux: Output[QBit],
) -> None:
allocate(state)
allocate(ref)
allocate(ind)
allocate(qsvt_aux)
hadamard_transform(state)
qsvt_sqrt_polynomial(QSVT_PHASES, state, ref, ind, qsvt_aux)
qmod = create_model(
main,
constraints=Constraints(optimization_parameter="width"),
execution_preferences=ExecutionPreferences(
num_shots=1,
backend_preferences=ClassiqBackendPreferences(
backend_name="simulator_statevector"
),
),
)
qprog = synthesize(qmod)
```
```python theme={null}
show(qprog)
```
**Output:**
```
Quantum program link: https://platform.classiq.io/circuit/3FmW1eMFbXPFRVnq1mtPbK1wBSc
```
```python theme={null}
result = execute(qprog).result_value()
measured, target = parse_qsvt_results(result)
assert np.allclose(measured, target, atol=0.02)
```
## References
\[1]: András Gilyén, Yuan Su, Guang Hao Low, and Nathan Wiebe. 2019. Quantum singular value transformation and beyond: exponential improvements for quantum matrix arithmetics. In Proceedings of the 51st Annual ACM SIGACT Symposium on Theory of Computing (STOC 2019). Association for Computing Machinery, New York, NY, USA, 193-204 [https://doi.org/10.1145/3313276.3316366](https://doi.org/10.1145/3313276.3316366).
\[2]: Stamatopoulos, Nikitas, and William J. Zeng. "Derivative pricing using quantum signal processing." arXiv preprint arXiv:2307.14310 (2023).
# Bell State Preparation
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/special_state_preparations/prepare_bell_state
Open this notebook in GitHub to run it yourself
The `prepare_bell_state` function creates one of the four Bell states
$$
\phi_{+} = \frac{1}{2} \left(|00\rangle + |11\rangle \right)
$$
$$
\phi_{-} = \frac{1}{2} \left(|00\rangle - |11\rangle \right)
$$
$$
\psi_{+} = \frac{1}{2} \left(|01\rangle + |10\rangle \right)
$$
$$
\psi_{-} = \frac{1}{2} \left(|01\rangle - |10\rangle \right)
$$
Function: `prepare_bell_state`
Arguments:
* `state_num: CInt`
* `q: Output[QArray[QBit]]`
## Example
The `prepare_bell_state` function creates
$$
\psi_{+} = \frac{1}{2} \left(|01\rangle + |10\rangle \right)
$$
`state_num` is set to 2
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QArray[QBit]]):
prepare_bell_state(2, x)
```
```python theme={null}
qprog = synthesize(main)
```
# Exponential State Preparation
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/special_state_preparations/prepare_exponential_state
Open this notebook in GitHub to run it yourself
The `prepare_exponential_state` function
creates a state with exponentially decreasing amplitudes. Namely,
the probability for a state representing an integer $n$ is
$$
P\left(n\right) = \frac{1}{Z} e^{-\lambda n}
$$
where $\lambda$ is the rate, and $Z$ is a normalization factor.
If $q$ in the number of qubits, then
$$
Z = \sum_{n=0} ^{n = 2^q - 1} e^{-\lambda n} = \frac{1 - e^{-\lambda 2^q}}{1 - e^{-\lambda}}
$$
Function: `prepare_exponential_state`
Arguments:
* `rate: CReal`
* `q: QArray[QBit]`
Notice that the function acts inplace on the qubits.
## Example
Prepare a state with probabilities:
$$
P\left(n\right) = \frac{1}{Z} e^{-0.1 n}
$$
where $n$ is in the range $[0, 31]$.
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QArray[QBit]]):
allocate(5, x)
prepare_exponential_state(0.1, x)
```
```python theme={null}
qprog = synthesize(main)
```
# GHZ State Preparation
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/special_state_preparations/prepare_ghz_state
Open this notebook in GitHub to run it yourself
Use the `prepare_ghz_state` function to create a Greenberger-Horne-Zeilinger (GHZ) state.
i.e., a balanced superposition of all ones and all zeros, on an arbitrary number of qubits.
## Syntax
Function: `prepare_ghz_state`
Arguments:
* `size: CInt`
* `q: Output[QArray[QBit]]`
## Example
`prepare_ghz_state` on 5 qubits
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QArray[QBit]]):
prepare_ghz_state(5, x)
```
```python theme={null}
qprog = synthesize(main)
```
# Partial Uniform State Preparations
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/special_state_preparations/prepare_partial_uniform_state
Open this notebook in GitHub to run it yourself
The functions `prepare_uniform_trimmed_state` and `prepare_uniform_interval_state` create states with uniform superposition over a discrete interval of the possible states.
Both scale polynomially with the number of qubits.
## Uniform Trimmed State
Function: `prepare_uniform_trimmed_state`
Arguments:
* `m: CInt` - number of states to load.
* `q: QArray[QBit]` - quantum variable to load the state into.
The function loads the following superposition:
$$
|\psi\rangle = \frac{1}{\sqrt{m}}\sum_{i=0}^{m-1}{|i\rangle}
$$
#
## Example
Prepare the following state on a variable of size 4 qubits.:
$$
|\psi\rangle = \frac{1}{\sqrt{3}}\sum_{i=0}^{2}{|i\rangle}
$$
```python theme={null}
import matplotlib.pyplot as plt
from classiq import *
@qfunc
def main(x: Output[QNum]):
allocate(4, x)
prepare_uniform_trimmed_state(3, x)
qmod = create_model(main)
qprog = synthesize(qmod)
```
```python theme={null}
result = execute(qprog).result_value()
counts = result.parsed_counts
```
```python theme={null}
plt.figure(figsize=(4, 3))
plt.bar(
[c.state["x"] for c in counts],
[c.shots for c in counts],
color="skyblue",
edgecolor="black",
)
plt.xlabel("state")
plt.ylabel("shots")
```
**Output:**
```
Text(0, 0.5, 'shots')
```
## Uniform Interval State
Function: `prepare_uniform_interval_state`
Arguments:
* `start: CInt` - first state to be loaded.
* `end: CInt` - boundary of the loaded states (not including).
* `q: QArray[QBit]` - quantum variable to load the state into.
The function loads the following superposition:
$$
|\psi\rangle = \frac{1}{\sqrt{end-start}}\sum_{i=start}^{end-1}{|i\rangle}
$$
#
## Example
Prepare the following state on a variable of size 5 qubits.:
$$
|\psi\rangle = \frac{1}{\sqrt{6}}\sum_{i=2}^{7}{|i\rangle}
$$
```python theme={null}
@qfunc
def main(x: Output[QNum]):
allocate(5, x)
prepare_uniform_interval_state(2, 8, x)
qmod = create_model(main)
qprog = synthesize(qmod)
```
```python theme={null}
result = execute(qprog).result_value()
counts = result.parsed_counts
```
```python theme={null}
plt.figure(figsize=(5, 3))
plt.bar(
[c.state["x"] for c in counts],
[c.shots for c in counts],
color="skyblue",
edgecolor="black",
)
plt.xlabel("state")
plt.ylabel("shots")
```
**Output:**
```
Text(0, 0.5, 'shots')
```
# Variational Data Encoding
Source: https://docs.classiq.io/qmod-reference/library-reference/open-library-functions/variational_data_encoding/variational_data_encoding
Open this notebook in GitHub to run it yourself
Encoding classical data on quantum states is an important subroutine in variational quantum circuits, such as Quantum Singular Vector Machine (QSVM) and Quantum Neural Networks (QNN).
## Encode in Angle
This function encodes $n$ data points on $n$ qubits, mapping the data point $x_i$ to a RY rotation on the $i$-th qubit with a $\pi x_i$ angle.
Function: `encode_in_angle`
Arguments:
* `data`: `CArray[Creal]`
* `qba`: `Output[QArray[QBit]]`
The `qba` quantum argument is the quantum state on which we encode the classical array `data`.
## Example
```python theme={null}
from classiq import *
@qfunc
def main(data: CArray[CReal, 4], x: Output[QArray[QBit]]):
encode_in_angle(data, x)
qmod = create_model(main)
```
```python theme={null}
from classiq import synthesize
qprog = synthesize(qmod)
```
## Encode on Bloch
This function encodes $n$ data points on $\lceil n/2 \rceil$, mapping pairs of data points $(x_{2i}, x_{2i+1})$ to the bloch sphere via RX rotation with an angle $\pi x_{2i}$ followed by a RZ rotation with an angle $\pi x_{2i+1}$. If the number of data points is odd then a single RX rotation is applied to the last qubit, with an angle of $2\pi x_n$.
Function: `encode_on_bloch`
Arguments:
* `data`: `CArray[Creal]`
* `qba`: `Output[QArray[QBit]]`
The `qba` quantum argument is the quantum state on which we encode the classical array `data`.
## Example
```python theme={null}
from classiq import *
@qfunc
def main(data: CArray[CReal, 7], x: Output[QArray[QBit]]):
encode_on_bloch(data, x)
qmod = create_model(main)
```
```python theme={null}
from classiq import synthesize
qprog = synthesize(qmod)
```
# Release News: July 2026
Source: https://docs.classiq.io/release-news/recap-july-2026
Five versions released in July, led by two headline features: a new architecture that makes synthesis significantly faster, and predefined hardware benchmarking across the IDE and SDK.
A faster synthesis architecture, and predefined quantum hardware benchmarks
A new QNN layer, language ergonomics, and direct session configuration
Benchmarking and QNN guides, plus three library notebooks
Correctness fixes and API deprecations
## A Faster, Scalable Synthesis Architecture
Synthesizing Qmod code (in the IDE or via the SDK's [`synthesize`](/sdk-reference/synthesis#synthesize)) now returns a **Qmod-based executable** representation rather than a QASM circuit. This representation is a subset of Qmod: it captures the concrete implementations and resource allocations chosen for the high-level constructs in the source, while preserving the function hierarchy and symbolic control flow. Compilation is therefore **significantly faster**, cutting synthesis runtime by up to 10x, and scales better to larger problems and algorithms. The quantum program visualization is generated directly from this representation.
Transpilation no longer occurs at synthesis. To restore the old flow, in which transpilation occurs during synthesis, set `compatibility_mode=True` in the [synthesis preferences](/sdk-reference/synthesis#preferences).
### Exporting to Target Languages
After synthesizing high-level Qmod code into a concrete gate-level quantum program, the [**`export`**](/sdk-reference/synthesis#export) function, or the export menu in the Classiq IDE, transpiles it into a circuit in a target language of your choice: OpenQASM 2.0, OpenQASM 3.0, QIR, Cirq JSON, or Q#.
By default no further transpilation is applied; pass `transpilation_config=True` in the SDK (see example below) to reuse the transpilation level, backend, gate set, and connectivity map defined in the [synthesis preferences](/sdk-reference/synthesis#preferences), or an explicit [`TranspilationConfig`](/sdk-reference/synthesis#transpilationconfig) object to override them.
For a full explanation of transpilation and the available levels, see the [Quantum Program Transpilation](/user-guide/synthesis/quantum-program-transpilation) guide.
**Exporting a synthesized program to OpenQASM 3 with a specific gate set and connectivity:**
[comment]: DO_NOT_TEST
```python theme={null}
# synthesis preferences: a target gate set and qubit connectivity
synthesis_preferences = Preferences(
custom_hardware_settings=CustomHardwareSettings(
basis_gates=["cx", "rz", "sx", "x"],
connectivity_map=[(0, 1), (1, 2), (2, 3)],
)
)
qprog = synthesize(main, preferences=synthesis_preferences)
# transpilation_config=True reuses the gate set and connectivity from the synthesis preferences
qasm = export(qprog, target_language=TargetLanguage.QASM3, transpilation_config=True)
```
[**Execution**](/user-guide/execution/index), by contrast, transpiles the program for the backend you run on; the backend and transpilation level you set for that execution override the synthesis preferences, if there is a conflict.
### Fault-Tolerant Export
Exporting a program to a fault-tolerant circuit with a Clifford+T gate set is now **faster and more accurate**, driven by the [gridsynth](https://github.com/quantum-programming/pygridsynth) algorithm rather than the Solovay-Kitaev method used previously. Passing a [`FaultTolerantTranspilationConfig`](/sdk-reference/synthesis#faulttoleranttranspilationconfig) object to [`export`](/sdk-reference/synthesis#export) (instead of a regular [`TranspilationConfig`](/sdk-reference/synthesis#transpilationconfig)) activates fault-tolerant transpilation. Its `clifford_t_approximation_error` parameter sets the error threshold for approximating the RZ rotations into Clifford+T gates, where a lower threshold gives a more accurate but deeper circuit.
### Circuit Metrics
Two new functions now report a program's resource estimates: [`get_circuit_metrics`](/sdk-reference/synthesis#get_circuit_metrics) returns the logical width, depth, and gate counts of the Qmod-based executable, without transpilation. [`get_transpiled_circuit_metrics`](/sdk-reference/synthesis#get_transpiled_circuit_metrics) transpiles the program using the synthesis preferences first, then returns the same counts for the resulting hardware-targeted circuit.
## Hardware Benchmarking
The new hardware benchmarking suite scores how accurately a backend runs standard quantum algorithms, and lets you compare across different hardware providers. To get started, open the Execution page within the Classiq IDE and switch to the Benchmark tab, then pick one of the available [predefined benchmarks](/user-guide/execution/benchmarking/predefined-benchmarks): GHZ, Adder, QFT, State Preparation, or Dynamical Localization.
At the bottom of the page, a panel describes the benchmark you chose and explains how it is scored. Set the range of problem sizes to sweep as min / max / step, select the backends, and set the shots per job; each backend has the option to be [run via Classiq](/user-guide/execution/budget-management) on an allocated budget, so no provider credentials are needed, and to be emulated against the device's noise model instead of the physical QPU.
Up to 10 backends can be selected, spanning QPUs, hardware emulators, and simulators, and a session can include up to 15 jobs, one per backend per problem size, so the number of backends times the number of problem sizes must not exceed 15.
Click Run to submit, and the results come back as a table of backend scores by problem size and a chart plotting them all together.
Each job receives a score between 0 and 1, where 1 means the measured outcomes match the noise-free ideal and lower values reflect hardware noise and error.
For a full walkthrough, see the [Benchmarking in the Classiq IDE](/user-guide/execution/benchmarking/predefined-benchmarks#benchmarking-in-the-classiq-ide) section of the Predefined Benchmarks user guide.
Benchmarks can also be run through the Python SDK, where [`run_benchmark`](/sdk-reference/execution#run_benchmark) takes a [`BenchmarkRequest`](/sdk-reference/execution#benchmarkrequest) and returns a [`BenchmarkSession`](/sdk-reference/execution#benchmarksession) to poll for results.
A dedicated SDK benchmarking package is on the way, adding support for custom benchmarks alongside the predefined ones. It is expected in the upcoming months.
## Enhancements
### New QLayer Interface for QNN
The new [`QLayerV2`](/user-guide/applications/qml/qnn/qlayerv2) is a cleaner, faster quantum layer for training [quantum neural networks](/user-guide/applications/qml/qnn/qnn). It accepts a synthesized quantum program and an optional list of [Pauli observables](/user-guide/modeling/observables-and-operators) (see example below), and produces a `torch` module with one output feature per observable, with no `execute` or `post_process` function to write. Its gradients use adjoint differentiation, so they are exact rather than finite-difference estimates, and training is much faster.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import Pauli
from classiq.applications.qnn import QLayerV2
layer = QLayerV2(
# a synthesized QuantumProgram
prog,
# optional observables to estimate; one output feature each (two in this case)
observables=[Pauli.Z(0), Pauli.X(1) + Pauli.Z(2)],
)
```
`QLayerV2` is set to supersede the existing [`QLayer`](/user-guide/applications/qml/qnn/qlayer) (now exported as `QLayerV1`) as the canonical interface. For a comparison and guidance on when to use each, see [Choosing between the two layers](/user-guide/applications/qml/qnn/qlayerv2#choosing-between-the-two-layers).
`QLayerV2` is Studio-only for now, with support outside Studio expected in the coming months.
### Language Ergonomics
Several small changes cut friction when writing in Qmod:
* New classical functions `range_` and `reversed_`, mirroring Python's `range` and `reversed`, are now available. They operate on Qmod classical variables within classical expressions.
* The `subscript` and `slice_` [path operators](/sdk-reference/qmod/path-operators) can now be imported directly from the top-level `classiq` package (`from classiq import *`), and no longer need an explicit import.
* Declaring a local quantum variable as a `QArray` or `QNum` now requires only its defining arguments, where a name was previously required as well.
### Direct Execution Session Configuration
Continuing the move toward flatter configuration, [`ExecutionSession`](/user-guide/execution/ExecutionSession) now accepts the advanced constructor arguments `noise_properties`, `amplitude_threshold`, `include_zero_amplitude_outputs`, and `job_name` directly, matching fields previously reachable only through [execution preferences](/sdk-reference/execution#executionpreferences).
### Backend Modality Data
The DataFrame returned by [`get_backend_details`](/user-guide/execution/index#step-2-—-inspect-available-backends) now includes a `modality` column, letting you filter and compare backends by modality when deciding where to execute your quantum program. The reported modalities are `superconducting`, `trapped-ion`, `simulator-cpu`, and `simulator-gpu`.
### Optional Execution Progress Logging
A `verbose` parameter was added to the execution functions and `ExecutionSession` methods, including [`sample`](/sdk-reference/execution#sample), [`observe`](/sdk-reference/execution#observe), [`variational_minimize`](/sdk-reference/execution#variational_minimize), and [`calculate_state_vector`](/sdk-reference/execution#calculate_state_vector). It allows the progress logging to be turned off (the "Submitting job to..." and "Job: ..." logs) by setting `verbose=False` (defaults to `True`). This is useful for repeated calls within a loop.
## Documentation Additions
* **[Hardware Benchmarking](/user-guide/execution/benchmarking) Guide:** Covering the new functional-level benchmarking suite, the different predefined benchmarks, how each is scored, and how to run them. For more information, see the [Hardware Benchmarking](#hardware-benchmarking) section above.
* **[QLayerV2](/user-guide/applications/qml/qnn/qlayerv2) Guide:** Covering the streamlined `QLayerV2` layer for hybrid QNNs, its interface and observables, worked examples, and how to choose between it and the existing [`QLayer`](/user-guide/applications/qml/qnn/qlayer). For more information, see the [New QLayer Interface for QNN](#new-qlayer-interface-for-qnn) section above.
## Library Additions
* **[Projection-Based Embedding](https://github.com/Classiq/classiq-library/blob/main/applications/chemistry/projection_based_embedding/projected_based_embedding_tutorial.ipynb):** A notebook demonstrating the [Wavefunction-in-DFT Embedding](/release-news/recap-june-2026#wavefunction-in-dft-embedding) capability added in June, putting the [`EmbeddingCalculator`](/sdk-reference/applications/chemistry#embeddingcalculator) to use on a water molecule. It treats a chemically active fragment with a quantum method such as VQE while describing the surrounding environment with DFT, then recombines the two to recover the total energy.
* **[Numerical Gradient Estimation](https://github.com/Classiq/classiq-library/blob/main/algorithms/quantum_primitives/gradient_estimation/gradient_estimation.ipynb):** Implementing Jordan's algorithm to estimate the gradient of a d-dimensional scalar function with a single quantum query, in place of the d+1 evaluations a classical finite-difference approach would require.
* **[Quantum Likelihood Estimation](https://github.com/Classiq/classiq-library/blob/main/algorithms/search_and_optimization/quantum_likelihood_estimation/quantum_likelihood_estimation.ipynb):** A hybrid algorithm for Hamiltonian learning that identifies an unknown Hamiltonian, accessible only through the time evolution it generates, from a candidate set. It implements the optimal variant, developed with the paper's authors, which jointly optimizes all five circuit parameters each iteration to make every measurement maximally informative. It converges in roughly an order of magnitude fewer experiments than standard QLE.
## Bug Fixes
* **Synthesis now catches unsafe qubit-layout changes in control-flow blocks:** reordering a quantum variable's qubits inside a `power`, `repeat`, `foreach`, or `if` block is now rejected up front with a descriptive error.
* **Classical path operators return correctly-typed results:** `subscript`, `slice_`, and `reversed_` in the Python SDK now correctly infer their result type from their argument.
* **`observe` no longer emits a spurious deprecation warning:** calling the [`observe`](/sdk-reference/execution#observe) function now runs cleanly, after previously surfacing a misplaced `submit_estimate() is deprecated` warning.
* **Quantum variable constructors reject non-string names cleanly:** passing a non-string name to `QArray`, `QNum`, `QBit`, or `QStruct` now raises a clear error, where it previously failed internally.
## Deprecations
* **`QuantumProgram.qasm` and `transpiled_circuit` deprecated:** following the synthesis architecture update, these `QuantumProgram` attributes are replaced by [`export`](/sdk-reference/synthesis#export) for a QASM circuit and [`get_circuit_metrics`](/sdk-reference/synthesis#get_circuit_metrics) or [`get_transpiled_circuit_metrics`](/sdk-reference/synthesis#get_transpiled_circuit_metrics) for resource estimation, as covered in the [synthesis architecture](#a-faster-scalable-synthesis-architecture) section above.
* **`execute_qnn` accepted observable type change:** `execute_qnn` now takes its observable as a `SparsePauliOp`; passing the deprecated `PauliOperator` is converted automatically, and emits a `DeprecationWarning`.
* **`slice` Qmod operator renamed to `slice_`:** calling `slice` now emits a deprecation warning; use `slice_` instead.
For the technical entries behind these changes, see the [Changelog](/release-notes).
# Release News: June 2026
Source: https://docs.classiq.io/release-news/recap-june-2026
Five versions released in June. Two ways to build with AI headline the month: a Quantum Engineer plugin that brings Classiq into Claude, Cursor, and Codex, and a no-code Assistant on the platform.
A Quantum Engineer plugin for AI coding agents, and a Classiq platform assistant
GPU simulation, molecular embedding, streamlined remote execution, and more
New user guides for the AI capabilities and M2M authentication
Correctness fixes and one function removal
## AI with Classiq
Two separate AI capabilities shipped this month; if you work locally, the Quantum Engineer plugin enables your coding agent to model, synthesize, execute, and analyze quantum programs with Classiq. If you work on the platform, the Classiq Assistant turns a description into a synthesized, executable program, and answers your questions along the way.
For further reading, refer to the [Classiq blog](https://www.classiq.io/insights/classiqs-quantum-engineering-agents-now-in-your-ide-and-the-platform).
### Quantum Engineer Plugin
The plugin draws its capability from a set of **Classiq skills** paired with the **Classiq MCP**: it writes in Qmod (through the Classiq SDK), builds on validated components from the Classiq Library, and synthesizes on Classiq's backend engine to produce optimized circuits. That grounding is what lets it pull ahead on hard work, such as reproducing paper implementations, research, and multi-step applications you refine over time. The plugin is available to Classiq's enterprise customers.
For more information, including a full breakdown of the skills for each phase of quantum algorithm development, see the [Quantum Engineer Plugin](/user-guide/ai/quantum-engineer-plugin) user guide. To request access, [contact us](https://www.classiq.io/contact-us).
### Classiq Assistant (Beta)
The new Classiq Assistant, built within the Classiq platform, takes you from an idea to a working quantum program. It accepts natural-language descriptions or circuit images, builds a Qmod-native model, synthesizes it, and opens the result on the Quantum Program page.
You start from the new text input box at the center of the home page, with no prior installation or configuration needed:
From there, the assistant follows you onto the Quantum Program page, opening as a side panel:
It keeps the context of your session, attaching the circuit you currently have open to the conversation, so you can ask it to explain what the program does, predict what results to expect, or refine the model, all in one continuous flow. It also answers conceptual questions about quantum computing, and a new chat starts fresh whenever you move to a different problem. When the program is ready, Execute takes it straight to a backend.
For more information, see the [Classiq Assistant](/user-guide/ai/classiq-assistant) user guide.
## Enhancements
### NVIDIA DGX Statevector Simulator
Statevector simulations can now run on a GPU-accelerated backend hosted on an NVIDIA DGX system. Selected by passing `backend="classiq/dgx_simulator"`, it handles up to **35 qubits** in single precision (float32) across both **sampling** and **statevector** modes. Exact simulation at this scale lets you validate larger algorithms, so you can catch errors in the logic before spending resources running on real hardware. Access requires specific license permissions; see [DGX Statevector Simulator](/user-guide/execution/cloud-providers/classiq-backends#dgx-statevector-simulator).
### Wavefunction-in-DFT Embedding
Simulating a full molecule at quantum accuracy quickly outgrows the qubit budget of current hardware, yet most of the chemistry that matters happens in a small, chemically active region of it. The new [`EmbeddingCalculator`](/sdk-reference/applications/chemistry#embeddingcalculator) class runs projection-based embedding to exploit exactly that: it partitions a molecular system into an active fragment, treated with a quantum algorithm such as VQE, and a surrounding environment described by DFT. The calculator drives the full DFT-and-embedding pipeline server-side and returns Hamiltonians ready to hand to a quantum solver.
A notebook walking through a complete example is coming in July.
### Streamlined Remote Execution
Two changes cut the job and queueing overhead of running on remote cloud hardware:
* **Hosted optimization on [IonQ](/user-guide/execution/cloud-providers/ionq-backends):** The [`variational_minimize`](/sdk-reference/execution#variational_minimize) variants (standalone function and `ExecutionSession` methods), used for variational algorithms such as VQE or QAOA, now accept `hosted=True` to run the entire optimization loop on IonQ Hosted Hybrid as a single Classiq execution job. Previously each optimizer iteration was submitted as its own Classiq sample job, so the job count grew with the optimization; now the SDK submits and polls that one job, while the Classiq backend handles all communication with IonQ.
Code Example:
[comment]: DO_NOT_TEST
```python theme={null}
with ExecutionSession(qprog, backend="ionq/...") as es:
result = es.variational_minimize(hamiltonian, initial_params, hosted=True)
```
Hosted mode has specific configuration requirements; see [`variational_minimize`](/sdk-reference/execution#variational_minimize) for details.
* **Persistent IBM Runtime sessions:** When you run on a remote [IBM backend](/user-guide/execution/cloud-providers/ibm-backends) inside a single [`ExecutionSession`](/user-guide/execution/ExecutionSession), successive primitives (`sample`, `observe`, `estimate_cost`, `variational_minimize`, and non-blocking counterparts) now reuse one IBM Quantum Runtime session rather than each opening its own. On busy hardware, where each session waits in the queue, keeping the session open across a multi-step workflow means you queue once instead of at every step.
No flag needed; the session reuse happens **automatically**:
[comment]: DO_NOT_TEST
```python theme={null}
with ExecutionSession(qprog, backend="ibm/...") as es:
counts = es.sample() # opens one IBM Runtime session
energy = es.observe(hamiltonian) # reuses the same session
```
### Per-Call Shot and Routing Overrides
Within an execution session, [`ExecutionSession.sample()`](/user-guide/execution/ExecutionSession#operations), `observe()`, and `variational_minimize()` (and their `submit_*` counterparts) now accept optional `num_shots` and `run_via_classiq` keyword arguments that override the session defaults for **that invocation only**. This lets the session hold your shared defaults while you vary shot counts or execution routing per primitive call.
Code Example:
[comment]: DO_NOT_TEST
```python theme={null}
with ExecutionSession(qprog, num_shots=1000) as es:
quick = es.sample() # uses the session default of 1000 shots
precise = es.sample(num_shots=8000) # overrides for this call only
```
### Visualizer Label Management
The [quantum program visualizer](/user-guide/analysis/visualization-of-quantum-programs) now keeps large circuits readable with finer control over variable labels. Previously, the same variable name repeated down every wire added visual noise that could obscure the circuit's architecture.
What has been updated:
* Adjacent repeating labels are suppressed automatically, cutting the clutter.
* A suppressed label is never lost: hover over the wire for a tooltip with the hidden name.
* A right-click context menu on each variable wire lets you show or hide individual labels as needed.
For example, a circuit with label repeats suppressed:
As opposed to the previous circuit visualization:
### LaTeX Export for Large Circuits
LaTeX export on the Quantum Program page now also handles very large circuits, rendering them as publication-quality diagrams.
## Documentation Additions
* **[Quantum Engineer Plugin](/user-guide/ai/quantum-engineer-plugin):** Install and set up the plugin in your AI coding agent, with a breakdown of the skills for each development phase and worked examples to start from.
* **[Classiq Assistant: Getting Started](/user-guide/ai/classiq-assistant):** Access the platform assistant, generate and refine a program from a prompt, and learn the best practices for prompting it well.
* **[M2M Authentication](/user-guide/authentication/m2m-authentication):** Authenticate backend services to the Classiq platform with no human intervention required, using the non-interactive machine-to-machine flow built on the OAuth 2.0 client credentials grant.
## Bug Fixes
* **Loops and controls that reuse variables now compile correctly:** [`foreach`/`power`](/qmod-reference/language-reference/statements/classical-control-flow) loops that modified quantum-numeric variables used in later comparisons, and [`control`](/qmod-reference/language-reference/statements/control) statements whose bodies reused their condition variables, could previously produce incorrect circuits (the latter by leaking a phase onto the controlled state).
* **`subscript` now accepts a quantum expression as its index:** Indexing a [`subscript`](/qmod-reference/language-reference/expressions#path-operators) with a quantum expression (for example `res ^= subscript(table, a + b)`) previously raised an internal error; such expressions are now lowered and synthesized correctly.
* **Classical expressions can now reuse a variable:** A classical expression that reuses a variable, such as the exponent `k + k` in `power(k + k, ...)`, no longer fails with "both sides of the operation are identical"; that restriction now applies only to in-place quantum arithmetic.
* **Clearer error message when exporting parametric programs to QASM 2:** Exporting a parametric program with the default `target_language=TargetLanguage.QASM2` now raises an indicative error suggesting QASM 3, rather than an unclear internal one.
* **The visualizer stays responsive on oversized function blocks:** Running Expand All on a function block with too many child operations to render could previously freeze or crash the browser tab. It now stops with a warning that the block is too large to visualize, and the same warning appears when expanding a single oversized block.
## Deprecations
* **`exponentiation_with_depth_constraint` removed:** This function exponentiated a Pauli operator (Hamiltonian simulation) while automatically selecting Suzuki-Trotter parameters to fit a target maximum circuit depth. It has now been removed after a deprecation period. Use [`exponentiate`](/sdk-reference/qmod/functions/core_library/exponentiation) for Hamiltonian exponentiation, or the [`suzuki_trotter`](/qmod-reference/library-reference/core-library-functions/hamiltonian_evolution/suzuki_trotter/suzuki_trotter) family and [`qdrift`](/qmod-reference/library-reference/core-library-functions/hamiltonian_evolution/qdrift/qdrift) when you need explicit control over the decomposition order and repetitions.
For the technical entries behind these changes, see the [Changelog](/release-notes).
# Release News: May 2026
Source: https://docs.classiq.io/release-news/recap-may-2026
Five versions released in May, spanning improvements to the execution workflow, scalability, and quantum developer experience.
New top-level execution functions and simplified execution session methods
New capabilities and performance improvements
New guides and notebooks
Correctness fixes and API deprecations
## Simplified Execution
The execution workflow has been refreshed across several areas:
* Three new top-level execution functions for one-call execution and result retrieval.
* New `ExecutionSession` methods for simplified execution.
* `ExecutionSession` preferences can now be passed directly.
* OpenQASM 2.0 and 3.0 strings now accepted in place of a `QuantumProgram`.
### New Top-Level Execution Functions
Three new top-level functions now enable execution and result retrieval in a single call, each returning results directly:
* `sample()` for shot-based measurement statistics, returned as a DataFrame.
* `observe()` for the expectation value of a Hermitian observable, returned as a scalar.
* `calculate_state_vector()` for the full quantum state including amplitudes and phases, returned as a DataFrame (simulators only).
Previously, this required managing job objects manually: submitting, polling, and unpacking results through separate API calls.
All three support single and batch execution and accept the same arguments, as well as `run_via_classiq`. See the [Execution](/user-guide/execution) user guide for the full workflow and function reference.
Usage examples:
```python theme={null}
from classiq import *
# Example function: Applies a Hadamard gate on a single qubit
@qfunc
def main(res: Output[QBit]):
allocate(res)
H(res)
# Synthesizing the model into a quantum program
qprog = synthesize(main)
# Shot-based measurement statistics
df = sample(qprog, num_shots=1000)
# Expectation value of an observable (Pauli Z matrix)
value = observe(qprog, observable=Pauli.Z(0), num_shots=1000)
# Full quantum state (simulators only)
df = calculate_state_vector(qprog)
```
### Updated Execution Session Methods
New `ExecutionSession` methods `sample()` and `estimate()` replace earlier dedicated batch functions (see [Execution Session](/user-guide/execution/ExecutionSession#operations) user guide), supporting both single and batch execution by accepting a parameter dictionary or a list of dictionaries.
The dedicated `batch_sample`, `submit_batch_sample`, `batch_estimate`, and `submit_batch_estimate` methods are deprecated as a result, with a removal date of **June 22nd, 2026**.
Usage examples:
[comment]: DO_NOT_TEST
```python theme={null}
with ExecutionSession(qprog) as es:
# Single execution
result = es.sample({"t": 0.5})
# Batch execution (2 iterations)
results = es.sample([{"t": 0.5}, {"t": 0.6}])
# Expectation value
hamiltonian = Pauli.Z(0)
value = es.estimate(hamiltonian, {"t": 0.5})
# Batch expectation values (2 iterations)
values = es.estimate(hamiltonian, [{"t": 0.5}, {"t": 0.6}])
```
In addition, the `ExecutionSession` method `minimize()` for variational optimization of a cost function over the quantum program's initial parameter values has been renamed to `variational_minimize`.
`variational_minimize` is now also available as a standalone function, usable outside the scope of `ExecutionSession`. It supports Hamiltonian and classical cost functions, `run_via_classiq`, and includes improved input validation. For more details, see [SDK Reference](/sdk-reference/execution#variational_minimize).
### Direct Execution Session Preferences
`ExecutionSession` now also accepts configuration parameters directly as keyword arguments, rather than through a separate `ExecutionPreferences` object.
Usage example:
[comment]: DO_NOT_TEST
```python theme={null}
with ExecutionSession(qprog, num_shots=2000, random_seed=42) as es:
results = es.sample()
```
Passing an `ExecutionPreferences` object via `execution_preferences=` can still be used, but is deprecated and will be removed on **June 22nd, 2026**.
Parameters that `ExecutionSession` may now accept directly: `backend`, `num_shots`, `random_seed`, `transpilation_option`, `run_via_classiq`, `config`.
### OpenQASM Support
OpenQASM 2.0 and 3.0 strings are now accepted directly by `sample()` and `ExecutionSession` as an alternative to a synthesized `QuantumProgram`. Results are returned in the same histogram DataFrame format.
Note that the `parameters` argument is not supported for OpenQASM strings. For parametric circuits, use a `QuantumProgram`, or bind parameters inside the QASM circuit directly. See the [Execution](/user-guide/execution) and [Execution Session](/user-guide/execution/ExecutionSession#initializing) user guides for more details.
## Enhancements
### Seamless Support for Larger Models
The SDK now handles significantly larger synthesis and execution workloads without hitting payload size limits. Upgraded backend data handling enables seamless processing of large-scale models and datasets, requiring no changes from users.
### Improved Visualizer Rendering
The visualizer can now fully render large circuits, with all child operations visible. This lifts a previous limitation where a per-block child operation limit could leave some operations unrendered in large circuits.
### GitHub Copilot in Classiq Studio
GitHub Copilot is now available within Classiq Studio, our web-based pre-configured IDE. It includes three main capabilities:
* **Chat-based AI Assistant**: ask questions about the Qmod language, Classiq workflow, or circuit debugging.
* **Coding agent**: let Copilot write or refactor your Qmod code.
* **Autocomplete**: inline suggestions as you write your quantum algorithm within the Studio.
The Copilot is available on Classiq Studio without any additional setup if you hold an active GitHub Copilot subscription.
### Faster Synthesis for Large Hamiltonians
Synthesis for models containing large Hamiltonian objects is now significantly faster. If you have been working with molecule simulations or large combinatorial problems and synthesis felt slow, this directly cuts that wait time.
See [Observables and Operators](/user-guide/modeling/observables-and-operators) for how Hamiltonians are defined and used in Qmod.
### Qmod-Variable Array Slice Operator
`classiq.qmod.symbolic` now includes a `slice(array, start, stop)` operator that accepts unsigned integer Qmod variables as the `start` and `stop` arguments (see [Path Operators](/qmod-reference/language-reference/expressions#path-operators)). It is the slice counterpart to the existing `subscript` operator for single-element access.
When `array` is a Qmod variable, the standard bracket syntax `array[start:stop]` can be used directly; the `slice()` syntax is required when `array` is a regular Python list and integer Qmod variables are used as indices.
### QSVM Application (QML)
A new [Quantum Support Vector Machine](/sdk-reference/applications/QSVM) (QSVM) module is now available in the Classiq Python SDK. It combines quantum-computed kernel matrices with classical SVMs, enabling quantum-enhanced classification through a `QSVM` class with `train`, `test`, and `predict` methods.
Users can select from built-in quantum feature maps or supply their own. The SDK handles circuit synthesis, execution, and kernel-matrix construction automatically. Relevant notebooks in the Classiq Library have been updated accordingly.
### New SDK Utilities
Two new utility functions have been added to the SDK for diagnostics and backend exploration:
* **`print_diagnostics()` function:** A new `classiq.print_diagnostics()` function prints a snapshot of the current SDK environment, including SDK version, Python version, backend host and version, authentication status, and user ID. Useful for quick inclusion in support tickets.
* **`get_backend_details()` function:** A new function that returns a DataFrame of all supported quantum backends, with details on provider, backend name, type (hardware or simulator), qubit count, availability, pending jobs, and queue time. For details, see the [Execution](/user-guide/execution/index#step-2--inspect-available-backends) user guide.
## Documentation Additions
* **[Hello World](/getting-started) Guide:** Build, synthesize, and run your first quantum algorithm, covering everything you need before diving deeper into the Classiq platform.
* **Streamlined [Execution](/user-guide/execution) and [Execution Session](/user-guide/execution/ExecutionSession) Guides:** The Execution and Execution Session user guides have been updated to cover the three new execution functions, the updated `ExecutionSession` methods, direct preferences passing, and a step-by-step workflow guide. See the [Simplified Execution](#simplified-execution) section for more details.
## Library Additions
* **1D Fermi-Hubbard Model Simulation:** A new [notebook](https://github.com/Classiq/classiq-library/blob/main/applications/physical_systems/fermi_hubbard_model_1D/fermi_hubbard_1D.ipynb) for simulating the 1D Fermi-Hubbard model has been added to the Classiq Library. The Fermi-Hubbard model is a key model in condensed matter physics; this notebook, inspired by Google Quantum AI's 2020 experiment, demonstrates state preparation, time evolution, and spin-charge separation using the Classiq SDK.
The implementation is fully high-level, with optimized quantum circuits generated automatically.
## Bug Fixes
* **Fixed unintended relative phase in controlled amplitude preparation:** `prepare_amplitudes` and `inplace_prepare_amplitudes` state preparation functions (see [state preparation routines](/qmod-reference/library-reference/core-library-functions/prepare_state_and_amplitudes/prepare_state_and_amplitudes)) could introduce an unintended global phase in certain scenarios. For the uncontrolled version this is unobservable, but when used inside a `control()` statement (see [control](/qmod-reference/language-reference/statements/control)), the global phase could become a relative phase conditional on the control qubit. This is now fixed.
* **Combinatorial optimization now handles degenerate constraints correctly:** `CombinatorialProblem` converts classical optimization problems into quantum models for algorithms like QAOA (see [Learning Optimization](/explore/tutorials/basic_tutorials/optimization/learning_optimization#learning-optimization)). A `KeyError` that was raised when an inequality constraint became degenerate (collapsed to a single feasible value) after another constraint had already fixed one of its variables to a single value is now corrected.
* **Inconsistency in gate arguments of QASM output resolved:** `QuantumProgram.qasm` could produce incorrect gate arguments in certain scenarios. While transpilation would correct this automatically during synthesis, the problem could carry through to simulation when manually disabling transpilation via `transpilation_option=TranspilationOption.NONE` (see [Quantum Program Transpilation](/user-guide/synthesis/quantum-program-transpilation)). This is now fixed.
* **Models saved with older SDK versions can now be successfully synthesized:** A compatibility issue that prevented most models saved with earlier SDK versions from being synthesized is now resolved.
* **Circuit visualizer now able to recover from GPU context loss:** The visualizer would go blank and fail to recover if the WebGPU/WebGL graphics context was lost. The visualizer now includes automatic recovery from context loss.
* **NVIDIA GPU worker now initializes correctly:** An issue that caused the NVIDIA GPU worker to fail during initialization is now fixed.
## Deprecations
* **`ExecutionSession` batch methods deprecated:** `batch_sample` and `batch_estimate` are replaced by passing parameters directly to `ExecutionSession.sample()` or `ExecutionSession.estimate()`, as covered in the [Simplified Execution](#updated-execution-session-methods) section above.
Removal date: **June 22nd, 2026**.
* **`ExecutionPreferences` object deprecated:** Replaced with direct keyword arguments in `ExecutionSession`, as covered in the [Simplified Execution](#direct-execution-session-preferences) section above.
Removal date: **June 22nd, 2026**.
* **`theta` parameter of `phase` renamed to `coefficient`:** The old `theta` parameter name has been deprecated and removed for the `phase` function specifically; it remains valid in other functions.
* **`randomized_benchmarking` function deprecated and removed:** This function has been deprecated and removed from the SDK.
* **`pretty_qasm` field in Synthesis Preferences removed:** OpenQASM 2 output is now always formatted with line breaks inside gate declarations (the previous default). If you were explicitly setting `pretty_qasm=False` to get unformatted output, that option no longer exists (see [synthesis preferences](/user-guide/synthesis/preferences) user guide).
# Changelog
Source: https://docs.classiq.io/release-notes/index
A chronological record of changes and improvements for each release.
## Upgrade Instructions
* [Python SDK](/getting-started/sdk_installation#platform-version-updates)
* The IDE upgrades automatically.
## Releases by Version
## Bug Fixes
* **Synthesis:** Fixed a bug where automatic uncomputation silently dropped a rolled `repeat` or `foreach` loop, or a `skip_control` body, from a function that had a variable to uncompute, producing an incorrect circuit.
## Interface Changes
* **Synthesis:**
* The compiler now rejects a program that changes a quantum variable's qubit layout across a compile-once boundary. Reordering the variable's qubits, or routing it onto different qubits, inside a `power`, `repeat`, `foreach`, `if`, `control`, or `invert` block, or across a function body, now raises an error; re-join the variable's parts in their original order with a `bind` statement instead.
* Comparing a quantum number against a constant (`x < 5`, `x >= 2.5`, and the other relations, in either operand order) is now computed directly, without allocating a scratch register. Previously it computed `x` minus the constant in an operand-width register, where the sign bit gives the comparison result. The compiler picks the implementation automatically to fit the optimization objective and any `max_width` constraint; the narrowest needs no auxiliary qubits, so a comparison now fits even where there is no spare width. Signed and fixed-point operands work as before, and under a `control`, the control is built into the comparison rather than applied to each of its gates, so a conditional comparison costs almost the same as an unconditional one.
* **Language:** The open library function `inplace_binary_to_one_hot` now takes separate input and output arguments (`source: Input[QArray]`, `target: Output[QArray]`) instead of a single in-out array argument.
## Announcements
* **Platform access is now by invitation only.** Free access is not currently available. Existing users are not affected and retain full access to the platform.
## Enhancements
* **New QNN layer [`QLayerV2`](../user-guide/applications/qml/qnn/qlayerv2):** A simpler, faster quantum layer, available only within Classiq Studio at the moment. It accepts a synthesized quantum program and an optional list of Pauli observables, and returns a `torch` module with one output feature per observable - no `execute` or `post_process` function to write. Gradients use adjoint differentiation, so they are exact rather than finite-difference estimates, and training is much faster. For sampling, custom post-processing, backend selection, or remote execution, keep using [`QLayer`](../user-guide/applications/qml/qnn/qlayer). Import it with `from classiq.applications.qnn import QLayerV2`.
* **Synthesis:** An in-place increment or decrement of a quantum number by 1 (`x += 1`, `x += -1`), including inside a `control` block, now uses a flexible, fault-tolerant increment primitive, automatically optimized for either circuit width or CX count according to the `max_width` constraint and the optimization parameter.
## Interface Changes
* **Execution:** Added a `verbose` parameter (default `True`) to the execution functions `sample`, `observe`, `variational_minimize`, and `calculate_state_vector`, and their `ExecutionSession` counterparts (including `submit_calculate_state_vector`). Set `verbose=False` to suppress the progress logging they would otherwise print (the `Submitting...` and `Job: ...` lines), useful when calling these functions repeatedly in a loop.
* **`QLayerV1` alias:** `QLayer` is now also exported as `QLayerV1`, distinguishing it from the new `QLayerV2`.
## Bug Fixes
* **Synthesis:** Fixed a bug where changing a quantum variable's qubit layout inside a `power`, `repeat`, `foreach`, or `if` block (for example, by reordering its qubits) silently produced an incorrect circuit; such programs are now rejected with a descriptive error.
* **Classiq Studio:** `QLayer` and `execute_qnn` now work in Classiq Studio for programs synthesized with the new synthesis flow. The in-process Studio simulator obtained its circuit through an export path that raised `ClassiqInternalError` for such programs, which made local simulation there unusable. Circuits of up to 12 qubits (previously 10) are now simulated in-process.
## Enhancements
* **IDE hardware benchmarking:** Predefined hardware benchmarks are now also available in the Classiq IDE, through the new Benchmark tab within the Execution page. This no-code interface sweeps a range of problem sizes across multiple backends and returns a per-backend score for the same set of well-established circuits (GHZ, Adder, QFT, State Preparation, and Dynamical Localization). See the [Predefined Benchmarks](../user-guide/execution/benchmarking/predefined-benchmarks#benchmarking-in-the-classiq-ide) user guide for a walkthrough of configuring and running a benchmark.
* **Synthesis:** Improved the runtime performance of [`export`](../sdk-reference/synthesis#export) when targeting a fault-tolerant gate set via [`FaultTolerantTranspilationConfig`](../sdk-reference/synthesis#faulttoleranttranspilationconfig).
* **Language:** The `subscript` and `slice_` [path operators](../sdk-reference/qmod/path-operators) can now be imported directly from the top-level `classiq` package and are picked up by `from classiq import *`, so they no longer need to be imported explicitly from `classiq.qmod.symbolic`.
## Bug Fixes
* **`observe`:** Calling [`observe`](../sdk-reference/execution#observe) no longer emits a spurious `submit_estimate() is deprecated` warning. The function now routes internally through `submit_observe`.
## Interface Changes
* Renamed the `slice` Qmod operator to `slice_`. The `slice` name is now deprecated and emits a deprecation warning when called; use `slice_` instead.
## Enhancements
* **Synthesis:** The executable representation of a quantum program returned by [`synthesize`](../sdk-reference/synthesis#synthesize) is now Qmod-based, significantly improving compilation performance and enabling quantum programs to scale better. Execution, resource estimation, and quantum program visualization now operate directly on the Qmod-based representation. [`export`](../sdk-reference/synthesis#export) can be used to generate the corresponding description in an external format, such as OpenQASM 2.0, OpenQASM 3.0, or QIR.
* **Language:** `QArray` and `QNum` now accept their arguments positionally when the variable name is omitted, so a call such as `QArray(QBit, 2)` or `QNum(4)` works as intended instead of raising an internal error. Passing a non-string name to any quantum variable constructor (`QArray`, `QNum`, `QBit`, or `QStruct`) now raises a clear error instead of failing internally.
## Bug Fixes
* Fixed the `subscript`, `slice`, and `reversed_` classical functions in the Python SDK, which returned wrong-typed objects instead of inferring the result type from their argument (for example, subscripting a nested list returned a scalar that could not be indexed further).
## Interface Changes
* **[`QuantumProgram`](../sdk-reference/synthesis#quantumprogram) circuit attributes:** Deprecated the `qasm` and `transpiled_circuit` attributes of `QuantumProgram`, following the move to a Qmod-based synthesis representation; they will no longer be supported in a future release.
* Use [`export`](../sdk-reference/synthesis#export) to obtain a circuit in an external format such as OpenQASM 2.0.
* Use [`get_circuit_metrics`](../sdk-reference/synthesis#get_circuit_metrics) for approximate circuit depth and gate counts, and [`get_transpiled_circuit_metrics`](../sdk-reference/synthesis#get_transpiled_circuit_metrics) for accurate depth and gate counts after transpilation.
* **Legacy synthesis flow:** To continue using the legacy synthesis flow from version 1.21.0 and earlier, set the Boolean [`compatibility_mode`](../sdk-reference/synthesis#compatibility_mode) attribute under [`Preferences`](../sdk-reference/synthesis#preferences).
* **Execution:** [`ExecutionSession`](../sdk-reference/execution#executionsession) now accepts the advanced flat constructor arguments `noise_properties`, `amplitude_threshold`, `include_zero_amplitude_outputs`, and `job_name`, matching the fields previously available only through `execution_preferences`.
## Enhancements
* **Hardware benchmarking:** Added predefined hardware benchmarks that measure and compare how well quantum backends run a set of well-established quantum circuits (GHZ, Adder, QFT, State Preparation, and Dynamical Localization). Sweep a range of problem sizes across multiple backends and get a per-backend score from the SDK via [`run_benchmark`](../sdk-reference/execution#run_benchmark) (and soon in the new Benchmark mode on the IDE Execution page). See the new [Predefined Benchmarks](../user-guide/execution/benchmarking/predefined-benchmarks) user guide.
* **Classiq Studio:** [`execute_qnn`](../user-guide/applications/qml/qnn/qlayer#execution) now runs locally via the Studio simulator. Sampling runs locally, and requests that pass an observable now compute exact (state vector, shot-free) expectation values locally instead of falling back to remote simulation.
* **QLayer observables:** [`QLayer`](../user-guide/applications/qml/qnn/qlayer) now accepts a keyword-only `observable` (a `SparsePauliOp`, the same type accepted by `ExecutionSession.observe`) when constructed without a custom `execute` function. The layer estimates the observable's expectation value instead of sampling: exact state vector expectation values inside Classiq Studio, and the `observe` flow remotely. The `post_process` callback receives a `SavedResult` wrapping an `EstimationResult` (read the value via `result.value.value.real`), and gradients work unchanged.
* **Language:** Added the `range_` and `reversed_` classical functions, available both in classical expressions and in the Python SDK.
## Bug Fixes
* **Synthesis:**
* Fixed `power` applied to a `foreach` loop, which distributed the exponent into each iteration instead of raising the whole loop to the power.
* Fixed `invert` applied to a `foreach` loop, which kept the original iteration order instead of reversing it.
## Interface Changes
* **execute\_qnn observable type:** `execute_qnn` now takes the observable as a `SparsePauliOp` (the same type accepted by `ExecutionSession.observe`). Passing the legacy `PauliOperator` is deprecated; it is converted automatically and emits a `DeprecationWarning`.
## Enhancements
* **AI with Classiq:**
* **Classiq Assistant (Beta):** Added an AI assistant to the platform home page and the Quantum Program page. Describe a quantum problem in natural language to the assistant (or upload a circuit image), and it will build a qmod-native model, synthesize it into a quantum program, and open it on the Quantum Program page. The assistant keeps conversation context within a session and supports follow-up messages, so you can ask it to explain or refine the circuit. For more information, see the new [Classiq Assistant](../user-guide/ai/classiq-assistant) user guide.
* **Quantum Engineer Plugin:** Added a Quantum Engineer plugin that brings Classiq into local AI coding agents such as Claude, Cursor, and Codex. The plugin pairs a set of Classiq skills with the Classiq MCP, letting the agents model, synthesize, execute, and analyze quantum programs across the full Classiq workflow. For more information, see the new [Quantum Engineer Plugin](../user-guide/ai/quantum-engineer-plugin) user guide.
## Enhancements
* **Execution:** Added the option to run on a GPU-accelerated statevector simulator hosted on an NVIDIA DGX system, selected by passing `backend="classiq/dgx_simulator"`. It supports both sampling and statevector modes and handles circuits of up to 35 qubits in single precision (float32). Access requires specific license permissions. See [DGX Statevector Simulator](../user-guide/execution/cloud-providers/classiq-backends#dgx-statevector-simulator).
* **Synthesis:**
* Added a new `export` function to the SDK that converts a synthesized quantum program into a circuit string in a chosen target language (QASM2, QASM3, QIR, Cirq JSON, or Q#), with an optional transpilation configuration. See [export](../sdk-reference/synthesis#export).
* Improved the algorithm that approximates RZ rotations over the Clifford+T basis when exporting to a fault-tolerant gate set (via [`FaultTolerantTranspilationConfig`](../sdk-reference/synthesis#faulttoleranttranspilationconfig)), which now uses gridsynth to produce lower-error decompositions.
* **Projection-based WF-in-DFT embedding:** Added a new `EmbeddingCalculator` API for running projection-based wavefunction-in-DFT (WF-in-DFT) embedding calculations. This method enables accurate quantum-chemistry simulations of large molecules by treating a small active fragment with a quantum solver while capturing the effect of the surrounding environment at the DFT level. Users define a molecule via `MoleculeSpec` (supporting inline geometry, `.pdb`, and `.xyz` files) and configure the embedding with `EmbeddingConfig` (fragment atom selection, DFT mean-field method, exchange-correlation functional, active-virtual selection, and optional core freezing). The calculator drives a three-stage pipeline, full-system DFT, fragment embedding, and Hamiltonian construction, entirely server-side as queued backend jobs, returning the embedded and physical Hamiltonians as `openfermion.FermionOperator` objects ready for a quantum solver.
* Both blocking (`run_dft`, `run_dft_embedding`) and non-blocking (`submit_dft`, `submit_dft_embedding`) execution modes are supported; the non-blocking variants return a `ChemistryJob` handle that can be polled, cancelled, or reconnected from a later process via `ChemistryJob.from_id`.
* Built-in validation diagnostics (`DFT-in-DFT`, `FCI active space`, `probability leak`, `trace conservation`, `geometry perturbation`) can run automatically at the end of the embedding pipeline or be requested post-hoc via `run_validations`.
* Restricted and unrestricted spin treatments are supported, with an `AUTO` mode that resolves based on the number of unpaired electrons.
* **Classiq Studio:**
* The Studio image now installs the Classiq SDK with all optional dependencies (`analyzer_sdk`, `qml`, `chemistry`, `qsp`, and `cudaq`) automatically.
* When executing inside Classiq Studio, `execute_qnn` now runs sampling locally via the Studio simulator; requests that pass an observable continue to use remote simulation.
## Bug Fixes
* Fixed Latex export failures on large circuits.
## Enhancements
* **Execution:** Benchmarking is now available, with built-in benchmark classes and an end-to-end flow for creating and running benchmark jobs. Supported benchmark classes are `GHZ`, `Adder` & `Dynamic Localization`.
## Enhancements
* **IonQ Hosted Hybrid variational minimization:** On IonQ backends, `variational_minimize`, `ExecutionSession.variational_minimize`, and `ExecutionSession.submit_variational_minimize` now accept `hosted=True` to delegate the full optimization loop to IonQ's Hosted Hybrid service instead of executing a separate Classiq sample job on every iteration. Classiq submits and polls a single IonQ optimization job through the standard execution job API, so the SDK never contacts IonQ directly. Hosted mode requires a Hamiltonian cost function, a single execution parameter (`CReal` or `CArray`), and `quantile=1.0`; classical Qmod cost functions and CVaR (`quantile < 1.0`) are not supported.
* **Sticky IBM Runtime sessions under `ExecutionSession`:** When you run on a remote IBM backend inside a single `ExecutionSession`, successive primitives (`sample`, `observe`, `estimate_cost`, `variational_minimize`, and their non-blocking `submit_*` counterparts) reuse the same IBM Quantum Runtime session instead of opening a new one for every job. This reduces queue overhead for multi-step workflows such as variational optimization followed by a validation sample.
## Interface Changes
* **`ExecutionSession.close()`:** Closing a session now calls a server-side close API that releases provider resources, including an open IBM Runtime session. Using `ExecutionSession` as a context manager (recommended) invokes `close()` automatically when the block exits.
## Bug Fixes
* **Incorrect circuits from `foreach`/`power` loops that modify a quantum-numeric variable:** When the body of a `foreach` or `power` loop modified a quantum-numeric variable, a comparison against that variable (for example `x == 0`) could be folded against its value at loop entry instead of its actual per-iteration value, producing an incorrect circuit. Such comparisons are no longer folded against stale bounds.
* **Incorrect circuit for a control whose body reuses the condition variable:** A control such as `control(q == 0, lambda: Z(q))` whose controlled block operates on the same variable used in the condition could leak a phase onto the controlled state, producing an incorrect circuit. The condition is now computed out of place when the variable is reused, so such controls compile correctly.
* **Internal error when indexing a `subscript` with a quantum expression:** Using a quantum expression as the index of a `subscript` (for example `res ^= subscript(table, a + b)`) raised an internal error instead of synthesizing. Such expressions are now lowered correctly by computing the index into a temporary quantum variable.
* **Error when a classical expression repeats a variable (for example `k + k`):** Expressions that used the same classical variable on both sides of an operation, such as `power(k + k, ...)` or two consecutive `power(k, ...)` blocks, failed with "both sides of the operation are identical". This restriction only applies to in-place quantum arithmetic and is no longer enforced on classical expressions.
* **Internal error when exporting a parametric program to QASM2:** Calling `export` on a parametric quantum program with the default `target_language=TargetLanguage.QASM2` failed with an opaque internal error, since QASM2 cannot represent parametric circuits. It now raises an indicative error suggesting `target_language=TargetLanguage.QASM3` instead.
* **QP Visualization:** Fixed Expand All freezing or crashing the browser tab on very large function blocks. In the quantum program visualizer (Classiq Studio and the Classiq IDE), expanding all operations when a function block had too many child operations to render could freeze or crash the tab. Expand All is now blocked in these cases with a warning that the function block is too large to visualize, and expanding an individual block over the same limit shows the same warning instead of failing silently or crashing.
## Interface Changes
* **`exponentiation_with_depth_constraint` removed:** The previously deprecated `exponentiation_with_depth_constraint` function has been removed. Use `exponentiate` instead.
## Enhancements
* **Hardware modality in `get_backend_details`:** The DataFrame returned by `get_backend_details` now includes a `modality` column (for example, `superconducting`, `trapped-ion`, `simulator-cpu`, or `simulator-gpu`), exposing the modality already tracked in the hardware catalog. Backends without a recorded modality show `None`.
* **Jobs page results display:** The measurement results and state vector histograms now show at most the 64 highest-probability states; circuits with 6 or fewer qubits still show every state, including zero-probability ones. The results table below the histogram lists only measured states, so a zero-probability state can appear as an empty bar in the histogram while being omitted from the table.
## Bug Fixes
* Fixed an issue that prevented `classiq` from being imported in Jupyter notebooks.
## Interface Changes
* **`ExecutionSession.calculate_state_vector`** (and its non-blocking `submit_calculate_state_vector` counterpart) is a new primitive for statevector calculation. Use this instead of `sample` on the state vector simulator.
## Enhancements
* **QP Visualization:** Added visual label management.
* Adjacent variables that repeat across wires are now automatically suppressed to reduce clutter and save visual space in quantum program diagrams.
* Suppressed variable labels can still be viewed by hovering over the wire, which shows a tooltip with the hidden name(s).
* A right-click context menu on each variable wire lets you show or hide individual labels as needed.
## Interface Changes
* **`ExecutionSession.sample()`, `observe()`, and `variational_minimize()`:** Accept optional per-call `num_shots` and `run_via_classiq` keyword arguments that override the session defaults for that invocation only (including the matching `submit_*` methods).
## Enhancements
* The Python SDK now collects telemetry to help us improve our product. This can be disabled by setting the environment variable `CLASSIQ_TELEMETRY_MODE=disabled`.
## Bug Fixes
* Fixed incorrect gate arguments in `QuantumProgram.qasm`. This also affected simulation when `transpilation_option=TranspilationOption.NONE`.
## Bug Fixes
* Fixed an issue where the nvidia-gpu worker would fail during initialization.
## Interface Changes
* The **pretty\_qasm** field was removed from `Preferences`. OpenQASM 2 outputs are now always formatted with line breaks inside gate declarations (the previous default behavior).
* **`ExecutionSession`** now accepts individual configuration parameters directly: `ExecutionSession(qprog, backend=..., num_shots=..., random_seed=..., transpilation_option=..., run_via_classiq=..., config=...)`. The `execution_preferences=` keyword form still works but is deprecated and will be removed on 2026-06-22.
## Enhancements
* **QP Visualization:** Improved support for larger circuits and operations. Visualizations can now display much larger quantum programs, with the maximum number of child operations that can be expanded at once raised from 1,000 to 2,500, so large composite gates, functions, and generated code blocks expand and render fully.
## Enhancements
* **GitHub Copilot Integration:** Added support for GitHub Copilot in Classiq Studio, including chat-based AI assistance, coding agent features, and code autocomplete. These features are now available in the browser-based IDE experience.
## Bug Fixes
* **`CombinatorialProblem`:** Fixed a `KeyError` raised when an inequality constraint became degenerate (collapsed to a single feasible value) after another constraint had fixed one of its variables.
## Bug Fixes
* Restored the Studio button to its original location in the left sidebar of the IDE.
## Enhancements
* **Synthesis:** Faster synthesis for models containing very large [Hamiltonian](../qmod-reference/language-reference/classical-types#hamiltonians) objects.
* Added support for the C12 provider when using `sample`, `observe`, and related functions with `backend='c12/'`.
* Added support for large-scale models by uploading/downloading execution and synthesis inputs/outputs directly to S3 via pre-signed URLs, bypassing payload size limitations.
## Bug Fixes
* **`prepare_amplitudes` / `inplace_prepare_amplitudes`:** Fixed a wrong global phase that affected the controlled version for some amplitude vectors.
* **QP Visualization:** Improved robustness of the QP Visualization feature by adding webGPU/webGL context loss recovery, preventing blank screens when the graphics context is lost.
## Bug Fixes
* Fixed a bug in the infrastructure.
## Enhancements
* **Studio:** `latexmk` and a TeX Live subset are now pre-installed, enabling the benchmarking application from the Classiq library to generate its PDF report directly in the Studio.
## Bug Fixes
* Fixed an issue where most models saved with older SDK versions could not be synthesized.
## Enhancements
* **`ExecutionSession.sample` and `ExecutionSession.estimate`:** These methods now accept a list of parameter dictionaries for batch execution, returning a list of results. The dedicated `batch_sample`, `submit_batch_sample`, `batch_estimate`, and `submit_batch_estimate` methods are deprecated — pass a list to the standard methods instead.
* **`variational_minimize` function:** Added a new public `variational_minimize` function for variational optimization of a cost function over the parameter values of a quantum program. Supports Hamiltonian and classical cost functions, `run_via_classiq`, and improved input validation. See the [SDK reference](/sdk-reference/execution/) for details.
* Added `slice(array, start, stop)` in `classiq.qmod.symbolic` as the Python alternative for [array slice expressions](../qmod-reference/language-reference/expressions/#path-operators) on Python lists, analogous to `subscript`.
* **`classiq.print_diagnostics()`:** New function that prints a snapshot of the SDK version, Python environment, backend host and version, authentication status, and user ID - for easy inclusion in support tickets.
## Bug Fixes
* **Execution:** Sample jobs started with `execute()` now persist submitted-circuit metadata so `ExecutionJob.get_submitted_circuits()` matches the documented behavior.
* **Classiq Studio:** Fixed light mode not being saved in user preferences.
* **Classiq IDE:** Fixed the Synthesize button repeatedly appearing and disappearing.
* Fixed synthesis of nested concatenations in control condition.
## Interface Changes
* The `theta` parameter of function `phase` was renamed to `coefficient`.
The old name is deprecated and will no longer be supported starting on
2026-05-04 at the earliest.
* Function `randomized_benchmarking` is deprecated and will no longer be
supported starting on 2026-05-11 at the earliest.
## Enhancements
* **`sample` function:** Added a new top-level `sample` function for executing a quantum program and retrieving results as a DataFrame directly, without managing a job object. Supports single and batch execution — pass a list of parameter dictionaries to `parameters` to run multiple parameter sets and receive a list of DataFrames. Also supports `run_via_classiq=True` to run using Classiq's provider credentials against your allocated budget. See the [SDK reference](../sdk-reference/execution/) for details.
* **`observe` function:** Added a new public `observe` function that computes the expectation value of a Hermitian observable with respect to a quantum program's output state. Supports exact statevector calculation or shot-based estimation, batch execution, and `run_via_classiq`. See the [SDK reference](../sdk-reference/execution/) for details.
* **`get_backend_details` function:** Added a `get_backend_details` function that returns a DataFrame of all supported quantum backends, including provider, backend name, type (hardware or simulator), qubit count, availability, pending jobs, and queue time.
* **`calculate_state_vector` function:** Added a new public `calculate_state_vector` function that returns the full state vector of a quantum program as a DataFrame. Supports batch execution by passing a list of parameter dictionaries. Available on Classiq simulators (e.g. `classiq/simulator`).
* **`minimize` function:** Added a new public `minimize` function for variational optimization of a cost function over the parameter values of a quantum program. Supports Hamiltonian and classical cost functions, `run_via_classiq`, and improved input validation. See the [SDK reference](../sdk-reference/execution/) for details.
* **OpenQASM in `sample` and `ExecutionSession`:** You can pass **OpenQASM 2.0 or 3.0** source as a string to `sample()` (first argument) or to `ExecutionSession` instead of a synthesized `QuantumProgram`. Results use the same histogram DataFrame shape (`bitstring`, `counts`, etc.). The `parameters` argument is not supported for OpenQASM strings (use a `QuantumProgram` for Qmod `main` parameters, or bind parameters inside the QASM circuit). See the [Execution](../user-guide/execution/#sampling-openqasm) section of the user guide.
* Improved error messages related to qfunc arguments.
* Added `emulate` on `AzureBackendPreferences` to enable IonQ hardware noise simulation on Azure Quantum when using an IonQ QPU target (`ionq.qpu.*`); ignored for other Azure targets.
* Added a QSVM application with a `QSVM` class that provides `train`, `test`, and `predict` methods for easy implementation of Quantum Support Vector Machine training and data classification. The relevant notebooks in the classiq-library will be updated accordingly.
## Enhancements
* Upgraded infrastructure to enable future support in AWS Marketplace.
## Enhancements
* **Execution:** Added optional `emulate` on `IBMBackendPreferences` and `IBMConfig`. Set `emulate=True` (default `False`) to run on Classiq AerSimulator with an IBM noise model derived from the backend name (e.g. `ibm_pittsburgh`, `ibm_boston`). Only valid for real IBM hardware backends (not fake backends); backend name must be in `CLASSIQ_NOISE_MODELS`. See [IBM backends](../user-guide/execution/cloud-providers/ibm-backends) for details.
* Added `ExecutionJob.get_submitted_circuits()` to return the final quantum circuits submitted to the provider (sample jobs only). The returned circuits reflect the actual QASM after transpilation and parameter assignment. Each circuit can be converted to QASM via `to_qasm()` or to a Qiskit `QuantumCircuit` via `to_qiskit()`.
* **Amplitude threshold for state vector simulation:** Added `amplitude_threshold` to `ExecutionPreferences`. When running state vector simulation, only states with amplitude magnitude strictly greater than the threshold are included in the result. Defaults to `0` (filters exactly zero-amplitude states, same as before). Setting a higher threshold reduces the size of the result for circuits where most amplitudes are negligibly small. `include_zero_amplitude_outputs=True` overrides this and includes all states regardless of amplitude. See [State Vector Filtering](../user-guide/execution/state-vector-filtering) for details.
* **QP Visualization:** Fixed a bug in the visualization of split operations.
* Added `estimate_sample_cost` and `estimate_sample_batch_cost` to the Python SDK for user-facing cost estimation before executing quantum programs. These functions return a `CostEstimateResult` with `cost` and `currency` fields. See [SDK execution reference](../sdk-reference/execution) for details.
## Bug Fixes
* Fixed error messages when calling built-in operations with the wrong number of arguments.
## Enhancements
* **Predefined noise models for Classiq simulators:** Added optional `noise_model` on `ClassiqBackendPreferences` to run Classiq Aer, Nvidia, and Braket Nvidia simulators with a device-style noise model. The value is a predefined name in the form `_` (e.g. `ibm_pittsburgh`, `ibm_boston`). Supported names are listed in `CLASSIQ_NOISE_MODELS`; initially IBM backend names are supported. The noise model is built from the provider (e.g. via IBM Runtime) and passed to the underlying AerSimulator.
* **IonQ execution:** Replaced explicit `noise_model` with an `emulate` flag on `IonqBackendPreferences` and `IonQConfig`. Set `emulate=True` (default `False`) to run on the IonQ simulator with a noise model derived from the backend name (e.g. `qpu.aria-1` → `aria-1`). Only valid when the backend is a QPU. See [IonQ backends](../user-guide/execution/cloud-providers/ionq-backends#usage) for details.
* **QLayer check-pointing:** Improved save/load behavior for models containing a `QLayer`. Non-picklable `post_process` callables are now omitted when saving and can be restored via `layer.register_post_process()` after loading. Added `serializable_post_process=False` constructor option to suppress the related warning when `post_process` is intentionally non-picklable.
## Bug Fixes
* **Execution:** When execution runs with no transpilation (`transpilation_level = None`), the circuit is now submitted to the provider without any backend transpilation when it already uses only the provider’s basis gates. If the circuit contains gates not supported by the provider, an error is raised that lists the provider’s supported gates, the invalid gates in the program, and suggests using `transpilation_level = "decompose"` (or `transpile_to_hardware = "decompose"` in ExecutionPreferences).
* Re-enabled negative indices for classical arrays.
* Fixed the problem where users were not redirected to the login page when attempting to synthesize while logged out.
* **Classiq IDE:** Changed the exported CSV on the results page to match the displayed tables.
* **QLayer:** Fixed saving models that contain a `QLayer` when `post_process` or the execution path use local functions or lambdas (e.g. `torch.save(model, path)` or saving an epoch state dict). Such callables are now omitted from the pickled state and re-created or restored after load so that save/load no longer raises "Can't pickle local object".
* Added an indicative error message when calling a classical function with quantum arguments in an arithmetic expression.
## Enhancements
* Added `use_double_precision` to `ClassiqBackendPreferences` to control numerical precision on Nvidia and Braket Nvidia simulators. Default is `False` (single precision). Set `use_double_precision=True` for double precision. See [Classiq backends](/user-guide/execution/cloud-providers/classiq-backends/#nvidia-simulator-usage) for details.
## Bug Fixes
* Fixed an incorrect compilation when an arithmetic operation appears inside a `repeat` statement and the left-hand side uses the repeat index as a subscript.
## Interface Changes
* Changed default vendor from Azure to Classiq.
* Removed `max_depth` and `max_gate_count` from `Constraints`. These fields were deprecated since 0.52 and are no longer supported.
## Bug Fixes
* Fixed a bug causing an internal error during synthesis when calling a function containing `foreach` twice or more.
## Enhancements
* **Classiq Platform:** Updated the [platform home page](https://platform.classiq.io).
## Enhancements
* The function `poly_inversion` now supports `error_type` (`"relative"` default or `"uniform"`) to choose between minimizing relative error
|xp(x)-1| or absolute uniform error |p(x)-1/x| over x in \[1/kappa,1].
The same `error_type` option is also available in `poly_inversion_degree` and `poly_inversion_error`.
* Added the [*foreach*](../qmod-reference/language-reference/statements/classical-control-flow#classical-foreach) statement to Qmod. *Foreach* iterates efficiently through the elements of a classical array.
* Added support for `QBit`s in addition to `QNum`s in `lookup_table`.
## Interface Changes
* Renamed `sample` to `cmain_sample` in legacy `cscope`. This does not affect any usage of ExecutionSession.
## Enhancements
* Introduced [CUDA-Q Integration](/user-guide/execution/cudaq_integration), enabling translation of synthesized Qmod programs into Python CUDA-Q kernels, to leverage CUDA-Q’s high-performance simulation and hybrid quantum–classical workflows.
## Bug Fixes
* Fixed compilation of symbolic values in concatenations (for example, `[q[i], q[j]]` where `i` and `j` are of type `CInt`).
## Interface Changes
* Renamed parameter `run_through_classiq` of `BackendPreferences` to `run_via_classiq`. `run_through_classiq` is deprecated and will no longer be supported starting on 2026-03-09 at the earliest.
## Enhancements
* **Classiq IDE:**
* Adjusted the table shown in "State Vector" jobs.
* Added a table to "Measurement Results" jobs.
* Noise models are now available for IonQ simulators.
## Bug Fixes
* **Classiq IDE:** Fixed the phase legend not matching the actual phase.
* Fixed compilation of the `I` (identity) gate.
* Fixed evaluation of constants in `main` function parameter types.
## Interface Changes
* Removed previously deprecated `"count"` column from execution result dataframe. Use `"counts"` column instead.
## Enhancements
* Reduced CX count and circuit depth for multi-controlled Pauli rotations (RX, RY, RZ).
## Enhancements
* **Classiq IDE:**
* Improved the appearance of the histograms and bar plots shown for results.
* Improved native Qmod library usability.
* **Classiq Studio:** Added support for light mode visualization in the Quantum Program (QP) visualizer. Users can now switch between light and dark themes for an improved viewing experience.
* C12 Cloud support was added. See the [Cloud Providers](/user-guide/execution/cloud-providers/) section in the user guide.
## Bug Fixes
* Fixed error message for a measurement under unitary context.
## Enhancements
* Support array subscripts with missing slices (e.g., `arr[1:]` and `arr[:9]`) in Python Qmod.
* Add qmod\_to\_qubit\_op function to convert from SparsePauliOp to OpenFermion's QubitOp data structure.
## Bug Fixes
* IDE - Fix selection in Quantum Program Execution Jobs tab - Make the first job on the jobs list be selected
* Fix synthesis of functions with `Output` quantum parameters called under `invert`.
## Bug Fixes
* IDE - Fix expand / collapse of backend details in the HW Catalogue
* In the dataframe, change the `count` field to `counts` so as not to override the built-in `count` method on pandas dataframes.
The current `count` field is deprecated and will be removed in the next release.
* Fix multi-value Boolean operations in Native Qmod (e.g., `a or b or c`).
* Fix synthesis error when controlling `X` with >=13 control qubits.
* Raise indicative errors when overriding internal functions (for example, when re-defining `prepare_state`).
## Enhancements
* Support `QArray[QBit]` assignment statements, for example, `qarr |= [1, 0, 0, 1]`.
* Improve implementation of in-place quantum subscript assignments (e.g., `x ^= subscript([1, 2, 3, 4], y)`).
* IDE - Execution in the IDE now supports running through Classiq account for Amazon Braket, Microsoft Azure Quantum, and IonQ backends. Authorized users can enable this option using the "Run through Classiq" switch, which eliminates the need to provide their own credentials for these backends. This feature also includes spending tracking and budget management capabilities.
* Support assignments of non-scalar variables, for example, `qarr1 |= qarr2`.
Both variables must have the same type.
* Improve error message when assigning a symbolic value to a generative parameter.
## Deprecations
* IDE - Removed support for `max depth` and `max gate count` synthesis constraints in the model
## Interface Changes
* Violations of [uncomputation rules](/qmod-reference/language-reference/uncomputation) are now flagged as errors instead of warnings.
* The function `qubit_op_to_pauli_terms` in the `chemistry` module is
deprecated due to incorrect order of qubits in its result. Please use
`qubit_op_to_qmod` instead.
## Bug Fixes
* Resolved an issue with labeling CX gate inputs in QP visualization, so that the correct qubit labels are now displayed.
* Fixed `qfunc`s being expanded declaratively (symbolically) when passed as arguments to other `qfunc`s.
* Improved the error message for type errors with function arrays.
* Fixed error message for `nan` values.
* Fix mapping from output registers to measured qubits on parametrized repeat circuits with HW aware synthesis.
* Fix `phase` applied with an execution parameter under multiple controls.
* Fix `unscheduled_suzuki_trotter` and `qdrift` implementations.
* Fix SDK function get\_execution\_actions
* Flattened the cost field. The result holds now cost, currency\_code
* Add session\_id in the result
* Fix compilation of unused variables defined in nested blocks.
## Classiq Studio
* Classiq Studio now includes built-in AI integration, allowing users to generate, optimize, and execute quantum models directly within the Studio. This capability leverages Classiq's quantum resources and requires no external API tokens.
## Enhancements
* Add quantum modular arithmetic functions to the open library, enabling modular quantum operations:
modular addition, multiplication, squaring, negation, and inversion: `modular_add_inplace`,
`modular_double_inplace`, `modular_negate_inplace`, `modular_multiply`, `modular_square`,
`modular_multiply_constant`, `modular_multiply_constant_inplace`, `modular_to_montgomery_inplace`,
`modular_montgomery_to_standard_inplace`, `modular_inverse_inplace`, `kaliski_iteration`, and
`modular_rsub_inplace`.
* Add functions `get_execution_actions` and `get_execution_actions_async` return a pandas DataFrame of execution actions. Filter by id, session\_id, status, name, provider, backend, program\_id, cost range (total\_cost\_min/max), and time ranges (start\_time\_min/max, end\_time\_min/max). All filters are combined with AND logic.
* Add functions `get_synthesis_actions` and `get_synthesis_actions_async` return a pandas DataFrame of synthesis actions. Filter by id, status, backend, program\_id, backend\_name, optimization\_parameter, random\_seed, max\_width, max\_gate\_count, cost range (total\_cost\_min/max), and time ranges (start\_time\_min/max, end\_time\_min/max). All filters are combined with AND logic.
## Bug Fixes
* Fix uncomputation of function calls with input or output concatenations.
* Fix within-apply bug caused by variable declarations nested in the "within"
block.
## Bug Fixes
* Fix memory issue in Synthesis queue mechanism.
## Enhancements
* Add functions for encoding conversions between binary, unary, and one-hot representations:
`binary_to_one_hot`, `binary_to_unary`, `one_hot_to_unary`,
`one_hot_to_binary`, `unary_to_one_hot`, `unary_to_binary`,
`inplace_binary_to_one_hot`, and `inplace_one_hot_to_unary`.
* Change precision of GPU simulators to single-precision to make better use of hardware.
## Bug Fixes
* Fixed a bug in Hardware-Aware Quantum Program.
* Fixed [concatenations](/qmod-reference/language-reference/quantum-variables/#concatenation-operator)
arguments to input and output quantum parameters.
## Classiq IDE
* Fixed a bug in Jobs page after Executing on several hardwares.
* Added a better labeling in the QP visualization. Now on "Show label" user will see label as on the closed box. On hover user will see full label.
* Fixed issue with duplicate error snackbar in the Jobs page.
## Interface Changes
* Function `exponentiation_with_depth_constraint` is deprecated and will no
longer be supported starting on 2025-12-10 at the earliest.
Instead, use `exponentiate`.
## Enhancements
* Add SX gate to Qmod core functions
## Classiq IDE
* Basis Gates field under “Hardware Aware” now starts empty. If left empty, synthesis applies default basis gates automatically based on connectivity; select one or more gates to override.
## Interface Changes
* Update the QSVT functions to use [Capturing](/qmod-reference/language-reference/operators/?h=captur#capturing-context-variables-and-parameters).
See the following [example](/qmod-reference/library-reference/open-library-functions/qsvt/qsvt/).
## Enhancements
* Add functions for getting polynomial approximations for common use cases - `poly_jacobi_anger_<>` for
Hamiltonian Simulation and `poly_inversion` for matrix inversion.
## Bug Fixes
* Fix an issue that caused certain execution runs to fail due to incompatible gates
## Bug Fixes
* Fixed minor issues in registration flow
## Enhancements
* Qmod now supports **automatic uncomputation** of local variables and enforces
rules that guarantee their correct uncomputation. Similar rules are enforced
on variables initialized inside a *within-apply* statement.
For more details, see [Uncomputation](../qmod-reference/language-reference/uncomputation).
Currently, violations of uncomputation rules are issued as warnings for backward compatibility.
These will become compilation errors no earlier than 2025-12-03.
* Add the `assign_amplitude_table` and `assign_amplitude_poly_sin`
open-library functions, to replace the `*=` operator and the
`assign_amplitude` function.
* Add [`unscheduled_suzuki_trotter`](../sdk-reference/qmod/functions/core_library/exponentiation/#classiq.qmod.builtins.functions.exponentiation.unscheduled_suzuki_trotter),
a variant of `multi_suzuki_trotter` that doesn't re-order the Pauli terms.
* Improve synthesis of controlled phase with theta=pi.
* This release includes initial support of classical local variables,
assignment of mid-circuit measurements, and runtime if statements.
Currently, only variables of type QBit can be measured, and only the
classical bool type is supported for local variable declaration and
assignment. This enables simple algorithms such as the quantum teleportation
protocol. These constructs have the corresponding dedicated graphics in the
quantum program visualization. See more details under [Classical variables](/qmod-reference/language-reference/classical-variables))
and [Mid-circuit measurement](../qmod-reference/language-reference/mid-circuit-measurement).
## Interface Changes
* The `*=` operator and the `assign_amplitude` function are deprecated and
will no longer be supported starting on 2025-12-03 at the earliest. Use
`assign_amplitude_table` instead.
* Function `qdrift` now receives a sparse Hamiltonian ([`SparsePauliOp`](../sdk-reference/qmod/classical-types/#classiq.qmod.builtins.structs.SparsePauliOp))
instead of a list of non-sparse Pauli terms (`CArray[PauliTerm]`).
Non-sparse pauli terms in `qdrift` will no longer be supported starting on
2025-12-03 at the earliest.
## Bug Fixes
* Fix `multi_suzuki_trotter` synthesis with symbolic evolution coefficients
raising an internal error.
* Fix a bug where an internal error is raised when synthesizing with a maximum width constraint
a model that contains control on a function, or a statement block, that allocates and frees qubits.
## Security
* Internal dependencies have been upgraded to address security vulnerabilities.
## Bug Fixes
* Fix transpilation and execution of `unitary` functions when compiling to
QASM2.
## Enhancements
* We've changed our AWS Braket integration, now AWS credentials consist of an access key ID and a secret access key. For more information, see [AWS Credentials](https://aws.amazon.com/blogs/quantum-computing/setting-up-your-local-development-environment-in-amazon-braket/).
* Added the function `prepare_select` for the definition of structured Linear Combination of Unitaries primitive (LCU) schemes.
## Bug Fixes
* Report assignments into non-numeric variables.
* Fix concatenation operator on single variable not casting to QArray.
* Fix lambda list (`QCallableList`) scoping issue causing a bug when a lambda
list item is invoked in a different lambda.
* Fix error which caused execution jobs on IonQ to fail if they took more than 5 minutes.
## Interface Changes
* The **debug\_info** field was removed from the QuantumProgram class
## Bug Fixes
* Report quantum types instantiated with execution parameters.
## Deprecations
1. Python 3.9 is no longer supported in the Python SDK. The minimum supported
version is now Python 3.10.
## Enhancements
* Added the [`skip_control` statement](/qmod-reference/language-reference/statements/skip-control/)
to the Qmod language. `skip_control` applies a quantum statements
unconditionally.
* Add `pauli_operator_to_matrix`, the sparse counterpart of `hamiltonian_to_matrix`.
* Add new quantum functions for modular arithmetics: `modular_add_qft_space`, `modular_multiply`,
and `inplace_modular_multiply`.
Those functions use `skip_control` statements for specifying their efficient controlled version.
## Bug Fixes
* Fix a bug where an error is raised when synthesizing with a maximum width constraint, even though a solution exists.
* Fix `qasm_to_qmod` quantum argument size calculations (resulting in, for
instance, illegal `control` statements generated from `mcx` gates).
## Deprecations
* SDK versions below 0.92 will be deprecated as planned from October 13, 2025 (at the earliest). As a one-time exception, the version deprecation error message will not be as usual. Instead of “You are using an unsupported version of Classiq SDK—... “, users will experience a “504 Gateway Timeout ERROR” or a similar message. We apologize for the inconvenience.
## Bug Fixes
* Fix a bug where an internal error occurred during hardware-aware synthesis with a basis gate set of Clifford + T.
* Fix `allocate` with floating-point size when the `max_width` constraint is
set.
## Classiq Studio
* A progress bar was added to the classiq studio start up page.
## Deprecations
* Python version 3.9 will no longer be supported starting on 2025-10-01 at the
earliest.
## Enhancements
* The new [`qasm_to_qmod` function](/sdk-reference/synthesis#qasm_to_qmod)
de-compiles QASM 2 or 3 into Python/Native Qmod source code.
* Added methods for [execution budget management](/user-guide/execution/budget-management).
* Classiq's AI agent is now installed in Classiq Studio, providing seamless AI-powered quantum development. See the [AI documentation](/user-guide/ai/index) for setup instructions.
* Remove negligibly small amplitudes from state vectors when the auxiliary
(non-output) qubits are non-zero. These amplitudes are caused by numeric
error during simulation, but they result in multiple states with
the same assignment for the variables, which caused confusion.
* Added several Quantum Signal Processing [(QSP)](/sdk-reference/applications/QSP) related functions to the SDK:
`qsvt_phases` for obtaining QSVT phases,
`qsp_approximate` for approximating QSP-compatible Chebyshev polynomials,
`gqsp_phases` for calculating Generalized-QSP (GQSP) phases,
and a quantum `gqsp` function that implements GQSP.
To use these functions the user should `pip install classiq[qsp]`.
The existing QSVT examples and a new GQSP example will be updated in the library
towards the next version release.
## Bug Fixes
* Fix a bug where the visualization generated unnecessary variable splits
and assigned incorrect variable names in certain cases.
* Support classical functions in the cost expression of `minimize`.
* Prevent invisible blocks from being collapsed.
* Adjust CZ gate boundaries to align with disconnected variable lines.
* Fix Studio loading stuck until page reload.
## Bug Fixes
* **Visualization tooltips are now supported and displayed in the Studio.** This enhancement improves the user experience by providing helpful information directly within visualizations, making it easier to understand and interact with your data.
## Enhancements
* Add magnitude and phase to the dataframe for state vector simulations.
* Increase the limit of the number of qubits that can be simulated on Classiq's Simulator from 25 to 28.
Note that wider circuits take longer to simulate, so Classiq's Nvidia Simulator will likely have improved performance
for wide/deep circuits.
Also, increase the limit on Classiq's State Vector Simulator to 28 qubits, as long as
[State Vector Filtering](/user-guide/execution/state-vector-filtering/) reduces the number
of output (unfiltered) qubits to 18 or less, the previous limit. For example, it is now possible
to get the state vector from a quantum program of 20 qubits with a 2-qubit QNum filtered out.
* Add support for bitwise operators in [phase statements](/qmod-reference/language-reference/statements/phase/#semantics).
### Documentation Enhancements
* A new tutorial on execution is now available under [The Classiq Tutorial](/getting-started/classiq_tutorial/)
* New explanations on visualization features in the [Synthesis Tutorial](/explore/tutorials/basic_tutorials/the_classiq_tutorial/synthesis_tutorial/)
* Search results have been improved to show the most relevant information at the top.
## Enhancements
* Loading of large Pandas Dataframes is now available in the studio, up to 200MB files.
* Use non-blocking flow for execution jobs on the Classiq Nvidia Simulator. This allows for longer-running jobs.
* The 'phase' statement has been generalized to support a fixed (classically
specified) rotation angle, that is, to insert a global phase. A global
phase across an entire circuit is undetectable in quantum hardware, but when
applied in a controlled context, it introduces a relative phase between
positive and negative condition states. This variant of the 'phase'
statement is useful to directly express key idioms in quantum algorithms
such as phase oracles, reflections, and relative-phase computations.
### QP Visualization: Improved Handling of Long Function Blocks Sub-labels
Long sub-labels in the quantum program visualizer are now automatically
truncated to prevent overflow and maintain a clean layout.
When a sub-label is truncated, the full text is accessible via a tooltip on
hover, ensuring that all information remains available without cluttering the
interface.
This enhancement improves readability and usability, especially for circuits
with verbose or complex expressions.
## Deprecations
* The following functions and classes have been deprecated and will no longer
be supported starting on 2025-09-18 at the earliest:
`construct_chemistry_model`, `molecule_ucc`, `molecule_hva`,
`molecule_hartree_fock`, `fock_hamiltonian_hva`,
`fock_hamiltonian_hartree_fock`, `GroundStateProblem`, `MoleculeProblem` and
`HamiltonianProblem`. For more information on Classiq's chemistry
application, see [here](/explore/applications/chemistry/classiq_chemistry_application/classiq_chemistry_application).
## Bug Fixes
* Fix a bug where allocating quantum variables in disallowed blocks was
not always reported.
* Fix a bug where controlled free operations could cause the visualization to crash. The visualization now handles these cases correctly and no longer fails when such operations are present.
## Interface Changes
* Parameter `expr` of function 'phase' has been renamed to `phase_expr`.
Parameter `expr` will no longer be supported starting on 2025-09-19 at the
earliest. Change `phase(expr=..., theta=...)` to
`phase(phase_expr=..., theta=...)` or `phase(..., ...)`.
## Classiq Studio
* You can now install and import Torch, PyQSP, and CUDA-Q packages in the Classiq Studio environment. Previously, these imports failed due to environment limitations, but they are now supported for your workflows.
* PyGLPK package is installed and usable in the Classiq Studio.
* Uploading files up to 1 GB to the user persistent workspace in the Classiq Studio is now enabled.
## Enhancements
* Added the functions `prepare_sparse_amplitudes` and `inplace_prepare_sparse_amplitudes` to the function library.
* Add support for numpy 2.2.6 (Python >=3.10) and numpy 2.3.2 (Python >=3.11)
* Shared QP links now come with the actual visualization image previews.
## Security
* Improved web application security
## Enhancements
* Added the function `prepare_linear_amplitudes` for preparing the state $|\psi\rangle = \frac\{1\}\{Z\}\sum_\{x=0\}^\{2^n-1\}\{x|x\rangle\}$.
* Extended the visualization of controlled functions as transparent boxes
displaying control lines to all Qmod statements.
* Support [state vector filtering](/user-guide/execution/state-vector-filtering) for Classiq's `simulator_statevector`.
* Added tolerance parameter to the minimize method of the execution session.
## Enhancements
* Added the functions `lcu` and `lcu_pauli` for creating the Linear Combination of Unitaries primitive (LCU).
* IBM Cloud is now available. See [Cloud Providers](/user-guide/execution/cloud-providers/) section in the user guide.
* The default optimization level in the synthesis preferences has been changed from `OptimizationLevel.HIGH` (3)
to `OptimizationLevel.LIGHT` (1). For more information about optimization level
see the [optimization level](/user-guide/synthesis/preferences/#optimization-level) section in the user guide.
### Introducing “Variables View”
A new compact visualization mode that displays quantum variable flow at a higher level perspective. Toggle between this streamlined view and the traditional qubit grid overlay using the Variables View switch in the visualization menu bar.”
## Classiq Studio
### Memory monitor
A new memory monitoring feature that tracks and displays resource usage during Classiq Studio Usage, providing real-time insights into memory consumption patterns.
## Bug Fixes
* Fix a synthesis bug that causes, in some cases, the function under power to have
a separate power for each function, instead of sharing it as a whole.
* Fix a failure in hardware-aware synthesis of parametric models for the
`Azure Quantum` provider.
* Fix a bug in `get_hf_state` when using qubit tapering.
## Enhancements
* [Concatenations](/qmod-reference/language-reference/quantum-variables/#concatenation-operator)
can now also be used as [control](/qmod-reference/language-reference/statements/control/)
expressions.
* Lower model creation and synthesis run times for large models.
## Bug Fixes
* Classical `if` statements are now supported in QP visualization, where they previously caused a failure.
* Fix synthesis bug which caused wrong results when using the bitwise invert (`~`) operator.
* Fix bug relating to classical struct arguments (such as
[Hamiltonians](/qmod-reference/language-reference/classical-types/#hamiltonians)).
* Use the Solovay-Kitaev algorithm in more cases when transpiling. Previously, we used the algorithm when transpiling with
respect to a particular fixed set of basis gates. Now, we use this algorithm whenever the basis gate set contains the Clifford gates
`X`, `Z`, `H`, `T`, and `CX` but does not contain arbitrary-angle rotation gates such as `RX` or `CRZ`.
## Classiq IDE
1. Add mechanism to allow more models to be visualized in new visualization.
2. ### Visualization: Data Tab Removal
The Data tab has been removed from the left panel in the visualization interface. This change is removing redundant functionality.
3. ### Deprecation: QP Visualization Basic View Mode
Deprecated "Basic" mode quantum program visualization in favor of the new visualization scheme with enhanced designs, views, and analysis capabilities.
4. ### Visualization: Focused Search
The search panel focuses only on user written functions and QMOD statements.
## Bug Fixes
* Fix the value range analysis of numerical variables declared with specified size.
## Deprecations
* The Qmod function `allocate_num` has been removed.
## Classiq IDE
### New Feature: QP Visualization Enhancements
The Classiq IDE now includes an improved QP visualization feature. Controlled functions are displayed in transparent boxes blocks, where:
* The transparent section represents the control mechanism.
* The filled block highlights the controlled function.
This enhancement provides a clearer and more intuitive representation of quantum programs, making it easier to understand and debug complex circuits.
## Enhancements
* Added new [chemistry functions](/sdk-reference/applications/chemistry) to
the Python SDK for using Hartree-Fock and UCC ansatz in Qmod. In order to
use them, it is required to install the Python SDK with the extra
`chemistry` dependency.
* Qmod functions are represented with a single symbolic definition throughout
the compilation process when their use of classical parameters allows it.
This improves compilation time and output QASM code size in many cases.
* Added a new function, [`multi_suzuki_trotter`](http://../sdk-reference/qmod/functions/core_library/exponentiation/#classiq.qmod.builtins.functions.exponentiation.multi_suzuki_trotter),
that applies the Suzuki-Trotter decomposition jointly to a sum of Hamiltonians.
* Added a new syntax for specifying sparse Hamiltonians ([`SparsePauliOp`](http://../sdk-reference/qmod/classical-types/#classiq.qmod.builtins.structs.SparsePauliOp))
in Qmod's Python embedding. For example: `0.5 * Pauli.Z(0) * Pauli.Y(1) * Pauli.X(2) + 0.8 * Pauli.X(1)`.
Check out the [documentation](http:///qmod-reference/language-reference/classical-types/#hamiltonians)
for more details.
* Added a `dataframe` property to ExecutionDetails object. Example usage:
```
with ExecutionSession(qprog) as es:
result = es.sample()
df = result.dataframe
```
* Added a new execution primitive [`ExecutionSession.minimize`](/sdk-reference/execution#classiq.execution.ExecutionSession.minimize)
that encapsulates classical optimization of ansatz parameters.
The cost function to minimize is specified either as a quantum observable (Hamiltonian) or an arithmetic expression.
This offers a significant performance advantage compared to executing the same logic on the client side, as it eliminates
communication overhead. Note that it utilizes a fixed generic minimization scheme (`scipy-COBYLA`).
In non-trivial cases, you may still need to implement your own optimization logic.
* The total size of quantum structs can be retrieved using the new
of `QStruct`.
## Interface Changes
* Function `sparse_suzuki_trotter` will no longer be supported starting on
21/7/25 at the earliest. Instead, use `suzuki_trotter`.
* Function `parametric_suzuki_trotter` will no longer be supported starting on
21/7/25 at the earliest. Instead, use `multi_suzuki_trotter`.
* Function `suzuki_trotter` now receives a sparse Hamiltonian ([`SparsePauliOp`](http://../sdk-reference/qmod/classical-types/#classiq.qmod.builtins.structs.SparsePauliOp))
instead of a list of non-sparse Pauli terms (`CArray[PauliTerm]`).
Non-sparse pauli terms in `suzuki_trotter` are deprecated, use
`SparsePauliOp` instead.
* [`ExecutionSession`](http:///sdk-reference/execution/#classiq.execution.ExecutionSession)'s
`estimate` methods now accept a sparse Hamiltonian ([`SparsePauliOp`](http://../sdk-reference/qmod/classical-types/#classiq.qmod.builtins.structs.SparsePauliOp))
instead of a list of non-sparse Pauli terms (`CArray[PauliTerm]`).
Non-sparse pauli terms in `ExecutionSession` will no longer be supported
starting on 21/7/25 at the earliest. Use `SparsePauliOp` instead.
## Enhancements
* Added the concatenation operator to Qmod. This operator packs a sequence of
quantum variables (or their parts) into a qubit array. For example,
`hadamard_transform([my_qnum, my_qarray[1:3]])` passes an array of the
respective qubits to the function. See more under
[concatenation operator](/qmod-reference/language-reference/quantum-variables/#concatenation-operator).
* Width constraints are now treated more systematically for optimization
levels 0-2 (partitioning the model into separate synthesis steps), yielding
solutions in cases where previously no solution was found. See more under
[Optimization Level](/user-guide/synthesis/preferences#optimization-level).
## Interface Changes
* The type `SerailizedQuantumProgram` and method `QuantumProgram.get_qprog` are no longer available.
## Bug Fixes
* Removed the "Login required" error message when not authenticated
## Enhancements
* In Quantum Program visualization, engine-level (grey) boxes are flattened when they are single children.
## Deprecations
1. The Qmod function `allocate_num` is deprecated and will no longer be
supported starting on 16/06/2025 at the earliest. Instead, use
which supports the same parameters.
## Security
* Updated dependencies to fix security vulnerabilities.
## Enhancements
1. Quantum functions inside a control statement get a `c-` prefix
2. Added the functions `prepare_dicke_state` and `prepare_dicke_state_unary_input`.
3. A new exponentiation function, [sparse\_suzuki\_trotter](../sdk-reference/qmod/functions/core_library/exponentiation#classiq.qmod.builtins.functions.exponentiation.sparse_suzuki_trotter),
has been added to the core library, performing Suzuki-Trotter decomposition using a sparse representation
of the Hamiltonian. It is recommended to use this function instead of `suzuki_trotter` when you handle a sparse Hamiltonian, as it is more efficient.
4. Include `classiq.execution` in the top level `classiq` package in the SDK.
Old:
```
from classiq.execution import ExecutionPreferences
```
New:
```
from classiq import ExecutionPreferences
```
5. [`allocate`](../sdk-reference/qmod/operations#classiq.qmod.builtins.operations.allocate) now
supports specifying numeric attributes of the allocated variable.
## Bug Fixes
1. Fix a system bug that caused execution jobs to fail with an "insufficient
resources" message.
2. Fix a bug related to execution parameters.
## Enhancements
1. Value range analysis of arithmetic expressions is now generalized to apply
across statements, optimizing quantum variables sizes and arithmetic expressions
implementation in more cases.
## Enhancements
1. A new `IQAE` application has been added to the SDK. It allows you to define `iqae` problems in terms of Qmod function,
and directly estimate the amplitude of the state you prepared.
It is recommended to use this application in `iqae` problems, rather than `cmain`
with the primitive `iqae`.
## Bug Fixes
1. Fixed an issue where the “Basic” view was always empty; it now correctly renders the circuit as intended.
2. Fixed bugs causing several example models to not be supported in the "New" circuit visualization, including "Shor's Algorithm Modular Exponentiation".
## Enhancements
1. In Qmod's Python embedding, you can now declare quantum functions with classical parameters
of Python builtin types such as `int`, `float`, and `list`. These variables can be
used in expressions that require Python values, such as Python `for` loops and 3rd party
library functions, as is shown in the example below. See more on this under the new
reference page on
[comment]: DO_NOT_TEST
```python theme={null}
@qfunc
def rotate(ratio: float, qa: QArray[QBit]):
for i in range(qa.len): # 'qa.len' is a Python integer
PHASE(math.asin(ratio * i), qa[i]) # 'ratio * i' evaluates to a Python float
```
## Interface Changes
1. With *Enhancement 1* described above, Python-type parameters supersede classical Qmod-type parameters
in generative functions. Hence, the use of the function decorator `@qfunc(generative=True)`
is no longer required. Qmod-type parameters are treated symbolically in Python, and their
use in Python expressions is deprecated.
## Classiq IDE
1. Improved UX in Quantum program visualization: collapsing a Quantum operation block will scroll the viewport into the parent operation block position
## Enhancements
1. It is now legal to [out-of-place assign](/qmod-reference/language-reference/statements/assignment#out-of-place-assignment)
to a variable whose declared size is larger than the minimal size required to
fit the range of possible expression values.
## Interface Changes
1. The function `synthesize` now returns an object of type `QuantumProgram`, and its fields can be accessed directly.
The type `SerailizedQuantumProgram` and method `QuantumProgram.get_qprog` are no longer needed, they are deprecated and will be removed in a future version.
2. Email Service Update - We've replaced the Community button with a new
dropdown menu.
Users can now select "Contact Us", which opens a form.
Once the form is submitted with user details, an email is sent directly to Classiq.
3. Layout Fixes - Resolved an issue with inconsistent padding across the layout to ensure a cleaner, more polished UI.
4. Enhanced Sharing Options - In addition to existing platforms, users can now share content to LinkedIn and Reddit with a single click.
## Classiq Studio
Added a new command `reset-user-env` to reset the virtual environment to its default state
helping resolve dependency issues and clean up installations.
## Classiq IDE
Added a "User Terms" button inside the IDE website at the bottom of the screen, and clicking on it opens a modal displaying our user terms.
## Enhancements
When estimating using the `ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR` backend,
whether using the `ExecutionSession` or classical main, compute the expectation
value directly from the state vector instead of running shots.
## Enhancements
* `QuantumProgram` objects have been optimized to be significantly leaner, improving performance across all actions that handle them.
* Visualizing Quantum Programs is now significantly faster.
* Added the functions `prepare_complex_amplitudes` and `inplace_prepare_complex_amplitudes`.
### Quantum Program Visualization
* Auto-expand QMOD statements without expressions (e.g. `power`).
* Statements with quantum expressions now display their corresponding expression directly on the block.
## Interface Changes
1. The functions `construct_qsvm_model`, `construct_finance_model`, and
`construct_grover_model` have been removed from the SDK.
Check out our Qmod implementations of the QSVM, finance, and Grover
algorithms in the [Classiq library](https://github.com/Classiq/classiq-library).
## Enhancements
1. Improve `control` statement visualization to distinguish control qubits from target qubits.
## Enhancements
1. Add new execution backends `BRAKET_NVIDIA_SIMULATOR` and `BRAKET_NVIDIA_SIMULATOR_STATEVECTOR`. These simulators run on Amazon Braket's infrastructure and provide faster execution for single circuits. See [Execution on Classiq Backends](/user-guide/execution/cloud-providers/classiq-backends) for more information.
2. Improve `prepare_amplitudes` and `prepare_state` performance for `bound=0`.
3. Add [`RESET`](../sdk-reference/qmod/functions/core_library/mid_circuit_measurement/#classiq.qmod.builtins.functions.mid_circuit_measurement.RESET), an atomic function that resets a qubit to the `|0>` state.
4. Intel simulator is now available as a backend for execution. See [Cloud Providers](/user-guide/execution/cloud-providers/) section in the user guide.
## Classiq IDE
1. Models page is now open to non-signed-up users.
## Classiq Studio
1. Trust Classiq Library workspace by default.
## Enhancements
1. Improve depth and gate count for transpilation options "intensive" and
"custom".
2. Improve the synthesis of the `suzuki_trotter` function for small Hamiltonians.
3. Updated the Quantum program icon in the drawer to a newer version.
## Bug Fixes
1. Fixed a bug where arithmetic expressions that classically evaluate to constant boolean values could not be used.
2. Fixed a bug where using the `show` function in the Python SDK would open the IDE with a "Not Authorized" error.
3. Fixed a bug where certain operations in the Quantum Program visualization are displayed with very long name that describes the operation's hierarchy.
## Classiq Studio
### **We’re launching Classiq Studio!**
Classiq Studio is a web-based coding environment where you can write and run Python code in a pre-configured setup. Access it now via the [Classiq Platform](https://platform.classiq.io).
For details, see the [Classiq Studio user guide](/user-guide/studio/index).
## Enhancements
1. Improved the synthesis of the `molecule_ucc` function for small molecules.
2. Social Sharing is now available. You can share circuits to various social platforms.
3. Added SLSQP optimizer for use in [VQE](/user-guide/execution/).
## Interface Changes
1. Introduced a new QMOD core-library function [`commuting_paulis_exponent`](../sdk-reference/qmod/functions/core_library/exponentiation#classiq.qmod.builtins.functions.exponentiation.commuting_paulis_exponent).
## Bug Fixes
1. Fixed unexpected resets when using Classiq Studio.
## Support
1. Error messages now include a link to our [support system](https://classiq-community.freshdesk.com/support/tickets/new) for reporting bugs or opening support tickets. You can also reach us on our [Slack community channel](https://short.classiq.io/join-slack).
## Enhancements
1. Arithmetic assignments and control conditions now support [quantum subscript
expressions](/qmod-reference/language-reference/expressions/#path-operators).
A quantum subscript expression comprises a classical list accessed by a quantum
subscript, e.g., `x |= subscript([1, 2, 3, 4], y)`
(in Native Qmod: `x = [1, 2, 3, 4][y];`).
2. Report an indicative error when not releasing local variables inside
[control](/qmod-reference/language-reference/statements/control),
[invert](/qmod-reference/language-reference/statements/invert) and
[power](/qmod-reference/language-reference/statements/power) statements.
3. When running VQE using the `ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR` backend,
compute the expectation value directly from the state vector instead of running shots.
4. In the Python SDK, arguments of type `CArray` can now be NumPy arrays, tuples, and
similar sequential objects. For example, the following statements are
equivalent:
`prepare_state([0.25, 0.25, 0.25, 0.25], 0, q)` and
`prepare_state(np.ones(4) / 4, 0, q)`.
## Interface Changes
1. The `synthesize` and `write_qmod` functions now accept a
[quantum entry point](/qmod-reference/language-reference/quantum-entry-point/?h=quantum+entry+point#model-outputs).
Instead of `synthesize(create_model(main))`, write `synthesize(main)`.
## Enhancements
1. Unreleased local variables of a function are now un-computed
and released when calling the function under a *compute* block of a
statement.
## Bug Fixes
1. Fix control optimization for constant equality conditions
(e.g., `control(x == 1, ...)`) producing wrong circuits under certain
conditions.
2. Fix in-place XOR optimization for classical values (e.g., `x ^= -0.5`)
producing wrong circuits under certain conditions.
3. Fix in-place XOR optimization for Boolean expressions
(e.g., `x ^= (y > 0) & (z > 0)`) producing wrong circuits under certain
conditions.
4. Fix a bug causing an internal error in arithmetic expression that use comparison,
subtraction, or negation (e.g. `x > 0.3`, `0.2 - x`, `-x`) when synthesizing
models with the machine precision set to higher than 8.
## Interface Changes
1. Add the functions `amplitude_amplification` and `exact_amplitude_amplification` to the function library.
## Enhancements
1. The `num_qubits` argument of function `allocate` is now optional. If it is
not specified, it is inferred automatically according to the quantum type
of the allocated variable. Example:
[comment]: DO_NOT_TEST
```python theme={null}
q = QBit()
allocate(q) # allocates one qubit for variable 'q'
```
2. The `execute` parameter of the `QLayer` object is now optional. Example:
[comment]: DO_NOT_TEST
```python theme={null}
QLayer(quantum_program, post_process)
```
## Deprecations
The simulator name "nvidia\_state\_vector\_simulator" has been removed. Please use
ClassiqNvidiaBackendNames.SIMULATOR or "nvidia\_simulator" instead.
## Classiq IDE
1. The Application Configuration Panel used for editing examples in the Built-in Apps folder has been removed.
2. Patched dependencies: Katex.
## Enhancements
1. Increase jobs memory.
## Bug Fixes
1. Fix failed execution jobs which stay in "running" status forever instead of
reporting an indicative error.
## Enhancements
1. Improve overall stability and performance.
## Enhancements
1. The name argument of local [quantum variables](/qmod-reference/language-reference/quantum-variables/)
is now optional. If a name is not specified, it is inferred automatically from
the Python code. For example, it is now possible to write `q = QBit()`
instead of `q = QBit("q")`.
2. Improve the performance of executing multiple primitives inside one
`ExecutionSession`, such as in `execute_qaoa`.
## Classiq IDE
Share Quantum Programs with anyone.
For more information, see [Sharing your Quantum Program Visualization](/user-guide/analysis/visualization-of-quantum-programs#sharing-your-quantum-program-visualization).
## Deprecations
Function `prepare_int` and `inplace_prepare_int` are now deprecated. Use Qmod out-of-place
and in-place numeric assignment statements instead. For example, instead of `prepare_int(5, my_qnum)`,
write `my_qnum |= 5`.
See more under [numeric assignments](/qmod-reference/language-reference/statements/assignment/).
## Enhancements
1. Improve error messages.
## Bug Fixes
1. Fix quantum bits raising an error when used in in-place assignments
(`^=` and `+=`).
2. Fix quantum struct field access raising an error in lambdas.
## Classiq IDE
1. Classiq Thumbnail: Updated the Classiq thumbnail image!
2. Links on the IDE model page now directing to Classiq Library.
3. Modify the Quantum Programs URL so that the circuit ID is embedded in its path
### New Visualization:
Compact View:
* Clean up variable names in engine blocks.
* Corrected the spacing miscalculation for junction dots.
* Refined padding before allocation
* Hide labels in open functional blocks to create a more space-efficient
display.
* Removed unnecessary dots and labels for low-level QC elements.
## Enhancements
1. [Generative functions](/qmod-reference/language-reference/generative-descriptions)
have undergone a round of significant improvements.
Check out our [DQI notebook](/explore/algorithms/search_and_optimization/dqi/dqi_max_xorsat/)
to see how generative functions are used to implement advanced quantum algorithms.
2. A new filed `optimization_level` has been added the `Preferences` of the synthesis.
This field determines the trade-off between synthesis speed and the quality of the results,
In terms of the optimization parameter and the constraints. For more information,
see [here](/user-guide/synthesis/preferences#optimization-level).
3. State vector filtering is available. This is an important step for simulating
large circuits with a state vector simulator. For more information, see [this page](/user-guide/execution/state-vector-filtering)
## Bug Fixes
1. Fix usage of overlapping quantum array slices (e.g., `qbv[1:3]` and `qbv[2]`)
in bodies of lambda expressions and control statements.
## Enhancements
1. Added a new simulator under the Classiq provider, under the name `ClassiqNvidiaBackendNames.SIMULATOR_STATEVECTOR`.
This simulator runs on a GPU and returns a state vector, similar to
`ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR` (which runs on a CPU).
Thus, it can handle larger circuits. The name `"nvidia_state_vector_simulator"`
is deprecated in favor of `ClassiqNvidiaBackendNames.SIMULATOR`. See [here](/user-guide/execution/cloud-providers/classiq-backends#nvidia-simulator-usage) for more information.
## Bug Fixes
1. Fix the connectivity map of the `rigetti.qpu.ankaa-9q-3` backend in Azure Quantum.
2. Fix the connectivity map of Amazon Braket devices.
3. Fix a bug in the method `from_id` of `ExecutionJob`.
## Deprecations
1. Parameters `value` and `target` of functions `inplace_add` and `inplace_xor`
have been renamed to `expression` and `target_var` respectively.
* In Native Qmod, use `+=` and `^=` instead of `inplace_add` and `inplace_xor`
respectively.
## Classiq IDE
1. Qmod examples on the Model page now contain direct links to their respective tutorials in the Classiq documentation. Simply hover over an algorithm list item from the QMODs list in the left panel and a tooltip will appear with link to the relevant tutorial.
### New Visualization:
1. Captured variables are now shown as uninitialized.
## Enhancements
1. Add a demonstration of the Decoded Quantum Interferometry (DQI) algorithm. See [notebook](/explore/algorithms/search_and_optimization/dqi/dqi_max_xorsat/).
## Bug Fixes
1. Operands' list elements can be used as operands (in expressions such as,
e.g., `[op_list[0]]`).
## Interface Changes
1. Add the function `qsvt_lcu` for efficiently encoding QSVT polynomials with indefinite parity.
2. Subsequent invocations to execution primitives inside `ExecutionSession` now use different random seeds (depending on the initial seed) to avoid getting the exact same simulation results inside a session.
## Classiq IDE
### New Visualization:
1. Clean up variable names in engine blocks.
## Interface Changes
1. `ExecutionSession` needs now to be explicitly closed, and it is recommended
to use it as a context manager. See [here](/user-guide/execution/ExecutionSession) for more information.
## Classiq IDE
1. Credentials for Alice & Bob hardware are now optional. Quantum programs run on Alice & Bob backends will use Classiq's credentials by default.
## Enhancements
1. Allow different parts of a quantum struct or array to be passed in different
sections of a quantum statement:
[comment]: DO_NOT_TEST
```python theme={null}
@qfunc
def main() -> None:
qbv = QArray("qbv")
allocate(2, qbv)
# The following line previously raised an exception, but is now valid
control(qbv[0], lambda: H(qbv[1]))
```
## Deprecations
1. Using `control` as a keyword parameter for standard gates (such as `CX`) is
no longer supported. Use `ctrl` instead.
## Bug Fixes
1. Fix package dependencies.
## Enhancements
1. This release introduces a new version to the Quantum Program (QP) visualization tool in parallel to the legacy visualization.
2. The new visualization version offers advanced visualization capabilities that bridge high-level algorithmic descriptions (Qmod) with gate-level implementations, incorporating interactive hierarchical views and data flow analysis.
### Feature Details
#### Visualization Versions:
Both the new version and the legacy version are available on the Quantum Program page.
Users can toggle between two visualization versions:
* 'New' version: Advanced visualization that includes quantum data flow views and new hierarchical block structures.
* 'Basic' version: Legacy visualization.
#### Documentation & Support:
[Initial documentation](/user-guide/analysis/visualization-of-quantum-programs) : A basic guide is available to help users navigate and utilize the visualization tool’s key features.
Tooltip: Integrated to the QP page to provide in-line initial guidance on key functions and elements.
#### Known Issues and Limitations:
Supported models: The 'New' visualization doesn't yet support all models. Unsupported models may not render - in these cases it is suggested to switch back to the 'Basic' visualization.
In-Progress development: This is part of an initial release milestone, with major issues being actively addressed.
#### Usage Recommendations
Switching between versions: It’s recommended to switch between the 'New' and 'Basic' versions to evaluate visualization consistency and effectiveness for specific quantum programs.
Feedback and bug reporting: Any issues, inconsistencies, or suggested improvements should be reported through the designated Slack channel for prompt review.
#### Next Steps
User feedback will inform ongoing improvements and prepare the tool for broader production release. Further enhancements and bug fixes are planned in alignment with Classiq’s high-level quantum design roadmap.
## Bug Fixes
1. Fix walkthrough bug in the IDE.
2. Change the default value of display\_url in show(circuit, display\_url) to True.
## Bug Fixes
Fix a bug causing execution failures on IBM in version 0.56.0.
## Interface Changes
1. Added an optional `else` block to the `control` statement.
## Bug Fixes
1. Fix Pauli feature map circuit visualization.
2. Add missing `len` property to `QConstant`s of type `CArray` (Qmod/Python).
## Enhancements
1. Qmod/Python: Functions `assign`, `assign_amplitude`, `inplace_xor`, and
`inplace_add` are equivalent to the operators `|=`, `*=`, `^=`, and `+=`
respectively except that they can be used in operands (Python lambda
functions):
[comment]: DO_NOT_TEST
```python theme={null}
within(
lambda: assign(x, y), # y |= x
lambda: inplace_xor(y, z), # z ^= y
)
```
2. Support non-equation Boolean expressions as control conditions:
[comment]: DO_NOT_TEST
```python theme={null}
@qfunc
def main(a: Output[QBit], b: Output[QBit], res: Output[QBit]) -> None:
allocate(1, a)
allocate(1, b)
allocate(1, res)
control(a & b, lambda: X(res))
```
```
qfunc main(output a: qbit, output b: qbit, output res: qbit) {
allocate(1, a);
allocate(1, b);
allocate(1, res);
control (a & b) {
X(res);
}
}
```
## Interface Changes
1. Parameters `value` and `target` of functions `inplace_add` and `inplace_xor`
have been renamed to `expression` and `target_var` respectively.
Parameters `value` and `target` will no longer be supported starting on
02/12/24 at the earliest.
## Bug Fixes
1. Solve a within-apply bug.
## Deprecations
1. Python 3.8 is no longer supported in the Python SDK. The minimum supported
version is now Python 3.9.
## Enhancements
1. Optimize in-place XOR variable assignments (`x ^= y`).
(The implementation no longer uses auxiliary qubits.)
2. Improve error messages in `CArray` (array) parameter declaration.
3. Support array subscripts and struct field access on the left-hand side of
in-place arithmetic assignments (`qbv[0] ^= 1` and `my_Struct.field += 2.5`).
4. Optimize the controlled version of QFT arithmetic implementations by skipping
controlling the QFT and QFT dagger.
## Enhancements
1. Introducing generative functions
to the Python SDK. Generative functions are `@qfunc`s that support Python
control flow, integration with third-party libraries, and debugging.
2. Execution using IBM devices is available again.
3. New method `estimation_cost` in `ExecutionSession` evaluates a quantum
circuit given a classical cost function.
4. A new `+=` operator performs
of quantum numerics.
Example: `z += x ** 2 - 0.5 * y`
5\. The state of `SampledState` supports dot-notation for field access when
representing a quantum struct:
[comment]: DO_NOT_TEST
```python theme={null}
struct_sample = sample.state["my_qstruct"]
field_sample = struct_sample.my_field
```
6. Add a new example for hybrid classical-quantum neural network. See [notebook](/explore/algorithms/QML/hybrid_qnn/hybrid_qnn_for_subset_majority#example-hybrid-neural-network-for-the-subset-majority-function).
## Interface Changes
1. Parameter `control` of built-in functions such as `CX` has been renamed to
`ctrl`. Parameter `control` will no longer be supported starting on 4/11/24
at the earliest.
2. Add two new functions for encoding classical data, `encode_in_angle` and `encode_on_bloch`. See [notebook](/qmod-reference/library-reference/open-library-functions/variational_data_encoding/variational_data_encoding/).
## Bug Fixes
1. Fix classical array slicing in the SDK (`my_list[1:3][0]`).
2. Fix synthesis of arithmetic operations nested in a within-apply statement
when `machine_precision` is set.
3. Fix in-place arithmetic operations (`^=`/`+=`) when the value on the
right-hand side is a signed variable that is not aligned with the target
variable.
## Enhancements
1. Optimize synthesis of variable and constant assignments (`x ^= y`, `x += 3`).
2. The behavior of synthesis with [`debug_mode`](/user-guide/synthesis/preferences?h=debug_mo#toggling-quantum-program-debug-information)
set to `False` has been changed, such that synthesis process is up to 50% faster. However,
the resulting visualized quantum program may lose much of its hierarchical structure.
Note that the default value for debug\_mode is still `True`, and this mode's behavior remains unchanged.
3. The maximum number of shots in a single execution on Nvidia simulators has
been increased to 1,000,000.
## Bug Fixes
1. Improve circuit width estimation when `machine_precision` is set.
2. Removing the non-gate-based devices from the available AWS Bracket devices.
3. Fix `n ^= 1` assignments where `n` has a single qubit
(used to raise an exception).
## Notice
* With the release of this version (`0.52.0`),
execution with older SDK versions may result in errors or unexpected behavior.
To ensure proper execution of your quantum programs via the SDK,
please upgrade to the latest version (See instructions guide above).
* The `Pydantic` package dependency has been upgraded from version 1 to version 2.
If you are using an older version of `Pydantic` in the same environment as our SDK,
this may lead to compatibility issues.
Note that installing or upgrading the SDK will also update your `Pydantic` version to V2.
It is recommended to verify compatibility across your environment.
## Bug Fixes
1. Allow the sign qubit of a quantum numeric variable to overlap the fraction
digits (e.g., `qnum[1, SIGNED, 1]`).
## Notice
* With the release of version `0.52` (scheduled for the week of 06-12.10.2024),
execution with older SDK versions might result in errors or unexpected behavior.
In order to make sure executions of your quantum programs via the SDK work properly
upgrade your SDK to the latest version (See instructions guide above).
## Enhancements
1. Improve qubit reuse in arithmetic operations when `machine_precision` is set.
2. Improve error messages when executing circuits on Amazon Braket.
3. Improve error messages when executing the VQE primitive.
4. Support constant assignments: `x |= 3`, `x ^= 3`, and `x += 3`.
## Bug Fixes
1. Fix in-place XOR assignments (`^=`) of 1-qubit expressions into multi-qubit
variables (used to raise an error).
## Interface Changes
1. Add a new function, `quantum_program_from_qasm`, to convert a QASM string into a Quantum Program.
## Notice
* With the release of version `0.52` (scheduled for the week of 06-12.10.2024),
execution with older SDK versions might result in errors or unexpected behavior.
In order to make sure executions of your quantum programs via the SDK work properly
upgrade your SDK to the latest version (See instructions guide above).
## Notice
* With the release of version `0.52` (scheduled for the week of 06-12.10.2024),
execution with older SDK versions might result in errors or unexpected behavior.
In order to make sure executions of your quantum programs via the SDK work properly
upgrade your SDK to the latest version (See instructions guide above).
## Bug Fixes
1. Raise indicative error when circuit cannot be visualized.
2. Fixed synthesis of arithmetic operations nested in a within-apply statement
when `machine_precision` is set.
## Enhancements
1. Improved error messages.
2. Added `SIGNED` and `UNSIGNED` built-in constants to improve readability of
QNum types. SDK: `QNum[4, SIGNED, 1]`. Native: `qnum<4, SIGNED, 1>`.
3. `QNum` types can specify just the size property. SDK: `QNum[4]` and
`QNum("n", 4)`. Native: `qnum<4>`. Such types are unsigned
(`is_signed=False`) integers (`fraction_digits=0`) by default.
4. Execution on remote providers is no longer subject to any time limit when using `ExecutionSession`
or executing models without classical execution code. Note: simulation on Classiq backends is still subject to time limit.
5. In-place add operations (`inplace_add`) now support signed variables.
6. Added a new notebook for solving the Differential equation using the HHL Algorithm, to simulate war games.
## Bug Fixes
1. Fixed an operand-related bug. Might occur when calling a function recursively
in one of its operands (for example: `foo(lambda: foo(...))`).
2. Fixed an expression-related bug. Might occur when using the same variable
in multiple expressions.
3. Fixed in-place XOR operations (`^=` / `inplace_xor`) in the presence of
signed variables. The sign variable is now interpreted as part of the
significand without special treatment.
4. Fixed synthesis of arithmetic operations nested in a within-apply statement.
## Interface Changes
1. SDK: Deprecated parameter names in built-in operations were removed.
* `control(ctrl=..., operand=...)` => `control(ctrl=..., stmt_block=...)`
* `within_apply(compute=..., action=...)` => `within_apply(within=..., apply=...)`
* `power(power=..., operand=...)` => `power(exponent=..., stmt_block=...)`
* `invert(operand=)` => `invert(stmt_block=...)`
## Enhancements
1. Cancelling an execution job will now result in cancellation of any ongoing jobs sent to the provider during the execution. For more information, see [Cancellation](/user-guide/execution/index#cancellation).
2. The Classiq SDK now supports Python 3.12.
3. Added a new tutorial on the Oblivious Amplitude Amplification algorithm.
## Enhancements
1. Improve synthesis performance in unconstrained large models by lowering circuit width via qubit recycling.
## Deprecations
1. The Classiq SDK will drop support for Python 3.8 near its end-of-life on October 2024.
## Bug Fixes
1. Fixed nested quantum struct bug.
## Enhancements
1. Add `size` attribute to quantum variables:
[comment]: DO_NOT_TEST
```python theme={null}
@qfunc
def main(my_struct: Output[MyStruct]) -> None:
allocate(my_struct.size, my_struct)
```
```
qfunc main(output my_struct: MyStruct) {
allocate(my_struct.size, my_struct);
}
```
## Bug Fixes
1. Fixed a bug related to boolean arithmetic expressions with invert.
2. Fixed a bug related to arithmetic expressions inside within-apply.
## Classiq IDE
1. Add back improved circuit nodes search.
2. Fix bug in Quantum Program page .qprog file extensions uploads.
3. Poll all active jobs in the job list, not just the selected job.
4. Add support for Alice & Bob hardware configurations in the IDE.
## Enhancements
1. Add support for arithmetic boolean expressions as conditionals for control statements;
see [here](/qmod-reference/language-reference/statements/control/).
2. Add quantum structs.
3. The element type of quantum arrays can be any quantum type. N-dimensional quantum arrays are supported.
4. Operand parameter names are optional in both Native
(`qfunc (indicator: qbit)` -> `qfunc (qbit)`) and Python
(`QCallable[QBit]` -> `QCallable[Annotated[QBit, "indicator"]]`) Qmod.
5. Improve error messages.
6. Provide better circuits for certain boolean arithmetic expressions.
7. Improved qubit reuse and runtime performance for model without constraints.
8. Add `solovay_kitaev_max_iterations` field to the synthesis preferences,
allowing for tuning the accuracy of the Solovay-Kitaev algorithm.
9. Built-in classical functions to decompose/compose a matrix into/from a Hamiltonian. Example of usage:
[comment]: DO_NOT_TEST
```python theme={null}
mat = np.array([[0, 1, 2, 3], [1, 4, 5, 6], [2, 5, 7, 8], [3, 6, 8, 9]])
hamiltonian = matrix_to_hamiltonian(mat)
mat = hamiltonian_to_matrix(hamiltonian)
```
10. parsed\_states, parsed\_counts, parsed\_state\_vector will contain the parsed execution details as lists if a quantum array was used in the model.
[comment]: DO_NOT_TEST
```python theme={null}
@qfunc
def main(qna: Output[QArray[QNum[3, True, 0]]]) -> None:
allocate(6, qna)
hadamard_transform(qna)
qp = synthesize(create_model(main))
res = execute(qp).result()
print(res[0].value.parsed_counts[0])
```
previously this would print -> state=\{\{'qna': 43}} shots=27
now it prints -> state=\{\{'qna': \[-2, 3]}} shots=27
11. Added a new tutorial on Hamiltonian simulation for block-encoded Hamiltonians, using QSVT and Qubitization.
12. Added a new tutorial on solving the discrete Poisson's equation using the HHL algorithm, combined with quantum sine and cosine transforms; see [here](/explore/algorithms/quantum_differential_equations_solvers/discrete_poisson_solver/discrete_poisson_solver/).
13. Enhanced the Discrete logarithm example to the case where the order is not a power of 2; see [here](/explore/algorithms/number_theory_and_cryptography/discrete_log/discrete_log/).
14. Updated the [Quantum Types](/qmod-reference/language-reference/quantum-types/) documentation page.
## Interface Changes
1. Some builtin operations parameters have been renamed:
* `control(ctrl=..., operand=...)` => `control(ctrl=..., stmt_block=...)`
* `within_apply(compute=..., action=...)` => `within_apply(within=..., apply=...)`
* `power(power=..., operand=...)` => `power(exponent=..., stmt_block=...)`
* `invert(operand=)` => `invert(stmt_block=...)`
2. Added new state preparation functions: `prepare_unifrom_trimmed_state` and `prepare_unifrom_interval_state`; see [here](/qmod-reference/library-reference/open-library-functions/special_state_preparations/prepare_partial_uniform_state/).
## Deprecations
1. SDK: The `@struct` decorator has been removed. Define classical structs
using `@dataclass`.
2. The field `variance` in `EstimationResult` is deprecated, and will be
populated with the value `-1` until removed.
3. The field `timeout_sec` in `ExecutionPreferences`, and the field
`job_timeout` in `AwsBackendPreferences`, have been removed.
4. classical arguments in the native language are now inside the parentheses
section (`(...)`) alongside quantum variables
and not inside the angle brackets (`<...>`), the angle brackets section is
now considered deprecated.
For example, you should
migrate: `qfunc main{...}` -> `qfunc main(a: real) {...}`
for info refer to the language reference about functions.
A Warning was added to the IDE in the case it is used.
## Enhancements
* Error mitigation can now be enabled or disabled for IonQ through Azure in the SDK. Default is set to False.
## Classiq IDE
1. Fix infinite loop bug in Quantum Program page.
2. Fix Quantum Program deletion bug on Quantum Program page.
## Bug Fixes
1. Fixed a bug related to nested control operations.
## Classiq IDE
1. Fix bug in .qprog files upload on Quantum Program page.
2. New Quantum Program export option: Quantum programs can now be exported as .qprog files.
## Enhancements
1. Support signed quantum numerics in in-place-xor assignments (`^=`).
2. Support quantum array subscripts in quantum expressions.
3. Support quantum numeric arrays.
4. Improve synthesis performance.
5. Apply an automatic qubit reuse pass when the model is unconstrained.
6. Add user-defined enums.
7. Added a new technology demonstration notebook for a discrete quantum walk on a circle; see [here](/explore/tutorials/technology_demonstrations/discrete_quantum_walk_circle/discrete_quantum_walk_circle/).
8. Added new rainbow options pricing notebooks in the public repository research folder.
[comment]: DO_NOT_TEST
```python theme={null}
@qfunc
def main(res: Output[QBit]) -> None:
allocate(1, res)
qnv: QArray = QArray("qnv", element_type=QNum[2, False, 0]) # quantum numeric array
allocate(6, qnv)
repeat(qnv.len, lambda i: inplace_prepare_int(i + 1, qnv[i]))
res ^= qnv[0] + qnv[1] == qnv[2] # array subscripts in expressions
```
```
qfunc main(output res: qbit) {
allocate<1>(res);
qnv: qnum<2, False, 0>[]; // quantum numeric array
allocate<6>(qnv);
repeat (i: qnv.len) { inplace_prepare_int(qnv[i]); }
res ^= qnv[0] + qnv[1] == qnv[2]; // array subscripts in expressions
}
```
## Interface Changes
1. The classical scope in Qmod no longer supports function definitions.
2. The `aer_simulator`, `aer_simulator_statevector`, `aer_simulator_density_matrix`, and `aer_simulator_matrix_product_state` Classiq backends are no longer accessible in the SDK. Use `simulator`, `simulator_statevector`, `simulator_density_matrix`, and `simulator_matrix_product_state` instead.
3. The `@struct` decorator is deprecated and will be removed in a future
release. Use `@dataclass` instead.
## Bug Fixes
1. Fixed a bug where multiple in-place assignment statements resulted in a `22102` error.
2. Fixed a bug where using the same variable in `control` operation for both the control operation and the body resulted in a non-indicative error.
3. Fix `invert` and `within-apply` variable initialization tracking in native
Qmod.
4. Fix division with classical symbolic variables.
5. Fix rogue comma inserted to the chemistry model classical execution code
after IDE form update.
6. Fix reporting uninitialized quantum variables in arithmetic expressions as
undefined.
7. Fix double execution on devices requiring access tokens.
8. Fix execution configuration being applied only to the first selected device, when one of the selected devices requires an access token.
9. Fix a bug where Grover circuit was incorrect when reflecting about states different than uniform superposition.
10. Fix a synthesis bug that could appear in models that constrain the width and optimize depth or vice versa.
## Classiq IDE
1. Graphical Model tab redesign of nodes (Function call, Output, Assignment).
2. Restructure of node categories (Graphical Model).
3. Fix countries list not loading sometimes during registration.
4. Prevent Qmod editor from crashing when compiler crashes.
5. Redesigned the Accordion and Icon status for jobs.
6. Quantum Program tabs moved to the left drawer.
7. Uploading Quantum Program can now be done using the Upload button on the left drawer.
8. 3 newly introduced tabs of Quantum Program data: Transpiled Info, Program Info, Data.
## Enhancements
* Add direct links of all examples from the documentation to Classiq's library and IDE.
## Bug Fixes
* fixed broken links.
## Enhancements
1. HHL workshop was added to the public repository and to the User Guide.
2. It is now possible to use the execution primitives `estimate` and `vqe` with models
with multiple output ports. The hamiltonian should match all the output ports
by their order.
3. Amplitude encoding assignments (`ind *= foo(n)`) support all quantum numeric
variables, not only unsigned fractions.
4. Add support for lookup tables in amplitude encoding assignments, e.g.,
`ind *= [0, 0.5, 0.5, 1][n]` where `n` is an unsigned quantum integer
(`ind *= subscript([0, 0.5, 0.5, 1], n)` in the SDK).
5. A quantum COSINE and SINE transforms of types I and II were added to the open library,
see [Quantum COSINE and SINE Transforms](/qmod-reference/library-reference/open-library-functions/qct_qst/qct_qst).
6. New algorithm was added to the library: "Variational Quantum Linear Solver (VQLS) with Linear Combination of Unitaries (LCU) Block Encoding"
7. `Alice & Bob` provider is now accessible.
## Interface Changes
1. `compute_qaoa_initial_point` is now exposed in the SDK directly from `classiq` package.
`from classiq import compute_qaoa_initial_point`
2. The examples in IDE Flow page are replaced with a new arithmetics example.
## Bug Fixes
1. Fixed an error related to the translation of certain circuits between synthesis and execution.
2. Fixed an error when calling a function with local variables multiple times.
3. Properly evaluate type attributes in `main`.
* Native Qmod: `qnum`'s sign field can be specified with lowercase
`true`/`false` in `main`'s signature.
4. Fix execution results received from running on Amazon Braket to be correct
when the measured outputs are not all of the variables of the model.
5. Improve language error reporting.
## Classiq IDE
1. Uniform drawer width for all pages
2. New way to trigger node options context menu on Graphical Model page: node options menu can now be triggered by right-clicking a selected node
## Enhancements
* Performance of synthesis has been improved, most significantly for synthesis requests
with no constraints.
## Enhancements
* Add `execution request` and `execution results` to reference manual in the documentation
## Bug Fixes
* Fix broken links in documentation
## Enhancements
1. [Hardware-aware synthesis](/user-guide/synthesis/hardware-aware-synthesis)
will now use the Solovay-Kitaev algorithm to approximate
single-qubit gates when the basis gate set is a specific variation of
Clifford + T (`X`, `Z`, `H`, `T`, `CX`, and `CCX`).
2. `qsvt` function was added to the function library.
See [Quantum Singular Value Transformation](/qmod-reference/library-reference/open-library-functions/qsvt/qsvt).
3. A tutorial on discrete quantum walks was added to the tutorials library.
See [Discrete Quantum Walk](/explore/tutorials/advanced_tutorials/discrete_quantum_walk/discrete_quantum_walk.ipynb).
4. SDK: Quantum functions (`@qfunc`) can be recursive.
5. SDK: PauliTerm can be used to declare a hamiltonian.
[comment]: DO_NOT_TEST
```python theme={null}
hamiltonian = [
PauliTerm(pauli=[Pauli.I], coefficient=1),
PauliTerm(pauli=[Pauli.Z, Pauli.X], coefficient=2),
]
```
6. Introducing **ExecutionSession** which will allow choosing the execution
primitive in the SDK
without the need of changing/synthesizing the quantum program once again.
[comment]: DO_NOT_TEST
```python theme={null}
model = create_model(main)
qprog = synthesize(model)
preferences = ExecutionPreferences(num_shots=1200)
execution_session = ExecutionSession(qprog, preferences)
# if the quantum program does not need any execution paramters:
execution_session.sample()
# if the quantum program needs execution parameters:
execution_session.sample({"phi": 1})
# if multiple samples are needed:
execution_session.batch_sample([{"phi": 1}, {"phi": 2}, {"phi": 3}])
# if an estimation is needed without execution parameters:
hamiltonian = [
PauliTerm(pauli=[Pauli.I], coefficient=1),
PauliTerm(pauli=[Pauli.Z], coefficient=2),
]
execution_parameters.estimate(hamiltonian)
# if an estimation is needed with execution paramters:
execution_parameters.estimate(hamiltonian, {"theta": 1})
# if multiple estimations are needed:
execution_parameters.batch_estimate(hamiltonian, [{"theta": 1}, {"theta": 2}])
```
7. A Qmod library reference, with usage examples for built-in and open library functions, can now be found in
[the function menu](/explore/functions/index).
## Interface Changes
1. SDK: In `execute_qnn`, the optional argument `observables` of type `PauliOperators`
has been replaced with the optional argument `observable` of type `PauliOperator`.
## Deprecations
1. SDK: The `quantum_if` operation and the old `control` syntax have been
removed.
* `quantum_if` is removed. Use `control` instead.
* `control(operand, ctrl)` is no longer supported. Use
`control(ctrl, operand)` instead.
* `control(n, operand)` does not support quantum numeric variables (`n`).
Instead, use a `bind` operation to cast `n` into a quantum array, or
compare `n` to an integer explicitly (e.g., `n == 7`).
2. SDK: The `QParam` type has been removed.
* Instead of `QParam[int]`, use `CInt`.
* Instead of `QParam[float]`, use `CReal`.
* Instead of `QParam[bool]`, use `CBool`.
* Instead of `QParam[List[...]]`, use `CArray[...]`.
* Instead of `QParam[Array[..., size]]`, use `CArray[..., size]`.
3. Native Qmod: Accessing quantum variable properties (e.g., `qbv.len` or
`n.is_signed`) via function call syntax (`len(qbv)`, `is_signed(qbv)`) is no
longer supported.
4. The field `optimizer_preferences` of `ExecutionPreferences` has been removed.
5. The function `set_initial_values` has been removed.
## Classiq IDE
1. "Slack" and "Learn More" links were moved from the side drawer to the IDE
header. New links were added as well: Community, User Guide.
2. Allow visualization of larger circuits and prolong the timeout for
visualization
3. Users can now download a LaTeX format of their quantum programs directly from
the IDE, allowing for easy sharing, publication, and presentation of their
work.
4. Cookies settings are now available to adjust the given consent at any time.
## Bug Fixes
1. "selected example not found" error when opening the IDE
2. Resetting now clears preferences form instead of initializing from cache on
the model page
3. Naming for exported files on the Graphical Editor
4. State vector measurement results ordering
5. Parameter names in lambda expressions don't have to match the
parameter names in operand declarations:
[comment]: DO_NOT_TEST
```python theme={null}
@qfunc
def my_H(qb: QBit) -> None:
H(qb)
...
apply_to_all(my_H, qba) # used to throw an error since "qb" != "target"
```
```
qfunc my_H(qb: qbit) {
H(qb);
}
...
apply_to_all(qba); // used to throw an error since "qb" != "target"
```
## Interface Changes
1. The `control` and `quantum_if` statements have been unified into one
statement in native Qmod and the SDK under the name `control`.
* SDK: The unified `control` statement accepts a qbit (`q`), a q-array
(`qbv`), or a comparison of a qnum and an integer (`n == 5`) as the
first argument.
* SDK: The old `control` syntax (with `ctrl` as the second argument) is
deprecated and will be removed in the next release.
* SDK: The `quantum_if` operator is deprecated and will be removed in the
next release.
* Native Qmod: `quantum_if` is no longer supported, use the new `control`
statement instead.
2. SDK: The `QParam` and `Array` types are deprecated and will be
removed in the next release.
* Instead of `QParam[int]`, use `CInt`.
* Instead of `QParam[float]`, use `CReal`.
* Instead of `QParam[bool]`, use `CBool`.
* Instead of `QParam[List[...]]`, use `CArray[...]`.
* Instead of `QParam[Array[..., size]]`, use `CArray[..., size]`.
3. SDK: Using Python types (`int`, `bool`, etc.) in struct declarations
(`@struct`) is deprecated and will not be supported by the next release.
Instead, use classical data types (`CInt`, `CBool`, etc., see above).
4. Default timeout for sending jobs to AWS changed from 5 minutes to 4 hours.
## Deprecations
1. The error mitigation settings in the execution preferences are no longer
available.
2. The `aer_simulator` backend has been removed. Use Classiq's simulator backend
instead (`ClassiqSimulatorBackendNames.SIMULATOR`).
## Enhancements
1. Improved error messages.
## Bug Fixes
1. Fixed a bug preventing execution of circuits synthesized with hardware aware synthesis on Azure and IonQ.
## Enhancements
1. Improved the native Qmod syntax of the `repeat`, `if` statements.
For details, see [Classical Control Flow](/qmod-reference/language-reference/statements/classical-control-flow).
2. Improved the native Qmod syntax of the `control`, `power`, and `invert` statements.
For details, see [Quantum Operators](/qmod-reference/language-reference/operators).
3. Added the `classiq.execution.all_hardware_devices.get_all_hardware_devices`
function to the Python SDK.
## Deprecations
1. In the SDK, the `classiq.analyzer.analyzer.Analyzer.get_available_devices` method is
deprecated. Use `classiq.execution.all_hardware_devices.get_all_hardware_devices`
instead.
## Interface Changes
1. The `len` method for `QArray`, `QCallableList`, and `QParam` of lists, is now a property.
use `.len` instead of `.len()`.
## Overview
Release 0.38 achieves a major milestone in the migration to the new Qmod language. The following general changes are now in effect:
1. In the IDE, Synthesis page is now removed. Writing and synthesizing models is now done exclusively in the Model page.
2. All pre-defined models previously available in the Synthesis page in Json format are now available in the Model page in native Qmod syntax.
3. Many Qmod language enhancements were introduced to enable the coding of all available models and applications, in both native Qmod and in its Python embedding (see detailed list below).
4. A new Qmod reference manual, covering all the language concepts and constructs in both input formats, is available [Qmod-language-reference](/qmod-reference/language-reference/index).
5. Documentation content covering old input formats - the Json input and the old SDK classes - has been removed
## Enhancements
1. Native Qmod now supports classical POD struct declaration, initialization, and member access.
2. Native Qmod now supports within-apply statements.
3. Native Qmod now supports generalized in-place quantum assignment.
4. Native Qmod now supports global constants.
## Interface Changes
1. The `QStruct` decorator was renamed to `struct` in the `qmod`-python integration.
2. The `qfunc` decorator is renamed to `quantum_function`. The newer `QFunc` and `ExternalQFunc` decorator are now available as `qfunc` and `qfunc(external=True)`. Using either classes as a decorator is deprecated, and this feature may be removed in a future release.
3. Similarly, a new `cfunc` decorator is now available, and using the class `CFunc` as a decorator is deprecated and may be removed in the future.
4. Renamed `GeneratedCircuit` to `QuantumProgram` in the SDK.
5. The `QNum` type does not accept size argument without sign and fraction digits.
6. `QNum` on the right-hand side of `bind` statements must have sign and fraction digits (inferred from initialization or declaration).
7. The Following async methods were removed from `Analyzer` class (The documented methods without the `async` suffix are still available and can be used instead):
1. `get_available_devices_async`
2. `analyzer_app_async`
3. `plot_hardware_connectivity_async`
4. `get_hardware_comparison_table_async`
8. The method `show_multiple_hardware_data` was removed from `RBAnalysis` class. The async equivalent `show_multiple_hardware_data_async` can be used instead.
9. Removed `reinterpret_num` operation (instead use `QNum`/`allocate_num` arguments).
10. Removed `split` and `join` operation (instead use `bind` operation).
11. Added method `parsed_counts_of_outputs` to sample's result in the Python SDK; see [sample](/user-guide/execution/sample).
12. Constants can now be used in the `qmod`-python integration with the `QConstant` class.
13. The quantum numeric type can now receive sign and fraction digits as type arguments in parameter declarations, in both the SDK and native Qmod.
* Native Qmod example: `qnum<5, True, 2>` to indicate a 5-bit signed number with 2 fraction digits.
* SDK examples:
* `QNum[5, True, 2]` to indicate a 5-bit signed number with 2 fraction digits (as a function argument)
* `QNum("x", 5, True, 2)` to indicate a 5-bit signed number with 2 fraction digits (as a local variable)
14. The amplitude encoding flavor of quantum arithmetic (`*=` operator) is now an in-place operation in both the SDK and native Qmod.
# Iqae
Source: https://docs.classiq.io/sdk-reference/applications/IQAE
Members:
| Name | Description |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `GenericIQAE` | The implementation is based on Algorithm 1 & Algorithm 2 in \[1], with the intent of demistifying variables names and simplifying the code flow. |
| `IQAEIterationData` | Handles the data storage for a single iteration of the Iterative Quantum Amplitude Estimation algorithm. |
| `IQAEResult` | Represents the result of an Iterative Quantum Amplitude Estimation (IQAE) process. |
| `ExecutionPreferences` | Represents the execution settings for running a quantum program. |
| `Constraints` | Constraints for the quantum circuit synthesis engine. |
| `Preferences` | Preferences for synthesizing a quantum circuit. |
| `ExecutionSession` | A session for executing a quantum program or OpenQASM source text. |
| `QBit` | A type representing a single qubit. |
| `Z` | \[Qmod core-library function]. |
| `allocate` | Initialize a quantum variable to a new quantum object in the zero state:. |
| `bind` | Reassign qubit or arrays of qubits by redirecting their logical identifiers. |
| `within_apply` | Given two operations $U$ and $V$, performs the composition of operations $U^\{-1\} V U$. |
| `drop` | \[Qmod core-library function]. |
| `create_model` | Create a serialized model from a given Qmod entry function and additional parameters. |
| `synthesize` | Synthesize a model with the Classiq engine to receive a quantum program. |
| `IQAE` | Implementation of Iterative Quantum Amplitude Estimation \[1]. |
## GenericIQAE
The implementation is based on Algorithm 1 & Algorithm 2 in \[1], with the intent of demistifying variables names
and simplifying the code flow.
Moreover, we separated the algorithm flow from quantum execution to allow migrating this code to any execution
interface and to improve its testability.
**Methods:**
| Name | Description |
| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [run](#run) | Execute the estimation algorithm. |
| [current\_estimation\_confidence\_interval](#current_estimation_confidence_interval) | |
| [current\_estimation](#current_estimation) | |
| [find\_next\_K](#find_next_K) | We want to find the largest K (with some lower and upper bounds) such that the K-scaled confidence interval lies completely in the upper or lower h... |
**Attributes:**
| Name | Type | Description |
| ------------ | --------------------- | ----------- |
| `iterations` | `list[IterationInfo]` | |
### run
run(
self:
) -> float
Execute the estimation algorithm.
See Algorithm 1, \[1].
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### current\_estimation\_confidence\_interval
current\_estimation\_confidence\_interval(
self:
) -> np.ndarray
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### current\_estimation
current\_estimation(
self:
) -> float
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### find\_next\_K
find\_next\_K(
K: int,
is\_upper\_plane: bool,
confidence\_interval: np.ndarray,
r: int = 2
) -> tuple\[int, bool]
We want to find the largest K (with some lower and upper bounds) such that the K-scaled confidence interval
lies completely in the upper or lower half planes.
See Algorithm 2, \[1].
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | ------------ | ----------- | ---------- |
| `K` | `int` | | *required* |
| `is_upper_plane` | `bool` | | *required* |
| `confidence_interval` | `np.ndarray` | | *required* |
| `r` | `int` | | 2 |
## IQAEIterationData
Handles the data storage for a single iteration of the Iterative Quantum Amplitude
Estimation algorithm.
This class is intended to represent the results and state of a single Grover iteration
of the IQAE process.
**Attributes:**
| Name | Type | Description |
| ------------------- | ------------------ | ----------------------------------------------------------------- |
| `grover_iterations` | `int` | The iteration number of Grover's algorithm. |
| `sample_results` | `ExecutionDetails` | The `ExecutionDetails` of Grover iteration. See ExecutionDetails. |
## IQAEResult
Represents the result of an Iterative Quantum Amplitude Estimation (IQAE)
process.
This class encapsulates the output of the IQAE algorithm, including the
estimated value, confidence interval, intermediate iteration data, and
any warnings generated during the computation.
**Attributes:**
| Name | Type | Description |
| --------------------- | ------------------------- | ----------------------------------------------------------------------------------- |
| `estimation` | `float` | Estimation of the amplitude. |
| `confidence_interval` | `list[float]` | The interval in which the amplitude is within, with a probability equal to epsilon. |
| `iterations_data` | `list[IQAEIterationData]` | List of `IQAEIterationData` of each Grover iteration. |
| `warnings` | `list[str]` | List of warnings generated during the IQAE process of each Grover iteration. |
## ExecutionPreferences
Represents the execution settings for running a quantum program.
Execution preferences for running a quantum program.
For more details, refer to:
ExecutionPreferences example: [ExecutionPreferences](https://docs.classiq.io/latest/user-guide/execution/#execution-preferences)..
**Attributes:**
| Name | Type | Description |
| -------------------------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `include_zero_amplitude_outputs` | `bool` | |
| `amplitude_threshold` | `float` | |
| `noise_properties` | `Optional[NoiseProperties]` | Properties defining the noise in the quantum circuit. Defaults to `None`. |
| `random_seed` | `int` | The random seed used for the execution. Defaults to a randomly generated seed. |
| `backend_preferences` | `BackendPreferencesTypes` | Preferences for the backend used to execute the circuit. Defaults to the Classiq Simulator. |
| `num_shots` | `Optional[pydantic.PositiveInt]` | The number of shots (executions) to be performed. |
| `transpile_to_hardware` | `TranspilationOption` | Option to transpile the circuit to the hardware's basis gates before execution. Defaults to `TranspilationOption.DECOMPOSE`. |
| `job_name` | `Optional[str]` | The name of the job, with a minimum length of 1 character. |
## Constraints
Constraints for the quantum circuit synthesis engine.
This class is used to specify constraints such as maximum width, depth,
gate count, and optimization parameters for the synthesis engine,
guiding the generation of quantum circuits that satisfy these constraints.
**Attributes:**
| Name | Type | Description |
| ------------------------ | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `max_width` | `int` | Maximum number of qubits allowed in the generated quantum circuit. Defaults to `None`. |
| `optimization_parameter` | `OptimizationParameterType` | Determines if and how the synthesis engine should optimize the solution. Defaults to `NO_OPTIMIZATION`. See `OptimizationParameterType` |
## Preferences
Preferences for synthesizing a quantum circuit.
**Methods:**
| Name | Description |
| ------------------------------------------------------------------------------------------------------------ | ----------- |
| [optimization\_timeout\_less\_than\_generation\_timeout](#optimization_timeout_less_than_generation_timeout) | |
| [make\_output\_format\_list](#make_output_format_list) | |
| [validate\_output\_format](#validate_output_format) | |
| [validate\_backend\_name](#validate_backend_name) | |
| [validate\_backend](#validate_backend) | |
**Attributes:**
| Name | Type | Description |
| ------------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `synthesize_all_separately` | `bool` | |
| `symbolic_loops` | `bool` | |
| `compatibility_mode` | `bool` | |
| `standalone` | `bool` | |
| `backend_preferences` | `BackendPreferences \| None` | |
| `machine_precision` | `int` | Specifies the precision used for quantum operations. Defaults to `DEFAULT_MACHINE_PRECISION`. |
| `backend_service_provider` | `str` | The provider company or cloud service for the requested backend. Defaults to `None`. |
| `backend_name` | `str` | The name of the requested backend or target. Defaults to `None`. |
| `custom_hardware_settings` | `CustomHardwareSettings` | Defines custom hardware settings for optimization. This field is ignored if backend preferences are specified. |
| `debug_mode` | `bool` | If `True`, debug information is added to the synthesized result, potentially slowing down the synthesis. Useful for executing interactive algorithms. Defaults to `True`. |
| `optimization_level` | `OptimizationLevel)` | The optimization level used during synthesis (0-3); |
| `output_format` | `List[QuantumFormat]` | Lists the output format(s) for the quantum circuit. Defaults to `[QuantumFormat.QASM]`. `QuantumFormat` Options: - QASM = "qasm" - QSHARP = "qsharp" - QIR = "qir" - IONQ = "ionq" - CIRQ\_JSON = "cirq\_json" - QASM\_CIRQ\_COMPATIBLE = "qasm\_cirq\_compatible" |
| `qasm3` | `Optional[bool]` | If `True`, outputs OpenQASM 3.0 in addition to 2.0, applicable to relevant attributes in `GeneratedCircuit`. Defaults to `None`. |
| `transpilation_option` | `TranspilationOption` | Sets the transpilation option to optimize the circuit. Defaults to `AUTO_OPTIMIZE`. See `TranspilationOption` |
| `solovay_kitaev_max_iterations` | `Optional[int]` | Specifies the maximum number of iterations for the Solovay-Kitaev algorithm, if used. Defaults to `None`. |
| `timeout_seconds` | `int` | Timeout setting for circuit synthesis in seconds. Defaults to `300`. |
| `optimization_timeout_seconds` | `Optional[int]` | Specifies the timeout for optimization in seconds, or `None` for no optimization timeout. This will still adhere to the overall synthesis timeout. Defaults to `None`. |
| `random_seed` | `int` | Random seed for circuit synthesis. |
### optimization\_timeout\_less\_than\_generation\_timeout
optimization\_timeout\_less\_than\_generation\_timeout(
cls: ,
optimization\_timeout\_seconds: pydantic.PositiveInt | None,
info: ValidationInfo
) -> pydantic.PositiveInt | None
**Parameters:**
| Name | Type | Description | Default |
| ------------------------------ | ------------------------------ | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `optimization_timeout_seconds` | `pydantic.PositiveInt \| None` | | *required* |
| `info` | `ValidationInfo` | | *required* |
### make\_output\_format\_list
make\_output\_format\_list(
cls: ,
output\_format: Any
) -> list
**Parameters:**
| Name | Type | Description | Default |
| --------------- | ----- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `output_format` | `Any` | | *required* |
### validate\_output\_format
validate\_output\_format(
cls: ,
output\_format: PydanticConstrainedQuantumFormatList,
info: ValidationInfo
) -> PydanticConstrainedQuantumFormatList
**Parameters:**
| Name | Type | Description | Default |
| --------------- | -------------------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `output_format` | `PydanticConstrainedQuantumFormatList` | | *required* |
| `info` | `ValidationInfo` | | *required* |
### validate\_backend\_name
validate\_backend\_name(
cls: ,
backend\_name: str | None
) -> str | None
**Parameters:**
| Name | Type | Description | Default |
| -------------- | ------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `backend_name` | `str \| None` | | *required* |
### validate\_backend
validate\_backend(
self:
) -> Self
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
## ExecutionSession
A session for executing a quantum program or OpenQASM source text.
`ExecutionSession` allows to execute the quantum program with different parameters and operations without the need to re-synthesize the model.
The session must be closed in order to ensure resources are properly cleaned up. It's recommended to use `ExecutionSession` as a context manager for this purpose. Alternatively, you can directly use the `close` method.
**Methods:**
| Name | Description |
| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| [close](#close) | Close the session and clean up its resources. |
| [get\_session\_id](#get_session_id) | |
| [update\_execution\_preferences](#update_execution_preferences) | Update the execution preferences for the session. |
| [sample](#sample) | Samples the quantum program with the given parameters, if any. |
| [submit\_sample](#submit_sample) | Initiates an execution job with the `sample` primitive. |
| [calculate\_state\_vector](#calculate_state_vector) | Calculate the state vector of the quantum program. |
| [submit\_calculate\_state\_vector](#submit_calculate_state_vector) | Initiates an execution job with the `calculate_state_vector` primitive. |
| [calculate\_unitary](#calculate_unitary) | Calculate the unitary matrix of the quantum program. |
| [submit\_calculate\_unitary](#submit_calculate_unitary) | Initiates an execution job with the `calculate_unitary` primitive. |
| [batch\_sample](#batch_sample) | Samples the quantum program multiple times with the given parameters for each iteration. |
| [submit\_batch\_sample](#submit_batch_sample) | Initiates an execution job with the `batch_sample` primitive. |
| [observe](#observe) | Estimates the expectation value of the given Hamiltonian using the quantum program. |
| [submit\_observe](#submit_observe) | Initiates an execution job with the `observe` primitive. |
| [estimate](#estimate) | Estimates the expectation value of the given Hamiltonian using the quantum program. |
| [submit\_estimate](#submit_estimate) | Initiates an execution job with the `estimate` primitive. |
| [batch\_estimate](#batch_estimate) | Estimates the expectation value of the given Hamiltonian multiple times using the quantum program, with the given parameters for each iteration. |
| [submit\_batch\_estimate](#submit_batch_estimate) | Initiates an execution job with the `batch_estimate` primitive. |
| [variational\_minimize](#variational_minimize) | Variationally minimizes the given cost function using the quantum program. |
| [minimize](#minimize) | . |
| [submit\_variational\_minimize](#submit_variational_minimize) | Initiates an execution job with the variational minimization primitive. |
| [submit\_minimize](#submit_minimize) | . |
| [estimate\_cost](#estimate_cost) | Estimates circuit cost using a classical cost function. |
| [set\_measured\_state\_filter](#set_measured_state_filter) | When simulating on a statevector simulator, emulate the behavior of postprocessing by discarding amplitudes for which their states are "undesirable". |
**Attributes:**
| Name | Type | Description |
| --------- | ---------------- | -------------------------------------------------------------------------------------------------------------- |
| `program` | `QuantumProgram` | The quantum program to execute, or a placeholder when the first constructor argument was OpenQASM source text. |
### close
close(
self:
) -> None
Close the session and clean up its resources.
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### get\_session\_id
get\_session\_id(
self:
) -> str
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### update\_execution\_preferences
update\_execution\_preferences(
self: ,
execution\_preferences: ExecutionPreferences | None
) -> None
Update the execution preferences for the session.
**Parameters:**
| Name | Type | Description | Default |
| ----------------------- | ------------------------------ | ------------------------------------ | ---------- |
| `self` | \`\` | | *required* |
| `execution_preferences` | `ExecutionPreferences \| None` | The execution preferences to update. | *required* |
**Returns:**
* **Type:** `None`
### sample
sample(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionDetails | list\[ExecutionDetails]
Samples the quantum program with the given parameters, if any.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `ExecutionDetails \| list[ExecutionDetails]`
* The result of the sampling, or a list of results when
* `parameters` is a list.
### submit\_sample
submit\_sample(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
Initiates an execution job with the `sample` primitive.
This is a non-blocking version of `sample`: it gets the same parameters and initiates the same execution job, but instead
of waiting for the result, it returns the job object immediately.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### calculate\_state\_vector
calculate\_state\_vector(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
filters: dict\[str, Any] | None = None,
amplitude\_threshold: float = 0.0,
verbose: bool = True
) -> DataFrame | list\[DataFrame]
Calculate the state vector of the quantum program.
The session must be configured with a Classiq simulator
(`"classiq/simulator"`, `"classiq/nvidia_simulator"`) or
`"google/cuquantum"`. The corresponding statevector variant is
selected automatically; callers do not need to know about the
`_statevector` backend names.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. | None |
| `filters` | `dict[str, Any] \| None` | Only states where the variables match these values will be included in the state vector. | None |
| `amplitude_threshold` | `float` | If provided, only states whose amplitude magnitude is strictly greater than this value will be included in the result. Defaults to 0 (filters exactly zero-amplitude states). | 0.0 |
| `verbose` | `bool` | Whether to print the "Submitting state-vector job to..." progress line. Set to `False` to suppress it, for example when calling `calculate_state_vector` repeatedly in a loop. Defaults to `True`. | True |
**Returns:**
* **Type:** `DataFrame \| list[DataFrame]`
* A dataframe containing the state vector, or a list of dataframes when
* `parameters` is a list.
### submit\_calculate\_state\_vector
submit\_calculate\_state\_vector(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
filters: dict\[str, Any] | None = None,
amplitude\_threshold: float = 0.0,
verbose: bool = True
) -> ExecutionJob
Initiates an execution job with the `calculate_state_vector` primitive.
This is a non-blocking version of [calculate\_state\_vector()](#calculate_state_vector): it gets
the same parameters and initiates the same execution job, but instead of
waiting for the result, it returns the job object immediately.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------------------------- | ---------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | See [calculate\_state\_vector()](#calculate_state_vector). | None |
| `filters` | `dict[str, Any] \| None` | See [calculate\_state\_vector()](#calculate_state_vector). | None |
| `amplitude_threshold` | `float` | See [calculate\_state\_vector()](#calculate_state_vector). | 0.0 |
| `verbose` | `bool` | See [calculate\_state\_vector()](#calculate_state_vector). | True |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### calculate\_unitary
calculate\_unitary(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
amplitude\_threshold: float = 0.0
) -> DataFrame | list\[DataFrame]
Calculate the unitary matrix of the quantum program.
The session must be configured with a Classiq simulator
(`"classiq/simulator"`, `"classiq/nvidia_simulator"`,
`"classiq/dgx_simulator"`) or `"google/cuquantum"`.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. | None |
| `amplitude_threshold` | `float` | If provided, matrix elements whose magnitude is below this threshold are zeroed (same cutoff semantics as `calculate_state_vector`). | 0.0 |
**Returns:**
* **Type:** `DataFrame \| list[DataFrame]`
* A dataframe containing the unitary matrix, or a list of dataframes when
* `parameters` is a list.
### submit\_calculate\_unitary
submit\_calculate\_unitary(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
amplitude\_threshold: float = 0.0
) -> ExecutionJob
Initiates an execution job with the `calculate_unitary` primitive.
Promotes the session backend to a unitary simulator and runs the `sample`
primitive on a dedicated unitary session. Program size limits are enforced
server-side.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | | None |
| `amplitude_threshold` | `float` | | 0.0 |
### batch\_sample
batch\_sample(
self: ,
parameters: list\[ExecutionParams]
) -> list\[ExecutionDetails]
Samples the quantum program multiple times with the given parameters for each iteration. The number of samples is determined by the length of the parameters list.
**Deprecated:** Pass a list of parameter dicts to [sample()](#sample) instead.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `list[ExecutionParams]` | A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | *required* |
**Returns:**
* **Type:** `list[ExecutionDetails]`
* List\[ExecutionDetails]: The results of all the sampling iterations.
### submit\_batch\_sample
submit\_batch\_sample(
self: ,
parameters: list\[ExecutionParams]
) -> ExecutionJob
Initiates an execution job with the `batch_sample` primitive.
**Deprecated:** Pass a list of parameter dicts to [submit\_sample()](#submit_sample) instead.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `list[ExecutionParams]` | A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | *required* |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### observe
observe(
self: ,
hamiltonian: Hamiltonian,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> EstimationResult | list\[EstimationResult]
Estimates the expectation value of the given Hamiltonian using the quantum program.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | The Hamiltonian to estimate the expectation value of. | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `EstimationResult \| list[EstimationResult]`
* The estimation result, or a list of results when `parameters`
* is a list.
### submit\_observe
submit\_observe(
self: ,
hamiltonian: Hamiltonian,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
Initiates an execution job with the `observe` primitive.
This is a non-blocking version of [observe()](#observe): it gets the same
parameters and initiates the same execution job, but instead of waiting
for the result, it returns the job object immediately.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | The Hamiltonian to estimate the expectation value of. | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### estimate
estimate(
self: ,
hamiltonian: Hamiltonian,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> EstimationResult | list\[EstimationResult]
Estimates the expectation value of the given Hamiltonian using the quantum program.
**Deprecated:** `estimate` is deprecated and will no longer be supported starting on 2026-06-22. Use [observe()](#observe) instead.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | | None |
| `num_shots` | `int \| None` | | None |
| `run_via_classiq` | `bool \| None` | | None |
### submit\_estimate
submit\_estimate(
self: ,
hamiltonian: Hamiltonian,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
Initiates an execution job with the `estimate` primitive.
**Deprecated:** `submit_estimate` is deprecated and will no longer be supported starting on 2026-06-22. Use [submit\_observe()](#submit_observe) instead.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | | None |
| `num_shots` | `int \| None` | | None |
| `run_via_classiq` | `bool \| None` | | None |
### batch\_estimate
batch\_estimate(
self: ,
hamiltonian: Hamiltonian,
parameters: list\[ExecutionParams]
) -> list\[EstimationResult]
Estimates the expectation value of the given Hamiltonian multiple times using the quantum program, with the given parameters for each iteration. The number of estimations is determined by the length of the parameters list.
**Deprecated:** Pass a list of parameter dicts to [observe()](#observe) instead.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | The Hamiltonian to estimate the expectation value of. | *required* |
| `parameters` | `list[ExecutionParams]` | A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | *required* |
**Returns:**
* **Type:** `list[EstimationResult]`
* List\[EstimationResult]: The results of all the estimation iterations.
### submit\_batch\_estimate
submit\_batch\_estimate(
self: ,
hamiltonian: Hamiltonian,
parameters: list\[ExecutionParams]
) -> ExecutionJob
Initiates an execution job with the `batch_estimate` primitive.
**Deprecated:** Pass a list of parameter dicts to [submit\_observe()](#submit_observe) instead.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | The Hamiltonian to estimate the expectation value of. | *required* |
| `parameters` | `list[ExecutionParams]` | A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | *required* |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### variational\_minimize
variational\_minimize(
self: ,
cost\_function: Hamiltonian | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
quantile: float = 1.0,
tolerance: float | None = None,
hosted: bool = False,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> list\[tuple\[float, ExecutionParams]]
Variationally minimizes the given cost function using the quantum program.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_function` | `Hamiltonian \| QmodExpressionCreator` | The cost function to minimize. It can be one of the following: - A quantum cost function defined by a Hamiltonian. - A classical cost function represented as a callable that returns a Qmod expression. The callable should accept `QVar`s as arguments and use names matching the Model outputs. | *required* |
| `initial_params` | `ExecutionParams` | The initial parameters for the minimization. Only Models with exactly one execution parameter are supported. This parameter must be of type `CReal` or `CArray`. The dictionary must contain a single key-value pair, where: - The key is the name of the parameter. - The value is either a float or a list of floats. | *required* |
| `max_iteration` | `int` | The maximum number of iterations for the minimization. | *required* |
| `quantile` | `float` | The quantile to use for cost estimation. | 1.0 |
| `tolerance` | `float \| None` | The tolerance for the minimization. | None |
| `hosted` | `bool` | When `True` on an IonQ backend, submit a Classiq execution job that runs the optimization loop on IonQ Hosted Hybrid in the backend. Defaults to `False`. | False |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `list[tuple[float, ExecutionParams]]`
* A list of tuples, each containing the estimated cost and the corresponding parameters for that iteration. `cost` is a float, and `parameters` is a dictionary matching the execution parameter format.
### minimize
minimize(
self: ,
cost\_function: Hamiltonian | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
quantile: float = 1.0,
tolerance: float | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> list\[tuple\[float, ExecutionParams]]
**Deprecated:** Use [variational\_minimize()](#variational_minimize) instead.
This name is kept for backward compatibility and will be removed in a future release.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_function` | `Hamiltonian \| QmodExpressionCreator` | | *required* |
| `initial_params` | `ExecutionParams` | | *required* |
| `max_iteration` | `int` | | *required* |
| `quantile` | `float` | | 1.0 |
| `tolerance` | `float \| None` | | None |
| `num_shots` | `int \| None` | | None |
| `run_via_classiq` | `bool \| None` | | None |
### submit\_variational\_minimize
submit\_variational\_minimize(
self: ,
cost\_function: Hamiltonian | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
quantile: float = 1.0,
tolerance: float | None = None,
hosted: bool = False,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
Initiates an execution job with the variational minimization primitive.
Non-blocking counterpart of [variational\_minimize()](#variational_minimize): same parameters and job,
but returns the [ExecutionJob](#executionjob) immediately.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_function` | `Hamiltonian \| QmodExpressionCreator` | The cost function to minimize. It can be one of the following: - A quantum cost function defined by a Hamiltonian. - A classical cost function represented as a callable that returns a Qmod expression. The callable should accept `QVar`s as arguments and use names matching the Model outputs. | *required* |
| `initial_params` | `ExecutionParams` | The initial parameters for the minimization. Only Models with exactly one execution parameter are supported. This parameter must be of type `CReal` or `CArray`. The dictionary must contain a single key-value pair, where: - The key is the name of the parameter. - The value is either a float or a list of floats. | *required* |
| `max_iteration` | `int` | The maximum number of iterations for the minimization. | *required* |
| `quantile` | `float` | The quantile to use for cost estimation. | 1.0 |
| `tolerance` | `float \| None` | The tolerance for the minimization. | None |
| `hosted` | `bool` | When `True` on an IonQ backend, submit a Classiq execution job that runs the optimization loop on IonQ Hosted Hybrid in the backend. Defaults to `False`. | False |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job. When `hosted=True` on an IonQ backend, the backend
* worker submits and polls IonQ Hosted Hybrid while this job tracks
* progress through the standard Classiq execution API.
### submit\_minimize
submit\_minimize(
self: ,
cost\_function: Hamiltonian | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
quantile: float = 1.0,
tolerance: float | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
**Deprecated:** Use [submit\_variational\_minimize()](#submit_variational_minimize) instead.
This name is kept for backward compatibility and will be removed in a future release.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_function` | `Hamiltonian \| QmodExpressionCreator` | | *required* |
| `initial_params` | `ExecutionParams` | | *required* |
| `max_iteration` | `int` | | *required* |
| `quantile` | `float` | | 1.0 |
| `tolerance` | `float \| None` | | None |
| `num_shots` | `int \| None` | | None |
| `run_via_classiq` | `bool \| None` | | None |
### estimate\_cost
estimate\_cost(
self: ,
cost\_func: Callable\[\[ParsedState], float],
parameters: ExecutionParams | None = None,
quantile: float = 1.0,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> float
Estimates circuit cost using a classical cost function.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------- | --------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_func` | `Callable[[ParsedState], float]` | classical circuit sample cost function | *required* |
| `parameters` | `ExecutionParams \| None` | execution parameters sent to 'sample' | None |
| `quantile` | `float` | drop cost values outside the specified quantile | 1.0 |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `float`
* cost estimation
### set\_measured\_state\_filter
set\_measured\_state\_filter(
self: ,
output\_name: str,
condition: Callable
) -> None
When simulating on a statevector simulator, emulate the behavior of postprocessing
by discarding amplitudes for which their states are "undesirable".
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ---------- | --------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `output_name` | `str` | The name of the register to filter | *required* |
| `condition` | `Callable` | Filter out values of the statevector for which this callable is False | *required* |
## QBit
A type representing a single qubit.
`QBit` serves both as a placeholder for a temporary, non-allocated qubit
and as the type of an allocated physical or logical qubit.
Conceptually, a qubit is a two-level quantum system, described by the
superposition of the computational basis states:
$$
|0\rangle = \begin{pmatrix} 1 \\ 0 \end{pmatrix},
\quad
|1\rangle = \begin{pmatrix} 0 \\ 1 \end{pmatrix}
$$
Therefore, a qubit state is a linear combination:
$$
|\psi\rangle = \alpha |0\rangle + \beta |1\rangle,
$$
where ( \alpha ) and ( \beta ) are complex numbers satisfying:
$$
|\alpha|^2 + |\beta|^2 = 1.
$$
Typical usage includes:
* Representing an unallocated qubit before its allocation.
* Acting as the output type for a qubit or an allocated qubit in the main function after calling an allocation function.
Examples:
**Methods:**
| Name | Description |
| --------------------------------- | ----------- |
| [to\_qvar](#to_qvar) | |
| [get\_qmod\_type](#get_qmod_type) | |
### to\_qvar
to\_qvar(
cls: ,
origin: str | Expr,
type\_hint: Any
) -> QBit
**Parameters:**
| Name | Type | Description | Default |
| ----------- | ------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `origin` | `str \| Expr` | | *required* |
| `type_hint` | `Any` | | *required* |
### get\_qmod\_type
get\_qmod\_type(
self:
) -> ConcreteQuantumType
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### Z
Z(
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Performs the Pauli-Z gate on a qubit.
This operation is represented by the following matrix:
$$
Z = \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | --------------------------------------- | ---------- |
| `target` | `Const[QBit]` | The qubit to apply the Pauli-Z gate to. | *required* |
### allocate
allocate(
args: Any = (),
kwargs: Any =
) -> None
Initialize a quantum variable to a new quantum object in the zero state:
$$
\left|\text{out}\right\rangle = \left|0\right\rangle^{\otimes \text{num_qubits}}
$$
If 'num\_qubits' is not specified, it will be inferred according to the type of 'out'.
In case the quantum variable is of type `QNum`, its numeric attributes can be specified as
well.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ----- | ----------- | ------- |
| `args` | `Any` | | () |
| `kwargs` | `Any` | | |
### bind
bind(
source: Input\[QVar] | list\[Input\[QVar]],
destination: Output\[QVar] | list\[Output\[QVar]]
) -> None
Reassign qubit or arrays of qubits by redirecting their logical identifiers.
This operation rewires the logical identity of the `source` qubits to new objects given in `destination`.
For example, an array of two qubits `X` can be mapped to individual qubits `Y` and `Z`.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ------------------------------------ | ----------------------------------------------------------------------------------------- | ---------- |
| `source` | `Input[QVar] \| list[Input[QVar]]` | A qubit or list of initialized qubits to reassign. | *required* |
| `destination` | `Output[QVar] \| list[Output[QVar]]` | A qubit or list of target qubits to bind to. Must match the number of qubits in `source`. | *required* |
### within\_apply
within\_apply(
within: Callable\[\[], Statements],
apply: Callable\[\[], Statements]
) -> None
Given two operations $U$ and $V$, performs the composition of operations $U^\{-1\} V U$.
This operation is used to represent a sequence where the operation `U` is applied, followed by another operation `V`, and then `U^{-1}` is applied to uncompute. This pattern is common in reversible
computation and quantum subroutines.
**Parameters:**
| Name | Type | Description | Default |
| -------- | -------------------------- | ------------------------------------------------------------- | ---------- |
| `within` | `Callable[[], Statements]` | The unitary operation `U` to be computed and then uncomputed. | *required* |
| `apply` | `Callable[[], Statements]` | The operation `V` to be applied within the `U` block. | *required* |
### drop
drop(
in\_: Input\[QArray\[QBit]]
) -> None
\[Qmod core-library function]
Discards the qubits allocated to a quantum variable which may be in any state,
preventing their further use.
**Parameters:**
| Name | Type | Description | Default |
| ----- | --------------------- | ---------------------------------------------------------------------- | ---------- |
| `in_` | `Input[QArray[QBit]]` | The quantum variable that will be dropped. Must be initialized before. | *required* |
### create\_model
create\_model(
entry\_point: QFunc | GenerativeQFunc,
constraints: Constraints | None = None,
execution\_preferences: ExecutionPreferences | None = None,
preferences: Preferences | None = None,
classical\_execution\_function: CFunc | None = None,
out\_file: str | None = None
) -> SerializedModel
Create a serialized model from a given Qmod entry function and additional parameters.
**Parameters:**
| Name | Type | Description | Default |
| ------------------------------ | ------------------------------ | -------------------------------------------------------------------------------- | ---------- |
| `entry_point` | `QFunc \| GenerativeQFunc` | The entry point function for the model, which must be a QFunc named 'main'. | *required* |
| `constraints` | `Constraints \| None` | Constraints for the synthesis of the model. See Constraints (Optional). | None |
| `execution_preferences` | `ExecutionPreferences \| None` | Preferences for the execution of the model. See ExecutionPreferences (Optional). | None |
| `preferences` | `Preferences \| None` | Preferences for the synthesis of the model. See Preferences (Optional). | None |
| `classical_execution_function` | `CFunc \| None` | A function for the classical execution logic, which must be a CFunc (Optional). | None |
| `out_file` | `str \| None` | File path to write the Qmod model in native Qmod representation to (Optional). | None |
**Returns:**
* **Type:** `SerializedModel`
* A serialized model.
### synthesize
synthesize(
model: SerializedModel | BaseQFunc,
auto\_show: bool = False,
constraints: Constraints | None = None,
preferences: Preferences | None = None
) -> QuantumProgram
Synthesize a model with the Classiq engine to receive a quantum program.
[More details](https://docs.classiq.io/latest/sdk-reference/synthesis/#classiq.synthesize)
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------- | ---------- |
| `model` | `SerializedModel \| BaseQFunc` | The entry point of the Qmod model - a qfunc named 'main' (or alternatively the output of 'create\_model'). | *required* |
| `auto_show` | `bool` | Whether to 'show' the synthesized model (False by default). | False |
| `constraints` | `Constraints \| None` | Constraints for the synthesis of the model. See Constraints (Optional). | None |
| `preferences` | `Preferences \| None` | Preferences for the synthesis of the model. See Preferences (Optional). | None |
**Returns:**
* **Type:** `QuantumProgram`
* Quantum program. (See: QuantumProgram)
## IQAE
Implementation of Iterative Quantum Amplitude Estimation \[1].
Given $A$ s.t. $A`|0>`_n`|0>` = \sqrt\{1-a\}|\psi_0>_n`|0>` + \sqrt\{a\}|\psi_1>_n`|1>`$, the algorithm estimates
$a$ by iteratively sampling $Q^kA$, where $Q=AS_0A^\{\dagger\}S_\{\psi_0\}$, and $k$ is an integer variable.
For estimating $a$, The algorithm estimates $\theta_a$ which is defined by $a = sin^2(\theta_a)$, so it starts with a
confidence interval $(0, \pi/2)$ and narrows down this interval on each iteration according to the sample results.
**Methods:**
| Name | Description |
| ------------------------ | -------------------------------------------------------------------------------------------- |
| [get\_model](#get_model) | Implement the quantum part of IQAE in terms of the Qmod Model. |
| [get\_qprog](#get_qprog) | Create an executable quantum Program for IQAE. |
| [run](#run) | Executes IQAE's quantum program with the provided epsilon, alpha, and execution preferences. |
### get\_model
get\_model(
self:
) -> SerializedModel
Implement the quantum part of IQAE in terms of the Qmod Model
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
**Returns:**
* **Type:** `SerializedModel`
* A serialized model.
### get\_qprog
get\_qprog(
self:
) -> QuantumProgram
Create an executable quantum Program for IQAE.
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
**Returns:**
* **Type:** `QuantumProgram`
* Quantum program. See QuantumProgram.
### run
run(
self: ,
epsilon: float,
alpha: float,
execution\_preferences: ExecutionPreferences | None = None
) -> IQAEResult
Executes IQAE's quantum program with the provided epsilon, alpha, and execution
preferences.
If execution\_preferences has been proved, or if it does not contain num\_shot, then num\_shot is set to 2048.
**Parameters:**
| Name | Type | Description | Default |
| ----------------------- | ------------------------------ | -------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `epsilon` | `float` | Target accuracy in therm of $\theta_a$ e.g $a = sin^2(\theta_a \pm \epsilon)$ . | *required* |
| `alpha` | `float` | Specifies the confidence level (1 - alpha) | *required* |
| `execution_preferences` | `ExecutionPreferences \| None` | Preferences for the execution of the model. See ExecutionPreferences (Optional). | None |
| Members: | | | |
| Name | Description |
| ------------------- | -------------------------------------------------------------------------------------------------------- |
| `IQAEIterationData` | Handles the data storage for a single iteration of the Iterative Quantum Amplitude Estimation algorithm. |
| `IQAEResult` | Represents the result of an Iterative Quantum Amplitude Estimation (IQAE) process. |
## IQAEIterationData
Handles the data storage for a single iteration of the Iterative Quantum Amplitude
Estimation algorithm.
This class is intended to represent the results and state of a single Grover iteration
of the IQAE process.
**Attributes:**
| Name | Type | Description |
| ------------------- | ------------------ | ----------------------------------------------------------------- |
| `grover_iterations` | `int` | The iteration number of Grover's algorithm. |
| `sample_results` | `ExecutionDetails` | The `ExecutionDetails` of Grover iteration. See ExecutionDetails. |
## IQAEResult
Represents the result of an Iterative Quantum Amplitude Estimation (IQAE)
process.
This class encapsulates the output of the IQAE algorithm, including the
estimated value, confidence interval, intermediate iteration data, and
any warnings generated during the computation.
**Attributes:**
| Name | Type | Description |
| --------------------- | ------------------------- | ----------------------------------------------------------------------------------- |
| `estimation` | `float` | Estimation of the amplitude. |
| `confidence_interval` | `list[float]` | The interval in which the amplitude is within, with a probability equal to epsilon. |
| `iterations_data` | `list[IQAEIterationData]` | List of `IQAEIterationData` of each Grover iteration. |
| `warnings` | `list[str]` | List of warnings generated during the IQAE process of each Grover iteration. |
# Qsp
Source: https://docs.classiq.io/sdk-reference/applications/QSP
## Functions
### qsvt\_phases
qsvt\_phases(
poly\_coeffs: np.ndarray,
cheb\_basis: bool = True
) -> np.ndarray
Get QSVT phases that will generate the given Chebyshev polynomial.
The phases are ready to be used in `qsvt` and `qsvt_lcu` functions in the classiq library. The convention
is the reflection signal operator, and the measurement basis is the hadamard basis (see [https://arxiv.org/abs/2105.02859](https://arxiv.org/abs/2105.02859)
APPENDIX A.).
The current implementation is using the nlft-qsp package.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ------------ | ------------------------------------------------------------------------------------------------------ | ---------- |
| `poly_coeffs` | `np.ndarray` | Array of polynomial coefficients (Chebyshev\Monomial, depending on cheb\_basis). | *required* |
| `cheb_basis` | `bool` | Whether the poly coefficients are given in Chebyshev (True) or Monomial(False). Defaults to Chebyshev. | True |
### qsp\_approximate
qsp\_approximate(
f\_target: Callable\[\[float], complex],
degree: int,
parity: int | None = None,
interval: tuple\[float, float] = (-1, 1),
bound: float = 0.99,
num\_grid\_points: int | None = None,
plot: bool = False
) -> tuple\[np.ndarray, float]
Approximate the target function on the given (sub-)interval of \[-1,1], using QSP-compatible chebyshev polynomials.
The approximating polynomial is enforced to |P(x)| \<= bound on all of \[-1,1].
Note: scaling f\_target by a factor \< 1 might help the convergence and also a later qsp phase factor finiding.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------ | ---------- |
| `f_target` | `Callable[[float], complex]` | Real function to approximate within the given interval. Should be bounded by \[-1, 1] in the given interval. | *required* |
| `degree` | `int` | Approximating polynomial degree. | *required* |
| `parity` | `int \| None` | None - full polynomial, 0 - restrict to even polynomial, 1 - odd polynomial. | None |
| `interval` | `tuple[float, float]` | sub interval of \[-1, 1] to approximate the function within. | (-1, 1) |
| `bound` | `float` | global polynomial bound on \[-1,1] (defaults to 0.99). | 0.99 |
| `num_grid_points` | `int \| None` | sets the number of grid points used for the polynomial approximation (defaults to `max(2 * degree, 1000)`). | None |
| `plot` | `bool` | A flag for plotting the resulting approximation vs the target function. | False |
**Returns:**
* **Type:** `tuple[np.ndarray, float]`
* Array of Chebyshev coefficients. In case of definite parity, still a full coefficients array is returned.
* (Approximated) maximum error between the target function and the approximating polynomial within the interval.
### gqsp\_phases
gqsp\_phases(
poly\_coeffs: np.ndarray,
cheb\_basis: bool = False
) -> list\[tuple\[float, float, float]]
Compute GQSP phases for a polynomial in the monomial (power) basis.
The returned phases are compatible with Classiq's `gqsp` function and use the Wz signal
operator convention.
The current implementation is using the nlft-qsp package, based on techniques in [https://arxiv.org/abs/2503.03026](https://arxiv.org/abs/2503.03026).
Notes:
* The polynomial must be bounded on the unit circle:
$|P(e^\{i*theta\})|$ \<= 1 for all theta in $[0, 2*pi)$.
* Laurent polynomials are supported by degree shifting. If
$P(z) = sum_\{k=m\}^n c_k * z^k with m < 0, the phases correspond to the$
degree-shifted polynomial $z^\{-m\} * P(z)$ (so the minimal degree is zero).
* The phase finiding works in the monomial basis. If a Chebyshev basis polynomial is provided,
it will be converted to the monomial basis (and introduce an additional overhead).
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ------------ | ----------------------------------------------------------------------------------------------------- | ---------- |
| `poly_coeffs` | `np.ndarray` | | *required* |
| `cheb_basis` | `bool` | Whether the poly coefficients are given in Chebyshev (True) or Monomial(False). Defaults to Monomial. | False |
**Returns:**
* **Type:** `list[tuple[float, float, float]]`
* list of (theta, phi, lambda) tuples of length d+1, ready to use with `gqsp`.
### poly\_jacobi\_anger\_cos
poly\_jacobi\_anger\_cos(
degree: int,
t: float
) -> np.ndarray
Gets the Chebyshev polynomial coefficients approximating cos(t\*x) using the Jacobi-Anger expansion.
$\cos(xt) = J_0(t) + 2\sum_\{k=1\}^\{d/2\} (-1)^k J_\{2k\}(t)\, T_\{2k\}(x) $
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------- | -------------------------------------------- | ---------- |
| `degree` | `int` | the degree of the approximating polynomial. | *required* |
| `t` | `float` | the parameter in cos(t\*x). Can be negative. | *required* |
### poly\_jacobi\_anger\_sin
poly\_jacobi\_anger\_sin(
degree: int,
t: float
) -> np.ndarray
Gets the Chebyshev polynomial coefficients approximating sin(t\*x) using the Jacobi-Anger expansion.
$\sin(xt) = 2\sum_\{k=0\}^\{d/2\} (-1)^k J_\{2k+1\}(t)\, T_\{2k+1\}(x)$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------- | ------------------------------------------- | ---------- |
| `degree` | `int` | the degree of the approximating polynomial. | *required* |
| `t` | `float` | the parameter in sin(t\*x). | *required* |
### poly\_jacobi\_anger\_exp\_sin
poly\_jacobi\_anger\_exp\_sin(
degree: int,
t: float
) -> np.ndarray
Gets the Chebyshev polynomial coefficients approximating exp(i*t*sin(x)) using the Jacobi-Anger expansion:
$e^\{it\sin(x)\} = \sum_\{k=-d\}^\{d\} J_\{k\}(t) e^\{ikx\}$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------- | --------------------------------------------------------------------------- | ---------- |
| `degree` | `int` | the maximum degree of the approximating polynomial (negative and positive). | *required* |
| `t` | `float` | the parameter in exp(i*t*sin(x)). | *required* |
### poly\_jacobi\_anger\_exp\_cos
poly\_jacobi\_anger\_exp\_cos(
degree: int,
t: float
) -> np.ndarray
Gets the Chebyshev polynomial coefficients approximating exp(i*t*cos(x)) using the Jacobi-Anger expansion:
$e^\{it\cos(x)\} = \sum_\{k=-d\}^\{d\} i^k J_\{k\}(t) e^\{ikx\}$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------- | --------------------------------------------------------------------------- | ---------- |
| `degree` | `int` | the maximum degree of the approximating polynomial (negative and positive). | *required* |
| `t` | `float` | the parameter in exp(i*t*cos(x)). | *required* |
### poly\_inversion
poly\_inversion(
degree: int,
kappa: float,
error\_type: str | ErrorType = ErrorType.RELATIVE
) -> tuple\[np.ndarray, float]
Gets the Chebyshev odd polynomial p(x) coefficients approximating 1/x on \[1/kappa, 1].
Based on the papers: [https://dl.acm.org/doi/pdf/10.1145/3649320](https://dl.acm.org/doi/pdf/10.1145/3649320) - for optimal polynomial that minimizes the relative error |xp(x)-1| for
x in \[1/kappa,1]; and [https://arxiv.org/pdf/2507.15537-](https://arxiv.org/pdf/2507.15537-) for optimal polynomial that minimizes the uniform error |p(x)-1/x| for x in \[1/kappa,1].
The relative error refers to |xp(x)-1|, whereas the uniform error refers to |p(x)-1/x|, both for x in \[1/kappa,1].
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ------------------ | --------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `degree` | `int` | The degree of the approximating polynomial. | *required* |
| `kappa` | `float` | The number defining the interval \[1/kappa, 1], usually represents the condition number in the setting of matrix inversion. | *required* |
| `error_type` | `str \| ErrorType` | A string specifying the error type to minimize, can be either "relative" (default) or "uniform". | ErrorType.RELATIVE |
**Returns:**
* **Type:** `tuple[np.ndarray, float]`
* The Chebyshev polynomial coefficients approximating 1/x on \[1/kappa, 1]
using the optimal polynomial of given degree.
* An upper bound on the maximum absolute value of the polynomial on \[-1, 1]. The value
can be used to scale down the polynomial for the usage within QSVT.
# Qsvm
Source: https://docs.classiq.io/sdk-reference/applications/QSVM
## QSVM
Quantum support vector machine (QSVM) model.
Classifies classical data into two categories.
The model is first trained, and fitted. After pre-training,
the model predicts the labels of new data points.
**Methods:**
| Name | Description |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| [train](#train) | Trains an SVM model using a custom precomputed kernel from the training data. |
| [predict](#predict) | Predicts labels for new data using a precomputed kernel with a trained SVM model. |
| [test](#test) | Predicts the labels of the test dataset and evaluates the resulting test score using the ground-truth labels. |
| [get\_svm\_model](#get_svm_model) | Returns the classical SVM model. |
| [get\_qprog](#get_qprog) | Returns the quantum program for the kernel at `data_dim` feature width. |
**Attributes:**
| Name | Type | Description |
| ----------------------- | -------------------- | ----------- |
| `feature_map` | | |
| `num_qubits` | | |
| `execution_preferences` | | |
| `kernel_eval` | | |
| `model` | | |
| `train_data` | `np.ndarray \| None` | |
### train
train(
self: ,
train\_data: np.ndarray,
train\_labels: np.ndarray
) -> None
Trains an SVM model using a custom precomputed kernel from the training data.
**Parameters:**
| Name | Type | Description | Default |
| -------------- | ------------ | ------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `train_data` | `np.ndarray` | Contains the data points (np.ndarray) | *required* |
| `train_labels` | `np.ndarray` | Contains the labels (0,1). | *required* |
### predict
predict(
self: ,
data: np.ndarray
) -> np.ndarray
Predicts labels for new data using a precomputed kernel with a trained SVM model. Evaluates kernel
matrix elements which are associated with the support vectors (those associated with non-vanishing
coefficients in the prediction equation).
**Parameters:**
| Name | Type | Description | Default |
| ------ | ------------ | ----------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `data` | `np.ndarray` | List of new data points to predict. | *required* |
**Returns:**
* **Type:** `np.ndarray`
* np.ndarray: Predicted labels (0,1).
### test
test(
self: ,
data: np.ndarray,
data\_labels: np.ndarray
) -> tuple\[float, np.ndarray]
Predicts the labels of the test dataset and evaluates the resulting test score using the ground-truth labels.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ------------ | ------------------------------------ | ---------- |
| `self` | \`\` | | *required* |
| `data` | `np.ndarray` | List of test data points to predict. | *required* |
| `data_labels` | `np.ndarray` | Contains the test data labels. | *required* |
**Returns:**
* **Type:** `tuple[float, np.ndarray]`
* containing test score (float) and test labels (np.ndarray\[int]).
### get\_svm\_model
get\_svm\_model(
self:
) -> SVC
Returns the classical SVM model.
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### get\_qprog
get\_qprog(
self: ,
data\_dim: int = 0
) -> QuantumProgram
Returns the quantum program for the kernel at `data_dim` feature width.
**Parameters:**
| Name | Type | Description | Default |
| ---------- | ----- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `data_dim` | `int` | | 0 |
# Chemistry
Source: https://docs.classiq.io/sdk-reference/applications/chemistry
Members:
| Name | Description |
| --------------------------- | -------------------------------------------------------------------------------------- |
| `FermionHamiltonianProblem` | Defines an electronic-structure problem using a Fermionic operator and electron count. |
## FermionHamiltonianProblem
Defines an electronic-structure problem using a Fermionic operator and electron count.
Can also be constructed from a `MolecularData` object using the `from_molecule`
method.
**Methods:**
| Name | Description |
| -------------------------------- | -------------------------------------------------------------- |
| [from\_molecule](#from_molecule) | Constructs a `FermionHamiltonianProblem` from a molecule data. |
**Attributes:**
| Name | Type | Description |
| --------------------- | ----------------- | ----------------------------------------------------------------------------------- |
| `occupied_alpha` | `list[int]` | |
| `virtual_alpha` | `list[int]` | |
| `occupied_beta` | `list[int]` | |
| `virtual_beta` | `list[int]` | |
| `occupied` | `list[int]` | |
| `virtual` | `list[int]` | |
| `fermion_hamiltonian` | `FermionOperator` | The fermionic hamiltonian of the problem. Assumed to be in the block-spin labeling. |
| `n_orbitals` | `int` | Number of spatial orbitals. |
| `n_alpha` | `int` | Number of alpha particles. |
| `n_beta` | `int` | Number of beta particles. |
| `n_particles` | `tuple[int, int]` | Number of alpha and beta particles. |
### from\_molecule
from\_molecule(
cls: ,
molecule: MolecularData,
first\_active\_index: int = 0,
remove\_orbitals: Sequence\[int] | None = None,
op\_compression\_tol: float = 1e-13
) -> FermionHamiltonianProblem
Constructs a `FermionHamiltonianProblem` from a molecule data.
**Parameters:**
| Name | Type | Description | Default |
| -------------------- | ----------------------- | ---------------------------------------------------------------- | ---------- |
| `cls` | \`\` | | *required* |
| `molecule` | `MolecularData` | The molecule data. | *required* |
| `first_active_index` | `int` | The first active index, indicates all prior indices are freezed. | 0 |
| `remove_orbitals` | `Sequence[int] \| None` | Active indices to be removed. | None |
| `op_compression_tol` | `float` | Tolerance for trimming the fermion operator. | 1e-13 |
**Returns:**
* **Type:** `FermionHamiltonianProblem`
* The fermion hamiltonian problem.
Members:
| Name | Description |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `FermionHamiltonianProblem` | Defines an electronic-structure problem using a Fermionic operator and electron count. |
| `MappingMethod` | Mapping methods from fermionic operators to qubits operators. |
| `FermionToQubitMapper` | Mapper between fermionic operators to qubits operators, using one of the supported mapping methods (see `MappingMethod`). |
## FermionHamiltonianProblem
Defines an electronic-structure problem using a Fermionic operator and electron count.
Can also be constructed from a `MolecularData` object using the `from_molecule`
method.
**Methods:**
| Name | Description |
| -------------------------------- | -------------------------------------------------------------- |
| [from\_molecule](#from_molecule) | Constructs a `FermionHamiltonianProblem` from a molecule data. |
**Attributes:**
| Name | Type | Description |
| --------------------- | ----------------- | ----------------------------------------------------------------------------------- |
| `occupied_alpha` | `list[int]` | |
| `virtual_alpha` | `list[int]` | |
| `occupied_beta` | `list[int]` | |
| `virtual_beta` | `list[int]` | |
| `occupied` | `list[int]` | |
| `virtual` | `list[int]` | |
| `fermion_hamiltonian` | `FermionOperator` | The fermionic hamiltonian of the problem. Assumed to be in the block-spin labeling. |
| `n_orbitals` | `int` | Number of spatial orbitals. |
| `n_alpha` | `int` | Number of alpha particles. |
| `n_beta` | `int` | Number of beta particles. |
| `n_particles` | `tuple[int, int]` | Number of alpha and beta particles. |
### from\_molecule
from\_molecule(
cls: ,
molecule: MolecularData,
first\_active\_index: int = 0,
remove\_orbitals: Sequence\[int] | None = None,
op\_compression\_tol: float = 1e-13
) -> FermionHamiltonianProblem
Constructs a `FermionHamiltonianProblem` from a molecule data.
**Parameters:**
| Name | Type | Description | Default |
| -------------------- | ----------------------- | ---------------------------------------------------------------- | ---------- |
| `cls` | \`\` | | *required* |
| `molecule` | `MolecularData` | The molecule data. | *required* |
| `first_active_index` | `int` | The first active index, indicates all prior indices are freezed. | 0 |
| `remove_orbitals` | `Sequence[int] \| None` | Active indices to be removed. | None |
| `op_compression_tol` | `float` | Tolerance for trimming the fermion operator. | 1e-13 |
**Returns:**
* **Type:** `FermionHamiltonianProblem`
* The fermion hamiltonian problem.
## MappingMethod
Mapping methods from fermionic operators to qubits operators.
**Attributes:**
| Name | Type | Description |
| --------------- | ------ | ----------- |
| `JORDAN_WIGNER` | `'jw'` | |
| `BRAVYI_KITAEV` | `'bk'` | |
## FermionToQubitMapper
Mapper between fermionic operators to qubits operators, using one of the supported
mapping methods (see `MappingMethod`).
**Methods:**
| Name | Description |
| ----------------------------------- | ---------------------------------------------------------------------------------------- |
| [map](#map) | Maps the given fermionic operator to a qubits operator using the mapper's configuration. |
| [get\_num\_qubits](#get_num_qubits) | Gets the number of qubits after mapping the given problem into qubits space. |
**Attributes:**
| Name | Type | Description |
| -------- | --------------- | ------------------- |
| `method` | `MappingMethod` | The mapping method. |
### map
map(
self: ,
fermion\_op: FermionOperator,
args: Any = (),
kwargs: Any =
) -> QubitOperator
Maps the given fermionic operator to a qubits operator using the mapper's
configuration.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ----------------- | --------------------- | ---------- |
| `self` | \`\` | | *required* |
| `fermion_op` | `FermionOperator` | A fermionic operator. | *required* |
| `args` | `Any` | | () |
| `kwargs` | `Any` | | |
**Returns:**
* **Type:** `QubitOperator`
* The mapped qubits operator.
### get\_num\_qubits
get\_num\_qubits(
self: ,
problem: FermionHamiltonianProblem
) -> int
Gets the number of qubits after mapping the given problem into qubits space.
**Parameters:**
| Name | Type | Description | Default |
| --------- | --------------------------- | -------------------- | ---------- |
| `self` | \`\` | | *required* |
| `problem` | `FermionHamiltonianProblem` | The fermion problem. | *required* |
**Returns:**
* **Type:** `int`
* The number of qubits.
Members:
| Name | Description |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `FermionToQubitMapper` | Mapper between fermionic operators to qubits operators, using one of the supported mapping methods (see `MappingMethod`). |
| `MappingMethod` | Mapping methods from fermionic operators to qubits operators. |
| `FermionHamiltonianProblem` | Defines an electronic-structure problem using a Fermionic operator and electron count. |
| `Z2SymTaperMapper` | Mapper between fermionic operators to qubits operators, using one of the supported mapping methods (see `MappingMethod`), and taking advantage of Z... |
## FermionToQubitMapper
Mapper between fermionic operators to qubits operators, using one of the supported
mapping methods (see `MappingMethod`).
**Methods:**
| Name | Description |
| ----------------------------------- | ---------------------------------------------------------------------------------------- |
| [map](#map) | Maps the given fermionic operator to a qubits operator using the mapper's configuration. |
| [get\_num\_qubits](#get_num_qubits) | Gets the number of qubits after mapping the given problem into qubits space. |
**Attributes:**
| Name | Type | Description |
| -------- | --------------- | ------------------- |
| `method` | `MappingMethod` | The mapping method. |
### map
map(
self: ,
fermion\_op: FermionOperator,
args: Any = (),
kwargs: Any =
) -> QubitOperator
Maps the given fermionic operator to a qubits operator using the mapper's
configuration.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ----------------- | --------------------- | ---------- |
| `self` | \`\` | | *required* |
| `fermion_op` | `FermionOperator` | A fermionic operator. | *required* |
| `args` | `Any` | | () |
| `kwargs` | `Any` | | |
**Returns:**
* **Type:** `QubitOperator`
* The mapped qubits operator.
### get\_num\_qubits
get\_num\_qubits(
self: ,
problem: FermionHamiltonianProblem
) -> int
Gets the number of qubits after mapping the given problem into qubits space.
**Parameters:**
| Name | Type | Description | Default |
| --------- | --------------------------- | -------------------- | ---------- |
| `self` | \`\` | | *required* |
| `problem` | `FermionHamiltonianProblem` | The fermion problem. | *required* |
**Returns:**
* **Type:** `int`
* The number of qubits.
## MappingMethod
Mapping methods from fermionic operators to qubits operators.
**Attributes:**
| Name | Type | Description |
| --------------- | ------ | ----------- |
| `JORDAN_WIGNER` | `'jw'` | |
| `BRAVYI_KITAEV` | `'bk'` | |
## FermionHamiltonianProblem
Defines an electronic-structure problem using a Fermionic operator and electron count.
Can also be constructed from a `MolecularData` object using the `from_molecule`
method.
**Methods:**
| Name | Description |
| -------------------------------- | -------------------------------------------------------------- |
| [from\_molecule](#from_molecule) | Constructs a `FermionHamiltonianProblem` from a molecule data. |
**Attributes:**
| Name | Type | Description |
| --------------------- | ----------------- | ----------------------------------------------------------------------------------- |
| `occupied_alpha` | `list[int]` | |
| `virtual_alpha` | `list[int]` | |
| `occupied_beta` | `list[int]` | |
| `virtual_beta` | `list[int]` | |
| `occupied` | `list[int]` | |
| `virtual` | `list[int]` | |
| `fermion_hamiltonian` | `FermionOperator` | The fermionic hamiltonian of the problem. Assumed to be in the block-spin labeling. |
| `n_orbitals` | `int` | Number of spatial orbitals. |
| `n_alpha` | `int` | Number of alpha particles. |
| `n_beta` | `int` | Number of beta particles. |
| `n_particles` | `tuple[int, int]` | Number of alpha and beta particles. |
### from\_molecule
from\_molecule(
cls: ,
molecule: MolecularData,
first\_active\_index: int = 0,
remove\_orbitals: Sequence\[int] | None = None,
op\_compression\_tol: float = 1e-13
) -> FermionHamiltonianProblem
Constructs a `FermionHamiltonianProblem` from a molecule data.
**Parameters:**
| Name | Type | Description | Default |
| -------------------- | ----------------------- | ---------------------------------------------------------------- | ---------- |
| `cls` | \`\` | | *required* |
| `molecule` | `MolecularData` | The molecule data. | *required* |
| `first_active_index` | `int` | The first active index, indicates all prior indices are freezed. | 0 |
| `remove_orbitals` | `Sequence[int] \| None` | Active indices to be removed. | None |
| `op_compression_tol` | `float` | Tolerance for trimming the fermion operator. | 1e-13 |
**Returns:**
* **Type:** `FermionHamiltonianProblem`
* The fermion hamiltonian problem.
## Z2SymTaperMapper
Mapper between fermionic operators to qubits operators, using one of the supported
mapping methods (see `MappingMethod`), and taking advantage of Z2 symmetries in
order to taper off qubits.
**Methods:**
| Name | Description |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [set\_sector](#set_sector) | Sets the symmetry sector coefficients. |
| [map](#map) | Maps the given fermionic operator to qubits operator by using the mapper's method, and subsequently by tapering off qubits according to Z2 symmetries. |
| [get\_num\_qubits](#get_num_qubits) | Gets the number of qubits after mapping the given problem into qubits space. |
| [from\_problem](#from_problem) | Initializes a `Z2SymTaperMapper` object from a fermion problem (i.e. |
**Attributes:**
| Name | Type | Description |
| ------------ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `method` | `MappingMethod` | The mapping method. |
| `generators` | `tuple[QubitOperator, ...]` | Generators representing the Z2 symmetries. |
| `x_ops` | `tuple[QubitOperator, ...]` | Single-qubit X operations, such that each operation anti-commutes with its matching generator and commutes with all other generators. |
### set\_sector
set\_sector(
self: ,
sector: Sequence\[int]
) -> None
Sets the symmetry sector coefficients.
**Parameters:**
| Name | Type | Description | Default |
| -------- | --------------- | ---------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `sector` | `Sequence[int]` | (Sequence\[int]): Symmetry sector coefficients, each is 1 or -1. | *required* |
### map
map(
self: ,
fermion\_op: FermionOperator,
args: Any = (),
is\_invariant: bool = False,
kwargs: Any =
) -> QubitOperator
Maps the given fermionic operator to qubits operator by using the
mapper's method, and subsequently by tapering off qubits according to Z2
symmetries.
**Parameters:**
| Name | Type | Description | Default |
| -------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `fermion_op` | `FermionOperator` | A fermionic operator. | *required* |
| `args` | `Any` | | () |
| `is_invariant` | `bool` | If `False`, the operator is not necessarily in the symmetry subspace, and thus gets projected onto it before tapering. | False |
| `kwargs` | `Any` | | |
**Returns:**
* **Type:** `QubitOperator`
* The mapped qubits operator.
### get\_num\_qubits
get\_num\_qubits(
self: ,
problem: FermionHamiltonianProblem
) -> int
Gets the number of qubits after mapping the given problem into qubits space.
**Parameters:**
| Name | Type | Description | Default |
| --------- | --------------------------- | -------------------- | ---------- |
| `self` | \`\` | | *required* |
| `problem` | `FermionHamiltonianProblem` | The fermion problem. | *required* |
**Returns:**
* **Type:** `int`
* The number of qubits.
### from\_problem
from\_problem(
cls: ,
problem: FermionHamiltonianProblem,
method: MappingMethod = MappingMethod.JORDAN\_WIGNER,
sector\_from\_hartree\_fock: bool = True,
tol: float = 1e-14
) -> Z2SymTaperMapper
Initializes a `Z2SymTaperMapper` object from a fermion problem (i.e. computing
the Z2 symmetries from the problem definition).
**Parameters:**
| Name | Type | Description | Default |
| -------------------------- | --------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------- |
| `cls` | \`\` | | *required* |
| `problem` | `FermionHamiltonianProblem` | The fermion problem. | *required* |
| `method` | `MappingMethod` | The mapping method. | MappingMethod.JORDAN\_WIGNER |
| `sector_from_hartree_fock` | `bool` | Whether to compute the symmetry sector coefficients according to the Hartree-Fock state. | True |
| `tol` | `float` | Tolerance for trimming off terms. | 1e-14 |
**Returns:**
* **Type:** `Z2SymTaperMapper`
* The Z2 symmetries taper mapper.
Members:
| Name | Description |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `FermionToQubitMapper` | Mapper between fermionic operators to qubits operators, using one of the supported mapping methods (see `MappingMethod`). |
| `FermionHamiltonianProblem` | Defines an electronic-structure problem using a Fermionic operator and electron count. |
| `get_hf_fermion_op` | Constructs a fermion operator that creates the Hartree-Fock reference state in block-spin ordering. |
| `get_hf_state` | Computes the qubits state after applying the Hartree-Fock operator defined by the given problem and mapper. |
## FermionToQubitMapper
Mapper between fermionic operators to qubits operators, using one of the supported
mapping methods (see `MappingMethod`).
**Methods:**
| Name | Description |
| ----------------------------------- | ---------------------------------------------------------------------------------------- |
| [map](#map) | Maps the given fermionic operator to a qubits operator using the mapper's configuration. |
| [get\_num\_qubits](#get_num_qubits) | Gets the number of qubits after mapping the given problem into qubits space. |
**Attributes:**
| Name | Type | Description |
| -------- | --------------- | ------------------- |
| `method` | `MappingMethod` | The mapping method. |
### map
map(
self: ,
fermion\_op: FermionOperator,
args: Any = (),
kwargs: Any =
) -> QubitOperator
Maps the given fermionic operator to a qubits operator using the mapper's
configuration.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ----------------- | --------------------- | ---------- |
| `self` | \`\` | | *required* |
| `fermion_op` | `FermionOperator` | A fermionic operator. | *required* |
| `args` | `Any` | | () |
| `kwargs` | `Any` | | |
**Returns:**
* **Type:** `QubitOperator`
* The mapped qubits operator.
### get\_num\_qubits
get\_num\_qubits(
self: ,
problem: FermionHamiltonianProblem
) -> int
Gets the number of qubits after mapping the given problem into qubits space.
**Parameters:**
| Name | Type | Description | Default |
| --------- | --------------------------- | -------------------- | ---------- |
| `self` | \`\` | | *required* |
| `problem` | `FermionHamiltonianProblem` | The fermion problem. | *required* |
**Returns:**
* **Type:** `int`
* The number of qubits.
## FermionHamiltonianProblem
Defines an electronic-structure problem using a Fermionic operator and electron count.
Can also be constructed from a `MolecularData` object using the `from_molecule`
method.
**Methods:**
| Name | Description |
| -------------------------------- | -------------------------------------------------------------- |
| [from\_molecule](#from_molecule) | Constructs a `FermionHamiltonianProblem` from a molecule data. |
**Attributes:**
| Name | Type | Description |
| --------------------- | ----------------- | ----------------------------------------------------------------------------------- |
| `occupied_alpha` | `list[int]` | |
| `virtual_alpha` | `list[int]` | |
| `occupied_beta` | `list[int]` | |
| `virtual_beta` | `list[int]` | |
| `occupied` | `list[int]` | |
| `virtual` | `list[int]` | |
| `fermion_hamiltonian` | `FermionOperator` | The fermionic hamiltonian of the problem. Assumed to be in the block-spin labeling. |
| `n_orbitals` | `int` | Number of spatial orbitals. |
| `n_alpha` | `int` | Number of alpha particles. |
| `n_beta` | `int` | Number of beta particles. |
| `n_particles` | `tuple[int, int]` | Number of alpha and beta particles. |
### from\_molecule
from\_molecule(
cls: ,
molecule: MolecularData,
first\_active\_index: int = 0,
remove\_orbitals: Sequence\[int] | None = None,
op\_compression\_tol: float = 1e-13
) -> FermionHamiltonianProblem
Constructs a `FermionHamiltonianProblem` from a molecule data.
**Parameters:**
| Name | Type | Description | Default |
| -------------------- | ----------------------- | ---------------------------------------------------------------- | ---------- |
| `cls` | \`\` | | *required* |
| `molecule` | `MolecularData` | The molecule data. | *required* |
| `first_active_index` | `int` | The first active index, indicates all prior indices are freezed. | 0 |
| `remove_orbitals` | `Sequence[int] \| None` | Active indices to be removed. | None |
| `op_compression_tol` | `float` | Tolerance for trimming the fermion operator. | 1e-13 |
**Returns:**
* **Type:** `FermionHamiltonianProblem`
* The fermion hamiltonian problem.
### get\_hf\_fermion\_op
get\_hf\_fermion\_op(
problem: FermionHamiltonianProblem
) -> FermionOperator
Constructs a fermion operator that creates the Hartree-Fock reference state in
block-spin ordering.
**Parameters:**
| Name | Type | Description | Default |
| --------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `problem` | `FermionHamiltonianProblem` | The fermion problem. The Hartree-Fock fermion operator depends only on the number of spatial orbitals and the number of alpha and beta particles. | *required* |
**Returns:**
* **Type:** `FermionOperator`
* The Hartree-Fock fermion operator.
### get\_hf\_state
get\_hf\_state(
problem: FermionHamiltonianProblem,
mapper: FermionToQubitMapper
) -> list\[bool]
Computes the qubits state after applying the Hartree-Fock operator defined by the
given problem and mapper.
The Qmod function `prepare_basis_state` can be used on the returned value to
allocate and initialize the qubits array.
**Parameters:**
| Name | Type | Description | Default |
| --------- | --------------------------- | ---------------------------------------------------- | ---------- |
| `problem` | `FermionHamiltonianProblem` | The fermion problem. | *required* |
| `mapper` | `FermionToQubitMapper` | The mapper from fermion operator to qubits operator. | *required* |
**Returns:**
* **Type:** `list[bool]`
* The qubits state, given as a list of boolean values for each qubit.
Members:
| Name | Description |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `FermionToQubitMapper` | Mapper between fermionic operators to qubits operators, using one of the supported mapping methods (see `MappingMethod`). |
| `FermionHamiltonianProblem` | Defines an electronic-structure problem using a Fermionic operator and electron count. |
| `SparsePauliOp` | Represents a collection of sparse Pauli operators. |
| `get_ucc_hamiltonians` | Computes the UCC hamiltonians of the given problem in the desired excitations, using the given mapper. |
| `get_excitations` | Gets all the possible excitations of the given problem according to the given number of excitations, preserving the particles spin. |
## FermionToQubitMapper
Mapper between fermionic operators to qubits operators, using one of the supported
mapping methods (see `MappingMethod`).
**Methods:**
| Name | Description |
| ----------------------------------- | ---------------------------------------------------------------------------------------- |
| [map](#map) | Maps the given fermionic operator to a qubits operator using the mapper's configuration. |
| [get\_num\_qubits](#get_num_qubits) | Gets the number of qubits after mapping the given problem into qubits space. |
**Attributes:**
| Name | Type | Description |
| -------- | --------------- | ------------------- |
| `method` | `MappingMethod` | The mapping method. |
### map
map(
self: ,
fermion\_op: FermionOperator,
args: Any = (),
kwargs: Any =
) -> QubitOperator
Maps the given fermionic operator to a qubits operator using the mapper's
configuration.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ----------------- | --------------------- | ---------- |
| `self` | \`\` | | *required* |
| `fermion_op` | `FermionOperator` | A fermionic operator. | *required* |
| `args` | `Any` | | () |
| `kwargs` | `Any` | | |
**Returns:**
* **Type:** `QubitOperator`
* The mapped qubits operator.
### get\_num\_qubits
get\_num\_qubits(
self: ,
problem: FermionHamiltonianProblem
) -> int
Gets the number of qubits after mapping the given problem into qubits space.
**Parameters:**
| Name | Type | Description | Default |
| --------- | --------------------------- | -------------------- | ---------- |
| `self` | \`\` | | *required* |
| `problem` | `FermionHamiltonianProblem` | The fermion problem. | *required* |
**Returns:**
* **Type:** `int`
* The number of qubits.
## FermionHamiltonianProblem
Defines an electronic-structure problem using a Fermionic operator and electron count.
Can also be constructed from a `MolecularData` object using the `from_molecule`
method.
**Methods:**
| Name | Description |
| -------------------------------- | -------------------------------------------------------------- |
| [from\_molecule](#from_molecule) | Constructs a `FermionHamiltonianProblem` from a molecule data. |
**Attributes:**
| Name | Type | Description |
| --------------------- | ----------------- | ----------------------------------------------------------------------------------- |
| `occupied_alpha` | `list[int]` | |
| `virtual_alpha` | `list[int]` | |
| `occupied_beta` | `list[int]` | |
| `virtual_beta` | `list[int]` | |
| `occupied` | `list[int]` | |
| `virtual` | `list[int]` | |
| `fermion_hamiltonian` | `FermionOperator` | The fermionic hamiltonian of the problem. Assumed to be in the block-spin labeling. |
| `n_orbitals` | `int` | Number of spatial orbitals. |
| `n_alpha` | `int` | Number of alpha particles. |
| `n_beta` | `int` | Number of beta particles. |
| `n_particles` | `tuple[int, int]` | Number of alpha and beta particles. |
### from\_molecule
from\_molecule(
cls: ,
molecule: MolecularData,
first\_active\_index: int = 0,
remove\_orbitals: Sequence\[int] | None = None,
op\_compression\_tol: float = 1e-13
) -> FermionHamiltonianProblem
Constructs a `FermionHamiltonianProblem` from a molecule data.
**Parameters:**
| Name | Type | Description | Default |
| -------------------- | ----------------------- | ---------------------------------------------------------------- | ---------- |
| `cls` | \`\` | | *required* |
| `molecule` | `MolecularData` | The molecule data. | *required* |
| `first_active_index` | `int` | The first active index, indicates all prior indices are freezed. | 0 |
| `remove_orbitals` | `Sequence[int] \| None` | Active indices to be removed. | None |
| `op_compression_tol` | `float` | Tolerance for trimming the fermion operator. | 1e-13 |
**Returns:**
* **Type:** `FermionHamiltonianProblem`
* The fermion hamiltonian problem.
## SparsePauliOp
Represents a collection of sparse Pauli operators.
**Methods:**
| Name | Description |
| --------------------------------------------------------- | ----------- |
| [get\_tuples\_representation](#get_tuples_representation) | |
**Attributes:**
| Name | Type | Description |
| ------------ | ------------------------- | ----------------------------------------------------------------------------------------------- |
| `terms` | `CArray[SparsePauliTerm]` | The list of chosen sparse Pauli terms, corresponds to a product of them. (See: SparsePauliTerm) |
| `num_qubits` | `CInt` | The number of qubits in the Hamiltonian. |
### get\_tuples\_representation
get\_tuples\_representation(
self: ,
reverse\_order: bool
) -> list\[tuple\[str, int | float | complex]]
**Parameters:**
| Name | Type | Description | Default |
| --------------- | ------ | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `reverse_order` | `bool` | | *required* |
### get\_ucc\_hamiltonians
get\_ucc\_hamiltonians(
problem: FermionHamiltonianProblem,
mapper: FermionToQubitMapper,
excitations: int | Sequence\[int]
) -> list\[SparsePauliOp]
Computes the UCC hamiltonians of the given problem in the desired excitations,
using the given mapper.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | --------------------------------------------------- | ---------- |
| `problem` | `FermionHamiltonianProblem` | The fermion problem. | *required* |
| `mapper` | `FermionToQubitMapper` | The mapper from fermion to qubits operators. | *required* |
| `excitations` | `int \| Sequence[int]` | A single desired excitation or an excitations list. | *required* |
**Returns:**
* **Type:** `list[SparsePauliOp]`
* The UCC hamiltonians.
### get\_excitations
get\_excitations(
problem: FermionHamiltonianProblem,
num\_excitations: int
) -> set\[tuple\[tuple\[int, ...], tuple\[int, ...]]]
Gets all the possible excitations of the given problem according to the
given number of excitations, preserving the particles spin.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | --------------------------- | ---------------------- | ---------- |
| `problem` | `FermionHamiltonianProblem` | The fermion problem. | *required* |
| `num_excitations` | `int` | Number of excitations. | *required* |
**Returns:**
* **Type:** `set[tuple[tuple[int, ...], tuple[int, ...]]]`
* A set of all possible excitations, specified as a pair of source and target indices.
Members:
| Name | Description |
| ---------------------- | ----------------------------------------------------------------------------------------------- |
| `DFTState` | Post-DFT handle returned to the user, recording the resolved spin mode, functional, and method. |
| `EmbeddingCalculator` | User-facing embedding driver, backed by queued backend jobs. |
| `EmbeddingConfig` | Embedding-method parameters. |
| `MeanFieldData` | Fragment / environment densities, electron counts, and active-MO basis. |
| `MoleculeSpec` | User-facing molecular description. |
| `QuantumData` | Solver-facing bundle: embedded + physical Hamiltonians and scalars. |
| `SpinMode` | Which mean-field treatment the backend should use. |
| `ValidationCheck` | Validation diagnostics the embedding pipeline can run. |
| `embedding_calculator` | User-facing API for projection-based WF-in-DFT embedding. |
| `chemistry_job` | Detached handle for a long-running chemistry backend job. |
## DFTState
Post-DFT handle returned to the user, recording the resolved spin mode,
functional, and method. Threaded back into later stages.
**Attributes:**
| Name | Type | Description |
| --------------- | ------------------- | ----------- |
| `spin_mode` | `SpinMode` | |
| `xc_functional` | `str` | |
| `method` | `CalculationMethod` | |
## EmbeddingCalculator
User-facing embedding driver, backed by queued backend jobs.
**Methods:**
| Name | Description |
| ----------------------------------------------- | ------------------------------------------------------------- |
| [run\_dft](#run_dft) | Run the full-system mean field and cache the result. |
| [submit\_dft](#submit_dft) | Enqueue the full-system mean field and return a job handle. |
| [run\_dft\_embedding](#run_dft_embedding) | Run the full embedding pipeline in one backend call. |
| [submit\_dft\_embedding](#submit_dft_embedding) | Enqueue the full embedding pipeline and return a job handle. |
| [run\_validations](#run_validations) | Run a batch of post-hoc validations in a single backend call. |
**Attributes:**
| Name | Type | Description |
| --------------------- | ----------------------------- | ----------- |
| `spec` | | |
| `spin_mode` | | |
| `auto_validations` | `tuple[ValidationCheck, ...]` | |
| `validation_results` | `ValidationResults` | |
| `config` | `EmbeddingConfig \| None` | |
| `effective_spin_mode` | `SpinMode` | |
### run\_dft
run\_dft(
self: ,
xc\_functional: str = 'B3LYP',
method: CalculationMethod = CalculationMethod.DFT
) -> DFTState
Run the full-system mean field and cache the result.
Blocks until the backend job finishes. For a long run prefer
[submit\_dft()](#submit_dft), which returns a handle you can poll later.
`method` selects DFT (default, using `xc_functional`) or Hartree-Fock
(`xc_functional` is then ignored).
**Parameters:**
| Name | Type | Description | Default |
| --------------- | ------------------- | ----------- | --------------------- |
| `self` | \`\` | | *required* |
| `xc_functional` | `str` | | 'B3LYP' |
| `method` | `CalculationMethod` | | CalculationMethod.DFT |
### submit\_dft
submit\_dft(
self: ,
xc\_functional: str = 'B3LYP',
method: CalculationMethod = CalculationMethod.DFT
) -> ChemistryJob\[DFTState]
Enqueue the full-system mean field and return a job handle.
The non-blocking counterpart to [run\_dft()](#run_dft): the DFT runs
server-side (it can take hours) while the client is free to exit. Call
`.result()` on the returned handle to fetch the [DFTState](#dftstate) once
ready -- doing so also caches the state for [run\_dft\_embedding()](#run_dft_embedding),
exactly as [run\_dft()](#run_dft) does.
**Parameters:**
| Name | Type | Description | Default |
| --------------- | ------------------- | ----------- | --------------------- |
| `self` | \`\` | | *required* |
| `xc_functional` | `str` | | 'B3LYP' |
| `method` | `CalculationMethod` | | CalculationMethod.DFT |
### run\_dft\_embedding
run\_dft\_embedding(
self: ,
config: EmbeddingConfig
) -> tuple\[MeanFieldData, QuantumData]
Run the full embedding pipeline in one backend call.
Blocks until the backend job finishes. For a long run prefer
[submit\_dft\_embedding()](#submit_dft_embedding), which returns a handle you can poll later.
Reuses the cached `DFTState` from a prior `run_dft` call if present;
otherwise the backend runs the full-system DFT first using
`config.xc_functional`. Auto-validations registered at construction are
computed in the same call and stored on `self.validation_results`.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ----------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `config` | `EmbeddingConfig` | | *required* |
### submit\_dft\_embedding
submit\_dft\_embedding(
self: ,
config: EmbeddingConfig
) -> ChemistryJob\[tuple\[MeanFieldData, QuantumData]]
Enqueue the full embedding pipeline and return a job handle.
The non-blocking counterpart to [run\_dft\_embedding()](#run_dft_embedding). Call
`.result()` on the returned handle to fetch the
`(MeanFieldData, QuantumData)` tuple once ready; doing so caches the
embedding state for subsequent [run\_validations()](#run_validations) calls and emits
any `n_active_virtuals` warning, exactly as the blocking method does.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ----------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `config` | `EmbeddingConfig` | | *required* |
### run\_validations
run\_validations(
self: ,
checks: Sequence\[ValidationCheck]
) -> ValidationResults
Run a batch of post-hoc validations in a single backend call.
**Parameters:**
| Name | Type | Description | Default |
| -------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `checks` | `Sequence[ValidationCheck]` | | *required* |
## EmbeddingConfig
Embedding-method parameters.
**Attributes:**
| Name | Type | Description |
| ------------------- | ------------------- | ----------- |
| `fragment_atoms` | `tuple[int, ...]` | |
| `method` | `CalculationMethod` | |
| `xc_functional` | `str` | |
| `mu` | `float` | |
| `w_cut` | `float` | |
| `sv_tol` | `float` | |
| `n_active_virtuals` | `int \| None` | |
| `freeze_core` | `bool` | |
## MeanFieldData
Fragment / environment densities, electron counts, and active-MO basis.
**Attributes:**
| Name | Type | Description |
| ---------------- | --------------------------------------------- | ----------- |
| `D_A` | `np.ndarray` | |
| `D_B` | `np.ndarray` | |
| `atom_indices` | `tuple[int, ...]` | |
| `n_electrons_A` | `int` | |
| `C_active` | `np.ndarray \| tuple[np.ndarray, np.ndarray]` | |
| `E_DFT_fragment` | `float` | |
| `n_electrons_B` | `int` | |
## MoleculeSpec
User-facing molecular description.
**Methods:**
| Name | Description |
| --------------------------------- | -------------------------------------- |
| [from\_pdb\_file](#from_pdb_file) | Build a spec from a local `.pdb` file. |
| [from\_xyz\_file](#from_xyz_file) | Build a spec from a local `.xyz` file. |
**Attributes:**
| Name | Type | Description |
| -------- | ----- | ----------- |
| `atom` | `str` | |
| `basis` | `str` | |
| `charge` | `int` | |
| `spin` | `int` | |
| `unit` | `str` | |
### from\_pdb\_file
from\_pdb\_file(
cls: ,
path: str | Path,
basis: str = 'cc-pVDZ',
charge: int = 0,
spin: int = 0,
unit: str = 'Angstrom'
) -> MoleculeSpec
Build a spec from a local `.pdb` file.
The file is read on the client; only its contents are sent to the
backend (the backend never opens paths). The remaining arguments mirror
the `MoleculeSpec` fields.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `path` | `str \| Path` | | *required* |
| `basis` | `str` | | 'cc-pVDZ' |
| `charge` | `int` | | 0 |
| `spin` | `int` | | 0 |
| `unit` | `str` | | 'Angstrom' |
### from\_xyz\_file
from\_xyz\_file(
cls: ,
path: str | Path,
basis: str = 'cc-pVDZ',
charge: int = 0,
spin: int = 0,
unit: str = 'Angstrom'
) -> MoleculeSpec
Build a spec from a local `.xyz` file.
The file is read on the client; only its contents are sent to the
backend (the backend never opens paths). The remaining arguments mirror
the `MoleculeSpec` fields.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `path` | `str \| Path` | | *required* |
| `basis` | `str` | | 'cc-pVDZ' |
| `charge` | `int` | | 0 |
| `spin` | `int` | | 0 |
| `unit` | `str` | | 'Angstrom' |
## QuantumData
Solver-facing bundle: embedded + physical Hamiltonians and scalars.
**Attributes:**
| Name | Type | Description |
| ------------------ | ----------------- | ----------- |
| `hamiltonian_emb` | `FermionOperator` | |
| `hamiltonian_phys` | `FermionOperator` | |
| `n_particles` | `tuple[int, int]` | |
| `env_correction` | `float` | |
## SpinMode
Which mean-field treatment the backend should use.
**Attributes:**
| Name | Type | Description |
| -------------- | ---------------- | ----------- |
| `AUTO` | `'auto'` | |
| `RESTRICTED` | `'restricted'` | |
| `UNRESTRICTED` | `'unrestricted'` | |
## ValidationCheck
Validation diagnostics the embedding pipeline can run.
**Attributes:**
| Name | Type | Description |
| ----------------------- | ------------------------- | ----------- |
| `DFT_IN_DFT` | `'dft_in_dft'` | |
| `FCI_ACTIVE_SPACE` | `'fci_active_space'` | |
| `PROBABILITY_LEAK` | `'probability_leak'` | |
| `TRACE_CONSERVATION` | `'trace_conservation'` | |
| `GEOMETRY_PERTURBATION` | `'geometry_perturbation'` | |
### embedding\_calculator
User-facing API for projection-based WF-in-DFT embedding.
Mirrors the local prototype: users build a [MoleculeSpec](#moleculespec) and an
[EmbeddingConfig](#embeddingconfig), then drive the pipeline through
[EmbeddingCalculator](#embeddingcalculator). Under the hood every stage is a queued backend job
(the heavy pyscf / openfermion chemistry runs server-side and never ships to the
client). The calculator exchanges the serializable wire models defined in
`classiq.interface.applications.chemistry.embedding` with the backend and
rehydrates the results into the dataclasses below.
The embedded / physical Hamiltonians come back as real
`openfermion.FermionOperator` objects, ready to feed into a quantum solver.
**Methods:**
| Name | Description |
| ----------- | ----------- |
| [run](#run) | |
**Attributes:**
| Name | Type | Description |
| ------------------- | ---- | ----------- |
| `ValidationResults` | | |
#### run
run(
coro: Awaitable\[T]
) -> T
**Parameters:**
| Name | Type | Description | Default |
| ------ | -------------- | ----------- | ---------- |
| `coro` | `Awaitable[T]` | | *required* |
#### embedding\_calculator.ArrayModel
A numpy array flattened to `(shape, data)` for JSON transport.
Real-valued only (every array crossing the embedding boundary -- densities,
MO coefficients, overlaps -- is real). Rebuild with
`np.asarray(data).reshape(shape)`.
**Attributes:**
| Name | Type | Description |
| ------- | ---------------------- | ----------- |
| `shape` | `list[NonNegativeInt]` | |
| `data` | `list[float]` | |
#### embedding\_calculator.CalculationMethod
Electronic-structure method for the mean-field stage.
`DFT` runs Kohn-Sham with the configured `xc_functional`; `HF` runs
Hartree-Fock (realized by setting the PySCF SCF object's `xc` to `"HF"`,
which makes `RKS`/`UKS` reproduce `RHF`/`UHF` exactly). `xc_functional`
is ignored when `method` is `HF`.
**Attributes:**
| Name | Type | Description |
| ----- | ------- | ----------- |
| `DFT` | `'dft'` | |
| `HF` | `'hf'` | |
#### embedding\_calculator.DFTStateModel
Serializable `DFTState` -- the serialized `Mole` + SCF bundle.
**Attributes:**
| Name | Type | Description |
| --------------- | ------------------- | ----------- |
| `mol_dumps` | `str` | |
| `scf` | `ScfPayload` | |
| `spin_mode` | `SpinMode` | |
| `xc_functional` | `str` | |
| `method` | `CalculationMethod` | |
#### embedding\_calculator.EmbeddingConfigModel
Serializable `EmbeddingConfig` (all primitives).
**Attributes:**
| Name | Type | Description |
| ------------------- | ---------------------- | ----------- |
| `fragment_atoms` | `list[NonNegativeInt]` | |
| `method` | `CalculationMethod` | |
| `xc_functional` | `str` | |
| `mu` | `float` | |
| `w_cut` | `float` | |
| `sv_tol` | `float` | |
| `n_active_virtuals` | `int \| None` | |
| `freeze_core` | `bool` | |
#### embedding\_calculator.FermionOperatorModel
Serializable `openfermion.FermionOperator` (its term -> coefficient map).
**Attributes:**
| Name | Type | Description |
| ------- | ------------------- | ----------- |
| `terms` | `list[FermionTerm]` | |
#### embedding\_calculator.MeanFieldDataModel
Serializable `MeanFieldData`.
`c_active` holds one `ArrayModel` for the restricted backend or two
(alpha, beta) for the unrestricted backend; `c_active_is_tuple` records
which so it can be rebuilt to the right shape.
**Attributes:**
| Name | Type | Description |
| ------------------- | ------------------ | ----------- |
| `atom_indices` | `list[int]` | |
| `d_a` | `ArrayModel` | |
| `n_electrons_a` | `int` | |
| `c_active` | `list[ArrayModel]` | |
| `c_active_is_tuple` | `bool` | |
| `e_dft_fragment` | `float` | |
| `d_b` | `ArrayModel` | |
| `n_electrons_b` | `int` | |
#### embedding\_calculator.MoleculeSpecModel
Serializable `MoleculeSpec`.
Exactly one of `atom` or `mol_dumps` is populated. `mol_dumps` carries a
pre-built `pyscf.gto.Mole` serialized via `Mole.dumps()`.
**Attributes:**
| Name | Type | Description |
| ----------- | ------------- | ----------- |
| `atom` | `str \| None` | |
| `basis` | `str` | |
| `charge` | `int` | |
| `spin` | `int` | |
| `unit` | `str` | |
| `mol_dumps` | `str \| None` | |
#### embedding\_calculator.QuantumDataModel
Serializable `QuantumData` -- the two fermion Hamiltonians + scalars.
**Attributes:**
| Name | Type | Description |
| ------------------ | ---------------------- | ----------- |
| `hamiltonian_emb` | `FermionOperatorModel` | |
| `hamiltonian_phys` | `FermionOperatorModel` | |
| `n_particles` | `tuple[int, int]` | |
| `env_correction` | `float` | |
#### embedding\_calculator.SpinMode
Which mean-field treatment the backend should use.
**Attributes:**
| Name | Type | Description |
| -------------- | ---------------- | ----------- |
| `AUTO` | `'auto'` | |
| `RESTRICTED` | `'restricted'` | |
| `UNRESTRICTED` | `'unrestricted'` | |
#### embedding\_calculator.ValidationCheck
Validation diagnostics the embedding pipeline can run.
**Attributes:**
| Name | Type | Description |
| ----------------------- | ------------------------- | ----------- |
| `DFT_IN_DFT` | `'dft_in_dft'` | |
| `FCI_ACTIVE_SPACE` | `'fci_active_space'` | |
| `PROBABILITY_LEAK` | `'probability_leak'` | |
| `TRACE_CONSERVATION` | `'trace_conservation'` | |
| `GEOMETRY_PERTURBATION` | `'geometry_perturbation'` | |
#### embedding\_calculator.ValidationResultModel
One validation check's outcome: a pass/fail flag plus a JSON-safe info dict.
**Attributes:**
| Name | Type | Description |
| -------- | ---------------- | ----------- |
| `passed` | `bool` | |
| `info` | `dict[str, Any]` | |
#### embedding\_calculator.RunDftEmbeddingInput
**Attributes:**
| Name | Type | Description |
| ------------------ | ----------------------- | ----------- |
| `spec` | `MoleculeSpecModel` | |
| `config` | `EmbeddingConfigModel` | |
| `spin_mode` | `SpinMode` | |
| `dft_state` | `DFTStateModel \| None` | |
| `auto_validations` | `list[ValidationCheck]` | |
#### embedding\_calculator.RunDftEmbeddingOutput
**Attributes:**
| Name | Type | Description |
| --------------------------- | ---------------------------------------------- | ----------- |
| `dft_state` | `DFTStateModel` | |
| `mean_field_data` | `MeanFieldDataModel` | |
| `quantum_data` | `QuantumDataModel` | |
| `validation_results` | `dict[ValidationCheck, ValidationResultModel]` | |
| `n_active_virtuals_warning` | `str \| None` | |
#### embedding\_calculator.RunDftInput
**Attributes:**
| Name | Type | Description |
| --------------- | ------------------- | ----------- |
| `spec` | `MoleculeSpecModel` | |
| `xc_functional` | `str` | |
| `spin_mode` | `SpinMode` | |
| `method` | `CalculationMethod` | |
#### embedding\_calculator.RunDftOutput
**Attributes:**
| Name | Type | Description |
| ----------- | --------------- | ----------- |
| `dft_state` | `DFTStateModel` | |
#### embedding\_calculator.RunValidationsInput
**Attributes:**
| Name | Type | Description |
| ----------------- | ----------------------- | ----------- |
| `dft_state` | `DFTStateModel` | |
| `mean_field_data` | `MeanFieldDataModel` | |
| `quantum_data` | `QuantumDataModel` | |
| `config` | `EmbeddingConfigModel` | |
| `checks` | `list[ValidationCheck]` | |
#### embedding\_calculator.ApiWrapper
**Methods:**
| Name | Description |
| ---------------------------------------------------------------------------------------- | ----------- |
| [call\_get\_benchmark\_classes](#call_get_benchmark_classes) | |
| [call\_submit\_benchmark](#call_submit_benchmark) | |
| [call\_get\_benchmark\_results](#call_get_benchmark_results) | |
| [call\_list\_benchmark\_sessions](#call_list_benchmark_sessions) | |
| [call\_cancel\_benchmark\_session](#call_cancel_benchmark_session) | |
| [call\_generation\_task](#call_generation_task) | |
| [call\_transpilation\_task](#call_transpilation_task) | |
| [call\_assign\_parameters\_task](#call_assign_parameters_task) | |
| [call\_export\_task](#call_export_task) | |
| [call\_transpiled\_circuit\_metrics\_task](#call_transpiled_circuit_metrics_task) | |
| [call\_circuit\_metrics\_task](#call_circuit_metrics_task) | |
| [call\_qasm\_to\_qmod\_task](#call_qasm_to_qmod_task) | |
| [submit\_chemistry\_run\_dft\_task](#submit_chemistry_run_dft_task) | |
| [submit\_chemistry\_run\_dft\_embedding\_task](#submit_chemistry_run_dft_embedding_task) | |
| [call\_chemistry\_run\_dft\_task](#call_chemistry_run_dft_task) | |
| [call\_chemistry\_run\_dft\_embedding\_task](#call_chemistry_run_dft_embedding_task) | |
| [call\_chemistry\_run\_validations\_task](#call_chemistry_run_validations_task) | |
| [call\_get\_visual\_model](#call_get_visual_model) | |
| [call\_visualization\_task](#call_visualization_task) | |
| [call\_create\_execution\_session](#call_create_execution_session) | |
| [call\_create\_openqasm\_execution\_session](#call_create_openqasm_execution_session) | |
| [call\_close\_execution\_session](#call_close_execution_session) | |
| [call\_create\_session\_job](#call_create_session_job) | |
| [call\_convert\_quantum\_program](#call_convert_quantum_program) | |
| [call\_execute\_execution\_input](#call_execute_execution_input) | |
| [call\_estimate\_sample\_cost](#call_estimate_sample_cost) | |
| [call\_get\_execution\_job\_details](#call_get_execution_job_details) | |
| [call\_get\_execution\_job\_result](#call_get_execution_job_result) | |
| [call\_get\_submitted\_circuits](#call_get_submitted_circuits) | |
| [call\_patch\_execution\_job](#call_patch_execution_job) | |
| [call\_cancel\_execution\_job](#call_cancel_execution_job) | |
| [call\_query\_execution\_jobs](#call_query_execution_jobs) | |
| [call\_query\_synthesis\_actions](#call_query_synthesis_actions) | |
| [call\_analysis\_task](#call_analysis_task) | |
| [get\_generated\_circuit\_from\_qasm](#get_generated_circuit_from_qasm) | |
| [get\_analyzer\_app\_data](#get_analyzer_app_data) | |
| [call\_rb\_analysis\_task](#call_rb_analysis_task) | |
| [call\_hardware\_connectivity\_task](#call_hardware_connectivity_task) | |
| [call\_table\_graphs\_task](#call_table_graphs_task) | |
| [call\_available\_devices\_task](#call_available_devices_task) | |
| [call\_get\_all\_hardware\_devices](#call_get_all_hardware_devices) | |
| [call\_get\_all\_budgets](#call_get_all_budgets) | |
| [call\_set\_budget\_limit](#call_set_budget_limit) | |
| [call\_clear\_budget\_limit](#call_clear_budget_limit) | |
| [call\_initialize\_logical\_noise](#call_initialize_logical_noise) | |
| [call\_get\_logical\_noise](#call_get_logical_noise) | |
| [call\_remove\_logical\_noise](#call_remove_logical_noise) | |
##### call\_get\_benchmark\_classes
call\_get\_benchmark\_classes(
cls:
) -> dict\[BenchmarkClass, BenchmarkClassMetadata]
**Parameters:**
| Name | Type | Description | Default |
| ----- | ---- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
##### call\_submit\_benchmark
call\_submit\_benchmark(
cls: ,
request: BenchmarkRequest,
http\_client: httpx.AsyncClient | None = None
) -> BenchmarkSession
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `request` | `BenchmarkRequest` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_get\_benchmark\_results
call\_get\_benchmark\_results(
cls: ,
session: BenchmarkSession,
http\_client: httpx.AsyncClient | None = None
) -> BenchmarkSession
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `session` | `BenchmarkSession` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_list\_benchmark\_sessions
call\_list\_benchmark\_sessions(
cls: ,
http\_client: httpx.AsyncClient | None = None
) -> list\[BenchmarkSession]
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_cancel\_benchmark\_session
call\_cancel\_benchmark\_session(
cls: ,
session\_id: str,
http\_client: httpx.AsyncClient | None = None
) -> None
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `session_id` | `str` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_generation\_task
call\_generation\_task(
cls: ,
model: Model,
http\_client: httpx.AsyncClient | None = None
) -> generator\_result.QuantumProgram
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `model` | `Model` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_transpilation\_task
call\_transpilation\_task(
cls: ,
params: TranspilationParams,
http\_client: httpx.AsyncClient | None = None
) -> generator\_result.QuantumProgram
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `TranspilationParams` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_assign\_parameters\_task
call\_assign\_parameters\_task(
cls: ,
params: ParameterAssignmentsParams,
http\_client: httpx.AsyncClient | None = None
) -> generator\_result.QuantumProgram
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ---------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `ParameterAssignmentsParams` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_export\_task
call\_export\_task(
cls: ,
params: ExportParams,
http\_client: httpx.AsyncClient | None = None
) -> TargetCode
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `ExportParams` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_transpiled\_circuit\_metrics\_task
call\_transpiled\_circuit\_metrics\_task(
cls: ,
program: generator\_result.QuantumProgram,
http\_client: httpx.AsyncClient | None = None
) -> ProgramData
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `program` | `generator_result.QuantumProgram` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_circuit\_metrics\_task
call\_circuit\_metrics\_task(
cls: ,
program: generator\_result.QuantumProgram,
http\_client: httpx.AsyncClient | None = None
) -> CircuitMetrics
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `program` | `generator_result.QuantumProgram` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_qasm\_to\_qmod\_task
call\_qasm\_to\_qmod\_task(
cls: ,
params: QasmToQmodParams,
http\_client: httpx.AsyncClient | None = None
) -> QmodCode
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `QasmToQmodParams` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### submit\_chemistry\_run\_dft\_task
submit\_chemistry\_run\_dft\_task(
cls: ,
params: RunDftInput,
http\_client: httpx.AsyncClient | None = None
) -> JobID
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `RunDftInput` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### submit\_chemistry\_run\_dft\_embedding\_task
submit\_chemistry\_run\_dft\_embedding\_task(
cls: ,
params: RunDftEmbeddingInput,
http\_client: httpx.AsyncClient | None = None
) -> JobID
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `RunDftEmbeddingInput` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_chemistry\_run\_dft\_task
call\_chemistry\_run\_dft\_task(
cls: ,
params: RunDftInput,
http\_client: httpx.AsyncClient | None = None
) -> RunDftOutput
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `RunDftInput` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_chemistry\_run\_dft\_embedding\_task
call\_chemistry\_run\_dft\_embedding\_task(
cls: ,
params: RunDftEmbeddingInput,
http\_client: httpx.AsyncClient | None = None
) -> RunDftEmbeddingOutput
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `RunDftEmbeddingInput` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_chemistry\_run\_validations\_task
call\_chemistry\_run\_validations\_task(
cls: ,
params: RunValidationsInput,
http\_client: httpx.AsyncClient | None = None
) -> RunValidationsOutput
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `RunValidationsInput` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_get\_visual\_model
call\_get\_visual\_model(
cls: ,
program\_id: str,
http\_client: httpx.AsyncClient | None = None
) -> ProgramVisualModel
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `program_id` | `str` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_visualization\_task
call\_visualization\_task(
cls: ,
circuit: generator\_result.QuantumProgram,
http\_client: httpx.AsyncClient | None = None
) -> ProgramVisualModel
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `circuit` | `generator_result.QuantumProgram` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_create\_execution\_session
call\_create\_execution\_session(
cls: ,
circuit: generator\_result.QuantumProgram,
http\_client: httpx.AsyncClient | None = None
) -> str
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `circuit` | `generator_result.QuantumProgram` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_create\_openqasm\_execution\_session
call\_create\_openqasm\_execution\_session(
cls: ,
qasm: str,
execution\_preferences: ExecutionPreferences,
http\_client: httpx.AsyncClient | None = None
) -> str
**Parameters:**
| Name | Type | Description | Default |
| ----------------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `qasm` | `str` | | *required* |
| `execution_preferences` | `ExecutionPreferences` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_close\_execution\_session
call\_close\_execution\_session(
cls: ,
session\_id: str,
http\_client: httpx.AsyncClient | None = None
) -> None
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `session_id` | `str` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_create\_session\_job
call\_create\_session\_job(
cls: ,
session\_id: str,
primitives\_input: PrimitivesInput,
http\_client: httpx.AsyncClient | None = None
) -> execution\_request.ExecutionJobDetails
**Parameters:**
| Name | Type | Description | Default |
| ------------------ | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `session_id` | `str` | | *required* |
| `primitives_input` | `PrimitivesInput` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_convert\_quantum\_program
call\_convert\_quantum\_program(
cls: ,
circuit: generator\_result.QuantumProgram,
http\_client: httpx.AsyncClient | None = None
) -> dict
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `circuit` | `generator_result.QuantumProgram` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_execute\_execution\_input
call\_execute\_execution\_input(
cls: ,
execution\_input: dict,
http\_client: httpx.AsyncClient | None = None
) -> execution\_request.ExecutionJobDetails
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `execution_input` | `dict` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_estimate\_sample\_cost
call\_estimate\_sample\_cost(
cls: ,
execution\_input: dict,
batch\_params: list\[dict] | None = None,
http\_client: httpx.AsyncClient | None = None
) -> dict
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `execution_input` | `dict` | | *required* |
| `batch_params` | `list[dict] \| None` | | None |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_get\_execution\_job\_details
call\_get\_execution\_job\_details(
cls: ,
job\_id: JobID,
http\_client: httpx.AsyncClient | None = None
) -> execution\_request.ExecutionJobDetails
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `job_id` | `JobID` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_get\_execution\_job\_result
call\_get\_execution\_job\_result(
cls: ,
job\_id: JobID,
http\_client: httpx.AsyncClient | None = None
) -> classiq.interface.executor.execution\_result.ExecuteGeneratedCircuitResults
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `job_id` | `JobID` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_get\_submitted\_circuits
call\_get\_submitted\_circuits(
cls: ,
job\_id: JobID,
http\_client: httpx.AsyncClient | None = None
) -> execution\_request.SubmittedCircuitsResponse
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `job_id` | `JobID` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_patch\_execution\_job
call\_patch\_execution\_job(
cls: ,
job\_id: JobID,
name: str,
http\_client: httpx.AsyncClient | None = None
) -> execution\_request.ExecutionJobDetails
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `job_id` | `JobID` | | *required* |
| `name` | `str` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_cancel\_execution\_job
call\_cancel\_execution\_job(
cls: ,
job\_id: JobID,
http\_client: httpx.AsyncClient | None = None
) -> None
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `job_id` | `JobID` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_query\_execution\_jobs
call\_query\_execution\_jobs(
cls: ,
offset: int,
limit: int,
http\_client: httpx.AsyncClient | None = None,
extra\_query\_params: Any =
) -> execution\_request.ExecutionJobsQueryResults
**Parameters:**
| Name | Type | Description | Default |
| -------------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `offset` | `int` | | *required* |
| `limit` | `int` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
| `extra_query_params` | `Any` | | |
##### call\_query\_synthesis\_actions
call\_query\_synthesis\_actions(
cls: ,
offset: int,
limit: int,
http\_client: httpx.AsyncClient | None = None,
extra\_query\_params: Any | None =
) -> SynthesisActionsQueryResults
**Parameters:**
| Name | Type | Description | Default |
| -------------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `offset` | `int` | | *required* |
| `limit` | `int` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
| `extra_query_params` | `Any \| None` | | |
##### call\_analysis\_task
call\_analysis\_task(
cls: ,
params: analysis\_params.AnalysisParams,
http\_client: httpx.AsyncClient | None = None
) -> analysis\_result.Analysis
**Parameters:**
| Name | Type | Description | Default |
| ------------- | -------------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `analysis_params.AnalysisParams` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### get\_generated\_circuit\_from\_qasm
get\_generated\_circuit\_from\_qasm(
cls: ,
params: analysis\_result.QasmCode,
http\_client: httpx.AsyncClient | None = None
) -> generator\_result.QuantumProgram
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `analysis_result.QasmCode` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### get\_analyzer\_app\_data
get\_analyzer\_app\_data(
cls: ,
params: analysis\_result.DataID,
http\_client: httpx.AsyncClient | None = None
) -> generator\_result.QuantumProgram
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `analysis_result.DataID` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_rb\_analysis\_task
call\_rb\_analysis\_task(
cls: ,
params: AnalysisRBParams,
http\_client: httpx.AsyncClient | None = None
) -> analysis\_result.RbResults
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `AnalysisRBParams` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_hardware\_connectivity\_task
call\_hardware\_connectivity\_task(
cls: ,
params: analysis\_params.AnalysisHardwareParams,
http\_client: httpx.AsyncClient | None = None
) -> analysis\_result.GraphResult
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ---------------------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `analysis_params.AnalysisHardwareParams` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_table\_graphs\_task
call\_table\_graphs\_task(
cls: ,
params: analysis\_params.AnalysisHardwareListParams,
http\_client: httpx.AsyncClient | None = None
) -> analysis\_result.GraphResult
**Parameters:**
| Name | Type | Description | Default |
| ------------- | -------------------------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `analysis_params.AnalysisHardwareListParams` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_available\_devices\_task
call\_available\_devices\_task(
cls: ,
params: analysis\_params.AnalysisOptionalDevicesParams,
http\_client: httpx.AsyncClient | None = None
) -> analysis\_result.DevicesResult
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ----------------------------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `analysis_params.AnalysisOptionalDevicesParams` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_get\_all\_hardware\_devices
call\_get\_all\_hardware\_devices(
cls: ,
http\_client: httpx.AsyncClient | None = None
) -> list\[HardwareInformation]
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### call\_get\_all\_budgets
call\_get\_all\_budgets(
cls:
) -> list\[UserBudget]
**Parameters:**
| Name | Type | Description | Default |
| ----- | ---- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
##### call\_set\_budget\_limit
call\_set\_budget\_limit(
cls: ,
provider: str,
budget\_limit: float
) -> UserBudget
**Parameters:**
| Name | Type | Description | Default |
| -------------- | ------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `provider` | `str` | | *required* |
| `budget_limit` | `float` | | *required* |
##### call\_clear\_budget\_limit
call\_clear\_budget\_limit(
cls: ,
provider: str
) -> UserBudget
**Parameters:**
| Name | Type | Description | Default |
| ---------- | ----- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `provider` | `str` | | *required* |
##### call\_initialize\_logical\_noise
call\_initialize\_logical\_noise(
cls: ,
params: InitializeLogicalNoiseParams
) -> None
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------------------------ | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `params` | `InitializeLogicalNoiseParams` | | *required* |
##### call\_get\_logical\_noise
call\_get\_logical\_noise(
cls: ,
name: str
) -> LogicalNoiseParameters
**Parameters:**
| Name | Type | Description | Default |
| ------ | ----- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `name` | `str` | | *required* |
##### call\_remove\_logical\_noise
call\_remove\_logical\_noise(
cls: ,
name: str
) -> None
**Parameters:**
| Name | Type | Description | Default |
| ------ | ----- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `name` | `str` | | *required* |
#### embedding\_calculator.ChemistryJob
**Methods:**
| Name | Description |
| ------------------------------ | --------------------------------------------------------------- |
| [from\_id](#from_id) | Reconnect to a previously submitted job by its id. |
| [status\_async](#status_async) | |
| [result\_async](#result_async) | Wait for the job to finish and return its (transformed) result. |
| [cancel\_async](#cancel_async) | |
**Attributes:**
| Name | Type | Description |
| -------- | ----- | ----------- |
| `id` | `str` | |
| `status` | | |
| `result` | | |
| `cancel` | | |
##### from\_id
from\_id(
cls: ,
id: str,
job\_route: str,
result\_type: type\[pydantic.BaseModel]
) -> ChemistryJob
Reconnect to a previously submitted job by its id.
The result is fetchable while the job's result is still retained by the
backend (see `MAX_KEEP_RESULT`); reconnecting much later may fail.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | -------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `id` | `str` | | *required* |
| `job_route` | `str` | | *required* |
| `result_type` | `type[pydantic.BaseModel]` | | *required* |
##### status\_async
status\_async(
self: ,
\_http\_client: httpx.AsyncClient | None = None
) -> JobStatus
**Parameters:**
| Name | Type | Description | Default |
| -------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `_http_client` | `httpx.AsyncClient \| None` | | None |
##### result\_async
result\_async(
self: ,
timeout\_sec: float | None = None,
\_http\_client: httpx.AsyncClient | None = None
) -> ResultT
Wait for the job to finish and return its (transformed) result.
Raises `ClassiqAPIError` if the job failed or was cancelled, or if
polling exceeds `timeout_sec` (`None` waits indefinitely).
**Parameters:**
| Name | Type | Description | Default |
| -------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `timeout_sec` | `float \| None` | | None |
| `_http_client` | `httpx.AsyncClient \| None` | | None |
##### cancel\_async
cancel\_async(
self: ,
\_http\_client: httpx.AsyncClient | None = None
) -> None
**Parameters:**
| Name | Type | Description | Default |
| -------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `_http_client` | `httpx.AsyncClient \| None` | | None |
#### embedding\_calculator.MoleculeSpec
User-facing molecular description.
**Methods:**
| Name | Description |
| --------------------------------- | -------------------------------------- |
| [from\_pdb\_file](#from_pdb_file) | Build a spec from a local `.pdb` file. |
| [from\_xyz\_file](#from_xyz_file) | Build a spec from a local `.xyz` file. |
**Attributes:**
| Name | Type | Description |
| -------- | ----- | ----------- |
| `atom` | `str` | |
| `basis` | `str` | |
| `charge` | `int` | |
| `spin` | `int` | |
| `unit` | `str` | |
##### from\_pdb\_file
from\_pdb\_file(
cls: ,
path: str | Path,
basis: str = 'cc-pVDZ',
charge: int = 0,
spin: int = 0,
unit: str = 'Angstrom'
) -> MoleculeSpec
Build a spec from a local `.pdb` file.
The file is read on the client; only its contents are sent to the
backend (the backend never opens paths). The remaining arguments mirror
the `MoleculeSpec` fields.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `path` | `str \| Path` | | *required* |
| `basis` | `str` | | 'cc-pVDZ' |
| `charge` | `int` | | 0 |
| `spin` | `int` | | 0 |
| `unit` | `str` | | 'Angstrom' |
##### from\_xyz\_file
from\_xyz\_file(
cls: ,
path: str | Path,
basis: str = 'cc-pVDZ',
charge: int = 0,
spin: int = 0,
unit: str = 'Angstrom'
) -> MoleculeSpec
Build a spec from a local `.xyz` file.
The file is read on the client; only its contents are sent to the
backend (the backend never opens paths). The remaining arguments mirror
the `MoleculeSpec` fields.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `path` | `str \| Path` | | *required* |
| `basis` | `str` | | 'cc-pVDZ' |
| `charge` | `int` | | 0 |
| `spin` | `int` | | 0 |
| `unit` | `str` | | 'Angstrom' |
#### embedding\_calculator.EmbeddingConfig
Embedding-method parameters.
**Attributes:**
| Name | Type | Description |
| ------------------- | ------------------- | ----------- |
| `fragment_atoms` | `tuple[int, ...]` | |
| `method` | `CalculationMethod` | |
| `xc_functional` | `str` | |
| `mu` | `float` | |
| `w_cut` | `float` | |
| `sv_tol` | `float` | |
| `n_active_virtuals` | `int \| None` | |
| `freeze_core` | `bool` | |
#### embedding\_calculator.DFTState
Post-DFT handle returned to the user, recording the resolved spin mode,
functional, and method. Threaded back into later stages.
**Attributes:**
| Name | Type | Description |
| --------------- | ------------------- | ----------- |
| `spin_mode` | `SpinMode` | |
| `xc_functional` | `str` | |
| `method` | `CalculationMethod` | |
#### embedding\_calculator.MeanFieldData
Fragment / environment densities, electron counts, and active-MO basis.
**Attributes:**
| Name | Type | Description |
| ---------------- | --------------------------------------------- | ----------- |
| `D_A` | `np.ndarray` | |
| `D_B` | `np.ndarray` | |
| `atom_indices` | `tuple[int, ...]` | |
| `n_electrons_A` | `int` | |
| `C_active` | `np.ndarray \| tuple[np.ndarray, np.ndarray]` | |
| `E_DFT_fragment` | `float` | |
| `n_electrons_B` | `int` | |
#### embedding\_calculator.QuantumData
Solver-facing bundle: embedded + physical Hamiltonians and scalars.
**Attributes:**
| Name | Type | Description |
| ------------------ | ----------------- | ----------- |
| `hamiltonian_emb` | `FermionOperator` | |
| `hamiltonian_phys` | `FermionOperator` | |
| `n_particles` | `tuple[int, int]` | |
| `env_correction` | `float` | |
#### embedding\_calculator.EmbeddingCalculator
User-facing embedding driver, backed by queued backend jobs.
**Methods:**
| Name | Description |
| ----------------------------------------------- | ------------------------------------------------------------- |
| [run\_dft](#run_dft) | Run the full-system mean field and cache the result. |
| [submit\_dft](#submit_dft) | Enqueue the full-system mean field and return a job handle. |
| [run\_dft\_embedding](#run_dft_embedding) | Run the full embedding pipeline in one backend call. |
| [submit\_dft\_embedding](#submit_dft_embedding) | Enqueue the full embedding pipeline and return a job handle. |
| [run\_validations](#run_validations) | Run a batch of post-hoc validations in a single backend call. |
**Attributes:**
| Name | Type | Description |
| --------------------- | ----------------------------- | ----------- |
| `spec` | | |
| `spin_mode` | | |
| `auto_validations` | `tuple[ValidationCheck, ...]` | |
| `validation_results` | `ValidationResults` | |
| `config` | `EmbeddingConfig \| None` | |
| `effective_spin_mode` | `SpinMode` | |
##### run\_dft
run\_dft(
self: ,
xc\_functional: str = 'B3LYP',
method: CalculationMethod = CalculationMethod.DFT
) -> DFTState
Run the full-system mean field and cache the result.
Blocks until the backend job finishes. For a long run prefer
[submit\_dft()](#submit_dft), which returns a handle you can poll later.
`method` selects DFT (default, using `xc_functional`) or Hartree-Fock
(`xc_functional` is then ignored).
**Parameters:**
| Name | Type | Description | Default |
| --------------- | ------------------- | ----------- | --------------------- |
| `self` | \`\` | | *required* |
| `xc_functional` | `str` | | 'B3LYP' |
| `method` | `CalculationMethod` | | CalculationMethod.DFT |
##### submit\_dft
submit\_dft(
self: ,
xc\_functional: str = 'B3LYP',
method: CalculationMethod = CalculationMethod.DFT
) -> ChemistryJob\[DFTState]
Enqueue the full-system mean field and return a job handle.
The non-blocking counterpart to [run\_dft()](#run_dft): the DFT runs
server-side (it can take hours) while the client is free to exit. Call
`.result()` on the returned handle to fetch the [DFTState](#dftstate) once
ready -- doing so also caches the state for [run\_dft\_embedding()](#run_dft_embedding),
exactly as [run\_dft()](#run_dft) does.
**Parameters:**
| Name | Type | Description | Default |
| --------------- | ------------------- | ----------- | --------------------- |
| `self` | \`\` | | *required* |
| `xc_functional` | `str` | | 'B3LYP' |
| `method` | `CalculationMethod` | | CalculationMethod.DFT |
##### run\_dft\_embedding
run\_dft\_embedding(
self: ,
config: EmbeddingConfig
) -> tuple\[MeanFieldData, QuantumData]
Run the full embedding pipeline in one backend call.
Blocks until the backend job finishes. For a long run prefer
[submit\_dft\_embedding()](#submit_dft_embedding), which returns a handle you can poll later.
Reuses the cached `DFTState` from a prior `run_dft` call if present;
otherwise the backend runs the full-system DFT first using
`config.xc_functional`. Auto-validations registered at construction are
computed in the same call and stored on `self.validation_results`.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ----------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `config` | `EmbeddingConfig` | | *required* |
##### submit\_dft\_embedding
submit\_dft\_embedding(
self: ,
config: EmbeddingConfig
) -> ChemistryJob\[tuple\[MeanFieldData, QuantumData]]
Enqueue the full embedding pipeline and return a job handle.
The non-blocking counterpart to [run\_dft\_embedding()](#run_dft_embedding). Call
`.result()` on the returned handle to fetch the
`(MeanFieldData, QuantumData)` tuple once ready; doing so caches the
embedding state for subsequent [run\_validations()](#run_validations) calls and emits
any `n_active_virtuals` warning, exactly as the blocking method does.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ----------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `config` | `EmbeddingConfig` | | *required* |
##### run\_validations
run\_validations(
self: ,
checks: Sequence\[ValidationCheck]
) -> ValidationResults
Run a batch of post-hoc validations in a single backend call.
**Parameters:**
| Name | Type | Description | Default |
| -------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `checks` | `Sequence[ValidationCheck]` | | *required* |
### chemistry\_job
Detached handle for a long-running chemistry backend job.
`EmbeddingCalculator.submit_*` returns one of these instead of blocking: a
chemistry DFT run can take hours, so the SDK hands the user a job id and lets
them fetch the result later (`result`) -- the job keeps running server-side
even if the client process exits. `from_id` reconnects to a job submitted by
an earlier process.
The handle is generic over the user-facing return type `ResultT`: a
`transform` callback maps the parsed wire output (`result_type`) to that type
(and, for the calculator, threads the freshly computed state back into the
calculator so a later stage can reuse it). Without a transform the parsed wire
model is returned as-is, which is what `from_id` does.
**Methods:**
| Name | Description |
| -------------------------------------- | ----------- |
| [syncify\_function](#syncify_function) | |
**Attributes:**
| Name | Type | Description |
| ------------ | ---- | ----------- |
| `JSONObject` | | |
| `WireT` | | |
| `ResultT` | | |
#### syncify\_function
syncify\_function(
async\_func: Callable\[..., Awaitable\[T]]
) -> Callable\[..., T]
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ----------------------------- | ----------- | ---------- |
| `async_func` | `Callable[..., Awaitable[T]]` | | *required* |
#### chemistry\_job.ClassiqAPIError
**Attributes:**
| Name | Type | Description |
| ------------- | ---- | ----------- |
| `status_code` | | |
#### chemistry\_job.JobDescription
**Methods:**
| Name | Description |
| ------------------------------------------------------------ | ----------- |
| [validate\_status\_and\_fields](#validate_status_and_fields) | |
**Attributes:**
| Name | Type | Description |
| ----------------- | ------------- | ----------- |
| `status` | `JobStatus` | |
| `failure_details` | `str \| None` | |
| `result` | `T \| None` | |
##### validate\_status\_and\_fields
validate\_status\_and\_fields(
self:
) -> Self
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
#### chemistry\_job.JobID
**Attributes:**
| Name | Type | Description |
| -------- | ----- | ----------- |
| `job_id` | `str` | |
#### chemistry\_job.JobStatus
**Methods:**
| Name | Description |
| ---------------------- | ----------- |
| [is\_final](#is_final) | |
**Attributes:**
| Name | Type | Description |
| ------------ | -------------- | ----------- |
| `QUEUED` | `'QUEUED'` | |
| `RUNNING` | `'RUNNING'` | |
| `READY` | `'READY'` | |
| `COMPLETED` | `'COMPLETED'` | |
| `FAILED` | `'FAILED'` | |
| `CANCELLING` | `'CANCELLING'` | |
| `CANCELLED` | `'CANCELLED'` | |
| `UNKNOWN` | `'UNKNOWN'` | |
##### is\_final
is\_final(
self:
) -> bool
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
#### chemistry\_job.JobPoller
**Methods:**
| Name | Description |
| ---------------------------------------- | ---------------------------------------------------------------- |
| [submit](#submit) | Enqueue a job and return its id without waiting for completion. |
| [fetch\_description](#fetch_description) | Read a job's current description with a single GET (no polling). |
| [cancel](#cancel) | |
| [poll](#poll) | |
| [run](#run) | |
| [run\_pydantic](#run_pydantic) | |
**Attributes:**
| Name | Type | Description |
| ---------------------- | -------- | ----------- |
| `INITIAL_INTERVAL_SEC` | `'0.1'` | |
| `INTERVAL_FACTOR` | `'1.5'` | |
| `FINAL_INTERVAL_SEC` | `'25'` | |
| `DEV_INTERVAL` | `'0.05'` | |
##### submit
submit(
self: ,
body: dict,
http\_client: httpx.AsyncClient | None = None
) -> JobID
Enqueue a job and return its id without waiting for completion.
The detached counterpart to `run`: callers hold on to the returned
`JobID` and poll for the result later (e.g. via `poll`), so a
long-running job survives the client process exiting.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `body` | `dict` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### fetch\_description
fetch\_description(
self: ,
job\_id: JobID,
http\_client: httpx.AsyncClient | None = None
) -> GeneralJobDescription
Read a job's current description with a single GET (no polling).
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `job_id` | `JobID` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### cancel
cancel(
self: ,
job\_id: JobID,
http\_client: httpx.AsyncClient | None = None
) -> None
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `job_id` | `JobID` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### poll
poll(
self: ,
job\_id: JobID,
timeout\_sec: float | None,
response\_parser: Callable\[\[JSONObject], T | None] = \_general\_job\_description\_parser,
http\_client: httpx.AsyncClient | None = None
) -> T
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | ----------------------------------- | ----------- | ----------------------------------- |
| `self` | \`\` | | *required* |
| `job_id` | `JobID` | | *required* |
| `timeout_sec` | `float \| None` | | *required* |
| `response_parser` | `Callable[[JSONObject], T \| None]` | | \_general\_job\_description\_parser |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### run
run(
self: ,
body: dict,
timeout\_sec: float | None,
http\_client: httpx.AsyncClient | None = None
) -> GeneralJobDescription
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `body` | `dict` | | *required* |
| `timeout_sec` | `float \| None` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
##### run\_pydantic
run\_pydantic(
self: ,
model: pydantic.BaseModel,
timeout\_sec: float | None,
http\_client: httpx.AsyncClient | None = None
) -> GeneralJobDescription
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `model` | `pydantic.BaseModel` | | *required* |
| `timeout_sec` | `float \| None` | | *required* |
| `http_client` | `httpx.AsyncClient \| None` | | None |
#### chemistry\_job.ChemistryJob
**Methods:**
| Name | Description |
| ------------------------------ | --------------------------------------------------------------- |
| [from\_id](#from_id) | Reconnect to a previously submitted job by its id. |
| [status\_async](#status_async) | |
| [result\_async](#result_async) | Wait for the job to finish and return its (transformed) result. |
| [cancel\_async](#cancel_async) | |
**Attributes:**
| Name | Type | Description |
| -------- | ----- | ----------- |
| `id` | `str` | |
| `status` | | |
| `result` | | |
| `cancel` | | |
##### from\_id
from\_id(
cls: ,
id: str,
job\_route: str,
result\_type: type\[pydantic.BaseModel]
) -> ChemistryJob
Reconnect to a previously submitted job by its id.
The result is fetchable while the job's result is still retained by the
backend (see `MAX_KEEP_RESULT`); reconnecting much later may fail.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | -------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `id` | `str` | | *required* |
| `job_route` | `str` | | *required* |
| `result_type` | `type[pydantic.BaseModel]` | | *required* |
##### status\_async
status\_async(
self: ,
\_http\_client: httpx.AsyncClient | None = None
) -> JobStatus
**Parameters:**
| Name | Type | Description | Default |
| -------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `_http_client` | `httpx.AsyncClient \| None` | | None |
##### result\_async
result\_async(
self: ,
timeout\_sec: float | None = None,
\_http\_client: httpx.AsyncClient | None = None
) -> ResultT
Wait for the job to finish and return its (transformed) result.
Raises `ClassiqAPIError` if the job failed or was cancelled, or if
polling exceeds `timeout_sec` (`None` waits indefinitely).
**Parameters:**
| Name | Type | Description | Default |
| -------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `timeout_sec` | `float \| None` | | None |
| `_http_client` | `httpx.AsyncClient \| None` | | None |
##### cancel\_async
cancel\_async(
self: ,
\_http\_client: httpx.AsyncClient | None = None
) -> None
**Parameters:**
| Name | Type | Description | Default |
| -------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `_http_client` | `httpx.AsyncClient \| None` | | None |
# Cudaq
Source: https://docs.classiq.io/sdk-reference/cudaq
\
Classiq to [CUDA-Q](https://developer.nvidia.com/cuda-q) translation.
These functions require the `cudaq` extra (install `classiq[cudaq]`).
Note that the `cudaq` extra is only available in Classiq Studio and on any Linux
Machine.
## Functions
### qprog\_to\_cudaq\_kernel
qprog\_to\_cudaq\_kernel(
quantum\_program: QuantumProgram,
is\_main\_kernel: bool = True
) -> Union\[cudaq.PyKernel, tuple]
Translates a quantum program into a CUDA-Q kernel.
The 'is\_main\_kernel' parameter controls the kind of the returned kernel.
If 'is\_main\_kernel' is True, the returned kernel can be used with CUDA-Q functions
such as 'cudaq.draw()' and 'cudaq.get\_state()', but it cannot be added to another
kernel via \`apply\_call()'.
If 'is\_main\_kernel' is False, the reverse holds: The returned kernel cannot be used
with CUDA-Q functions but can be added to another kernel.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `quantum_program` | `QuantumProgram` | The quantum program to translate into CUDA-Q kernel. This is the result of the function 'synthesize()'. | *required* |
| `is_main_kernel` | `bool` | Whether the kernel is compatible with CUDA-Q functions (`is_main_kernel=True`, the default behavior) or 'apply\_call()' (`is_main_kernel=False`) | True |
**Returns:**
* **Type:** `Union[cudaq.PyKernel, tuple]`
* A CUDA-Q kernel. If the quantum program includes foreach statements, a tuple
* containing a CUDA-Q kernel and its foreach arguments will be returned.
### pauli\_operator\_to\_cudaq\_spin\_op
pauli\_operator\_to\_cudaq\_spin\_op(
operator: SparsePauliOp
) -> cudaq.SpinOperator
Transforms Qmod's SparsePauliOp data structure to CUDA-Q's SpinOperator.
**Parameters:**
| Name | Type | Description | Default |
| ---------- | --------------- | ------------------------------ | ---------- |
| `operator` | `SparsePauliOp` | The operator to be transformed | *required* |
**Returns:**
* **Type:** `cudaq.SpinOperator`
* The equivalent operator in CUDA-Q's data structure
# Execution
Source: https://docs.classiq.io/sdk-reference/execution
Members:
| Name | Description |
| ---------------------- | ----------------------------------------------------------------------------------------------------- |
| `ProviderConfig` | Provider-specific configuration data for execution, such as API keys and machine-specific parameters. |
| `ExecutionPreferences` | Represents the execution settings for running a quantum program. |
| `TranspilationOption` | Transpilation optimization level for quantum circuits. |
| `ExecutionSession` | A session for executing a quantum program or OpenQASM source text. |
| `sample` | Sample a quantum program or OpenQASM circuit. |
## ProviderConfig
Provider-specific configuration data for execution, such as API keys and
machine-specific parameters.
## ExecutionPreferences
Represents the execution settings for running a quantum program.
Execution preferences for running a quantum program.
For more details, refer to:
ExecutionPreferences example: [ExecutionPreferences](https://docs.classiq.io/latest/user-guide/execution/#execution-preferences)..
**Attributes:**
| Name | Type | Description |
| -------------------------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `include_zero_amplitude_outputs` | `bool` | |
| `amplitude_threshold` | `float` | |
| `noise_properties` | `Optional[NoiseProperties]` | Properties defining the noise in the quantum circuit. Defaults to `None`. |
| `random_seed` | `int` | The random seed used for the execution. Defaults to a randomly generated seed. |
| `backend_preferences` | `BackendPreferencesTypes` | Preferences for the backend used to execute the circuit. Defaults to the Classiq Simulator. |
| `num_shots` | `Optional[pydantic.PositiveInt]` | The number of shots (executions) to be performed. |
| `transpile_to_hardware` | `TranspilationOption` | Option to transpile the circuit to the hardware's basis gates before execution. Defaults to `TranspilationOption.DECOMPOSE`. |
| `job_name` | `Optional[str]` | The name of the job, with a minimum length of 1 character. |
## TranspilationOption
Transpilation optimization level for quantum circuits.
**Attributes:**
| Name | Type | Description |
| --------------- | ----------------- | ----------- |
| `NONE` | `'none'` | |
| `DECOMPOSE` | `'decompose'` | |
| `AUTO_OPTIMIZE` | `'auto optimize'` | |
| `LIGHT` | `'light'` | |
| `MEDIUM` | `'medium'` | |
| `INTENSIVE` | `'intensive'` | |
| `CUSTOM` | `'custom'` | |
## ExecutionSession
A session for executing a quantum program or OpenQASM source text.
`ExecutionSession` allows to execute the quantum program with different parameters and operations without the need to re-synthesize the model.
The session must be closed in order to ensure resources are properly cleaned up. It's recommended to use `ExecutionSession` as a context manager for this purpose. Alternatively, you can directly use the `close` method.
**Methods:**
| Name | Description |
| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| [close](#close) | Close the session and clean up its resources. |
| [get\_session\_id](#get_session_id) | |
| [update\_execution\_preferences](#update_execution_preferences) | Update the execution preferences for the session. |
| [sample](#sample) | Samples the quantum program with the given parameters, if any. |
| [submit\_sample](#submit_sample) | Initiates an execution job with the `sample` primitive. |
| [calculate\_state\_vector](#calculate_state_vector) | Calculate the state vector of the quantum program. |
| [submit\_calculate\_state\_vector](#submit_calculate_state_vector) | Initiates an execution job with the `calculate_state_vector` primitive. |
| [calculate\_unitary](#calculate_unitary) | Calculate the unitary matrix of the quantum program. |
| [submit\_calculate\_unitary](#submit_calculate_unitary) | Initiates an execution job with the `calculate_unitary` primitive. |
| [batch\_sample](#batch_sample) | Samples the quantum program multiple times with the given parameters for each iteration. |
| [submit\_batch\_sample](#submit_batch_sample) | Initiates an execution job with the `batch_sample` primitive. |
| [observe](#observe) | Estimates the expectation value of the given Hamiltonian using the quantum program. |
| [submit\_observe](#submit_observe) | Initiates an execution job with the `observe` primitive. |
| [estimate](#estimate) | Estimates the expectation value of the given Hamiltonian using the quantum program. |
| [submit\_estimate](#submit_estimate) | Initiates an execution job with the `estimate` primitive. |
| [batch\_estimate](#batch_estimate) | Estimates the expectation value of the given Hamiltonian multiple times using the quantum program, with the given parameters for each iteration. |
| [submit\_batch\_estimate](#submit_batch_estimate) | Initiates an execution job with the `batch_estimate` primitive. |
| [variational\_minimize](#variational_minimize) | Variationally minimizes the given cost function using the quantum program. |
| [minimize](#minimize) | . |
| [submit\_variational\_minimize](#submit_variational_minimize) | Initiates an execution job with the variational minimization primitive. |
| [submit\_minimize](#submit_minimize) | . |
| [estimate\_cost](#estimate_cost) | Estimates circuit cost using a classical cost function. |
| [set\_measured\_state\_filter](#set_measured_state_filter) | When simulating on a statevector simulator, emulate the behavior of postprocessing by discarding amplitudes for which their states are "undesirable". |
**Attributes:**
| Name | Type | Description |
| --------- | ---------------- | -------------------------------------------------------------------------------------------------------------- |
| `program` | `QuantumProgram` | The quantum program to execute, or a placeholder when the first constructor argument was OpenQASM source text. |
### close
close(
self:
) -> None
Close the session and clean up its resources.
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### get\_session\_id
get\_session\_id(
self:
) -> str
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### update\_execution\_preferences
update\_execution\_preferences(
self: ,
execution\_preferences: ExecutionPreferences | None
) -> None
Update the execution preferences for the session.
**Parameters:**
| Name | Type | Description | Default |
| ----------------------- | ----------------------------------------------------- | ------------------------------------ | ---------- |
| `self` | \`\` | | *required* |
| `execution_preferences` | [ExecutionPreferences](#executionpreferences) \| None | The execution preferences to update. | *required* |
**Returns:**
* **Type:** `None`
### sample
sample(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionDetails | list\[ExecutionDetails]
Samples the quantum program with the given parameters, if any.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `ExecutionDetails \| list[ExecutionDetails]`
* The result of the sampling, or a list of results when
* `parameters` is a list.
### submit\_sample
submit\_sample(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
Initiates an execution job with the `sample` primitive.
This is a non-blocking version of `sample`: it gets the same parameters and initiates the same execution job, but instead
of waiting for the result, it returns the job object immediately.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### calculate\_state\_vector
calculate\_state\_vector(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
filters: dict\[str, Any] | None = None,
amplitude\_threshold: float = 0.0,
verbose: bool = True
) -> DataFrame | list\[DataFrame]
Calculate the state vector of the quantum program.
The session must be configured with a Classiq simulator
(`"classiq/simulator"`, `"classiq/nvidia_simulator"`) or
`"google/cuquantum"`. The corresponding statevector variant is
selected automatically; callers do not need to know about the
`_statevector` backend names.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. | None |
| `filters` | `dict[str, Any] \| None` | Only states where the variables match these values will be included in the state vector. | None |
| `amplitude_threshold` | `float` | If provided, only states whose amplitude magnitude is strictly greater than this value will be included in the result. Defaults to 0 (filters exactly zero-amplitude states). | 0.0 |
| `verbose` | `bool` | Whether to print the "Submitting state-vector job to..." progress line. Set to `False` to suppress it, for example when calling `calculate_state_vector` repeatedly in a loop. Defaults to `True`. | True |
**Returns:**
* **Type:** `DataFrame \| list[DataFrame]`
* A dataframe containing the state vector, or a list of dataframes when
* `parameters` is a list.
### submit\_calculate\_state\_vector
submit\_calculate\_state\_vector(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
filters: dict\[str, Any] | None = None,
amplitude\_threshold: float = 0.0,
verbose: bool = True
) -> ExecutionJob
Initiates an execution job with the `calculate_state_vector` primitive.
This is a non-blocking version of [calculate\_state\_vector()](#calculate_state_vector): it gets
the same parameters and initiates the same execution job, but instead of
waiting for the result, it returns the job object immediately.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------------------------- | ---------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | See [calculate\_state\_vector()](#calculate_state_vector). | None |
| `filters` | `dict[str, Any] \| None` | See [calculate\_state\_vector()](#calculate_state_vector). | None |
| `amplitude_threshold` | `float` | See [calculate\_state\_vector()](#calculate_state_vector). | 0.0 |
| `verbose` | `bool` | See [calculate\_state\_vector()](#calculate_state_vector). | True |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### calculate\_unitary
calculate\_unitary(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
amplitude\_threshold: float = 0.0
) -> DataFrame | list\[DataFrame]
Calculate the unitary matrix of the quantum program.
The session must be configured with a Classiq simulator
(`"classiq/simulator"`, `"classiq/nvidia_simulator"`,
`"classiq/dgx_simulator"`) or `"google/cuquantum"`.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. | None |
| `amplitude_threshold` | `float` | If provided, matrix elements whose magnitude is below this threshold are zeroed (same cutoff semantics as `calculate_state_vector`). | 0.0 |
**Returns:**
* **Type:** `DataFrame \| list[DataFrame]`
* A dataframe containing the unitary matrix, or a list of dataframes when
* `parameters` is a list.
### submit\_calculate\_unitary
submit\_calculate\_unitary(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
amplitude\_threshold: float = 0.0
) -> ExecutionJob
Initiates an execution job with the `calculate_unitary` primitive.
Promotes the session backend to a unitary simulator and runs the `sample`
primitive on a dedicated unitary session. Program size limits are enforced
server-side.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | | None |
| `amplitude_threshold` | `float` | | 0.0 |
### batch\_sample
batch\_sample(
self: ,
parameters: list\[ExecutionParams]
) -> list\[ExecutionDetails]
Samples the quantum program multiple times with the given parameters for each iteration. The number of samples is determined by the length of the parameters list.
**Deprecated:** Pass a list of parameter dicts to [sample()](#sample) instead.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `list[ExecutionParams]` | A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | *required* |
**Returns:**
* **Type:** `list[ExecutionDetails]`
* List\[ExecutionDetails]: The results of all the sampling iterations.
### submit\_batch\_sample
submit\_batch\_sample(
self: ,
parameters: list\[ExecutionParams]
) -> ExecutionJob
Initiates an execution job with the `batch_sample` primitive.
**Deprecated:** Pass a list of parameter dicts to [submit\_sample()](#submit_sample) instead.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `list[ExecutionParams]` | A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | *required* |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### observe
observe(
self: ,
hamiltonian: Hamiltonian,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> EstimationResult | list\[EstimationResult]
Estimates the expectation value of the given Hamiltonian using the quantum program.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | The Hamiltonian to estimate the expectation value of. | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `EstimationResult \| list[EstimationResult]`
* The estimation result, or a list of results when `parameters`
* is a list.
### submit\_observe
submit\_observe(
self: ,
hamiltonian: Hamiltonian,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
Initiates an execution job with the `observe` primitive.
This is a non-blocking version of [observe()](#observe): it gets the same
parameters and initiates the same execution job, but instead of waiting
for the result, it returns the job object immediately.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | The Hamiltonian to estimate the expectation value of. | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### estimate
estimate(
self: ,
hamiltonian: Hamiltonian,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> EstimationResult | list\[EstimationResult]
Estimates the expectation value of the given Hamiltonian using the quantum program.
**Deprecated:** `estimate` is deprecated and will no longer be supported starting on 2026-06-22. Use [observe()](#observe) instead.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | | None |
| `num_shots` | `int \| None` | | None |
| `run_via_classiq` | `bool \| None` | | None |
### submit\_estimate
submit\_estimate(
self: ,
hamiltonian: Hamiltonian,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
Initiates an execution job with the `estimate` primitive.
**Deprecated:** `submit_estimate` is deprecated and will no longer be supported starting on 2026-06-22. Use [submit\_observe()](#submit_observe) instead.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | | None |
| `num_shots` | `int \| None` | | None |
| `run_via_classiq` | `bool \| None` | | None |
### batch\_estimate
batch\_estimate(
self: ,
hamiltonian: Hamiltonian,
parameters: list\[ExecutionParams]
) -> list\[EstimationResult]
Estimates the expectation value of the given Hamiltonian multiple times using the quantum program, with the given parameters for each iteration. The number of estimations is determined by the length of the parameters list.
**Deprecated:** Pass a list of parameter dicts to [observe()](#observe) instead.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | The Hamiltonian to estimate the expectation value of. | *required* |
| `parameters` | `list[ExecutionParams]` | A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | *required* |
**Returns:**
* **Type:** `list[EstimationResult]`
* List\[EstimationResult]: The results of all the estimation iterations.
### submit\_batch\_estimate
submit\_batch\_estimate(
self: ,
hamiltonian: Hamiltonian,
parameters: list\[ExecutionParams]
) -> ExecutionJob
Initiates an execution job with the `batch_estimate` primitive.
**Deprecated:** Pass a list of parameter dicts to [submit\_observe()](#submit_observe) instead.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | The Hamiltonian to estimate the expectation value of. | *required* |
| `parameters` | `list[ExecutionParams]` | A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | *required* |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### variational\_minimize
variational\_minimize(
self: ,
cost\_function: Hamiltonian | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
quantile: float = 1.0,
tolerance: float | None = None,
hosted: bool = False,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> list\[tuple\[float, ExecutionParams]]
Variationally minimizes the given cost function using the quantum program.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_function` | `Hamiltonian \| QmodExpressionCreator` | The cost function to minimize. It can be one of the following: - A quantum cost function defined by a Hamiltonian. - A classical cost function represented as a callable that returns a Qmod expression. The callable should accept `QVar`s as arguments and use names matching the Model outputs. | *required* |
| `initial_params` | `ExecutionParams` | The initial parameters for the minimization. Only Models with exactly one execution parameter are supported. This parameter must be of type `CReal` or `CArray`. The dictionary must contain a single key-value pair, where: - The key is the name of the parameter. - The value is either a float or a list of floats. | *required* |
| `max_iteration` | `int` | The maximum number of iterations for the minimization. | *required* |
| `quantile` | `float` | The quantile to use for cost estimation. | 1.0 |
| `tolerance` | `float \| None` | The tolerance for the minimization. | None |
| `hosted` | `bool` | When `True` on an IonQ backend, submit a Classiq execution job that runs the optimization loop on IonQ Hosted Hybrid in the backend. Defaults to `False`. | False |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `list[tuple[float, ExecutionParams]]`
* A list of tuples, each containing the estimated cost and the corresponding parameters for that iteration. `cost` is a float, and `parameters` is a dictionary matching the execution parameter format.
### minimize
minimize(
self: ,
cost\_function: Hamiltonian | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
quantile: float = 1.0,
tolerance: float | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> list\[tuple\[float, ExecutionParams]]
**Deprecated:** Use [variational\_minimize()](#variational_minimize) instead.
This name is kept for backward compatibility and will be removed in a future release.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_function` | `Hamiltonian \| QmodExpressionCreator` | | *required* |
| `initial_params` | `ExecutionParams` | | *required* |
| `max_iteration` | `int` | | *required* |
| `quantile` | `float` | | 1.0 |
| `tolerance` | `float \| None` | | None |
| `num_shots` | `int \| None` | | None |
| `run_via_classiq` | `bool \| None` | | None |
### submit\_variational\_minimize
submit\_variational\_minimize(
self: ,
cost\_function: Hamiltonian | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
quantile: float = 1.0,
tolerance: float | None = None,
hosted: bool = False,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
Initiates an execution job with the variational minimization primitive.
Non-blocking counterpart of [variational\_minimize()](#variational_minimize): same parameters and job,
but returns the [ExecutionJob](#executionjob) immediately.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_function` | `Hamiltonian \| QmodExpressionCreator` | The cost function to minimize. It can be one of the following: - A quantum cost function defined by a Hamiltonian. - A classical cost function represented as a callable that returns a Qmod expression. The callable should accept `QVar`s as arguments and use names matching the Model outputs. | *required* |
| `initial_params` | `ExecutionParams` | The initial parameters for the minimization. Only Models with exactly one execution parameter are supported. This parameter must be of type `CReal` or `CArray`. The dictionary must contain a single key-value pair, where: - The key is the name of the parameter. - The value is either a float or a list of floats. | *required* |
| `max_iteration` | `int` | The maximum number of iterations for the minimization. | *required* |
| `quantile` | `float` | The quantile to use for cost estimation. | 1.0 |
| `tolerance` | `float \| None` | The tolerance for the minimization. | None |
| `hosted` | `bool` | When `True` on an IonQ backend, submit a Classiq execution job that runs the optimization loop on IonQ Hosted Hybrid in the backend. Defaults to `False`. | False |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job. When `hosted=True` on an IonQ backend, the backend
* worker submits and polls IonQ Hosted Hybrid while this job tracks
* progress through the standard Classiq execution API.
### submit\_minimize
submit\_minimize(
self: ,
cost\_function: Hamiltonian | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
quantile: float = 1.0,
tolerance: float | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
**Deprecated:** Use [submit\_variational\_minimize()](#submit_variational_minimize) instead.
This name is kept for backward compatibility and will be removed in a future release.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_function` | `Hamiltonian \| QmodExpressionCreator` | | *required* |
| `initial_params` | `ExecutionParams` | | *required* |
| `max_iteration` | `int` | | *required* |
| `quantile` | `float` | | 1.0 |
| `tolerance` | `float \| None` | | None |
| `num_shots` | `int \| None` | | None |
| `run_via_classiq` | `bool \| None` | | None |
### estimate\_cost
estimate\_cost(
self: ,
cost\_func: Callable\[\[ParsedState], float],
parameters: ExecutionParams | None = None,
quantile: float = 1.0,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> float
Estimates circuit cost using a classical cost function.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------- | --------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_func` | `Callable[[ParsedState], float]` | classical circuit sample cost function | *required* |
| `parameters` | `ExecutionParams \| None` | execution parameters sent to 'sample' | None |
| `quantile` | `float` | drop cost values outside the specified quantile | 1.0 |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `float`
* cost estimation
### set\_measured\_state\_filter
set\_measured\_state\_filter(
self: ,
output\_name: str,
condition: Callable
) -> None
When simulating on a statevector simulator, emulate the behavior of postprocessing
by discarding amplitudes for which their states are "undesirable".
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ---------- | --------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `output_name` | `str` | The name of the register to filter | *required* |
| `condition` | `Callable` | Filter out values of the statevector for which this callable is False | *required* |
### sample
sample(
qprog: QuantumProgram | str,
backend: str | None = None,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
config: dict\[str, Any] | ProviderConfig | None = None,
num\_shots: int | None = None,
random\_seed: int | None = None,
transpilation\_option: TranspilationOption = TranspilationOption.DECOMPOSE,
run\_via\_classiq: bool = False,
verbose: bool = True
) -> DataFrame | list\[DataFrame]
Sample a quantum program or OpenQASM circuit.
**Parameters:**
| Name | Type | Description | Default |
| ---------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| `qprog` | `QuantumProgram \| str` | A synthesized `QuantumProgram`, or OpenQASM **2.0** / **3.0** source as a single string (for example output of `qiskit.qasm2.dumps` or `qiskit.qasm3.dumps`). | *required* |
| `backend` | `str \| None` | The hardware or simulator on which to run the quantum program. Use `"simulator"` for Classiq's default simulator, or specify a backend as `"provider/device_id"`. Use the `get_backend_details` function to see supported devices. | None |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the `main` function), and the value should be the value to set for that parameter. **Not supported** when `qprog` is an OpenQASM string (use a `QuantumProgram` or bind values in QASM before calling `sample`). | None |
| `config` | dict\[str, Any] \| [ProviderConfig](#providerconfig) \| None | Provider-specific configuration, such as API keys. For full details, see the SDK reference under Providers. | None |
| `num_shots` | `int \| None` | The number of times to sample. | None |
| `random_seed` | `int \| None` | The random seed used for transpilation and simulation. | None |
| `transpilation_option` | `TranspilationOption` | Advanced configuration for hardware-specific transpilation. | TranspilationOption.DECOMPOSE |
| `run_via_classiq` | `bool` | Run via Classiq's credentials while using your allocated budget. Defaults to `False`. | False |
| `verbose` | `bool` | Whether to print the "Submitting job to..." and "Job: ..." progress lines. Set to `False` to suppress them, for example when calling `sample` repeatedly in a loop. Defaults to `True`. | True |
**Returns:**
* **Type:** `DataFrame \| list[DataFrame]`
* A dataframe containing the histogram, or a list of dataframes when
* `parameters` is a list.
## BraketConfig
Configuration specific to Amazon Braket.
**Attributes:**
| Name | Type | Description |
| -------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `braket_access_key_id` | `str \| None` | The access key id of user with full braket access |
| `braket_secret_access_key` | `str \| None` | The secret key assigned to the access key id for the user with full braket access. |
| `s3_bucket_name` | `str \| None` | The name of the S3 bucket where results and other related data will be stored. This field should contain a valid S3 bucket name under your AWS account. |
| `s3_folder` | `pydantic_backend.PydanticS3BucketKey \| None` | The folder path within the specified S3 bucket. This allows for organizing results and data under a specific directory within the S3 bucket. |
## IBMConfig
Configuration specific to IBM.
**Attributes:**
| Name | Type | Description |
| -------------- | ------------- | ------------------------------------------------------------------------------------------------------------- |
| `access_token` | `str \| None` | The IBM Cloud access token to be used with IBM Quantum hosted backends. Defaults to `None`. |
| `channel` | `str` | Channel to use for IBM cloud backends. Defaults to `"ibm_cloud"`. |
| `instance_crn` | `str \| None` | The IBM Cloud instance CRN (Cloud Resource Name) for the IBM Quantum service. |
| `emulate` | `bool` | If True, run on a Classiq-hosted simulator with IBM noise derived from the backend name. Defaults to `False`. |
## IonQConfig
Configuration specific to IonQ.
Attributes:
api\_key (PydanticIonQApiKeyType | None): Key to access IonQ API.
error\_mitigation (bool): A configuration option to enable or disable error mitigation during execution. Defaults to `False`.
emulate (bool): If True, run on IonQ simulator with noise model derived from the backend name. Defaults to `False`.
**Attributes:**
| Name | Type | Description |
| ------------------ | ------------------------------------------------- | ----------- |
| `api_key` | `pydantic_backend.PydanticIonQApiKeyType \| None` | |
| `error_mitigation` | `bool` | |
| `emulate` | `bool` | |
## AzureConfig
Configuration specific to Azure.
**Attributes:**
| Name | Type | Description |
| ----------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `location` | `str` | Azure region. Defaults to `"East US"`. |
| `tenant_id` | `str \| None` | Azure Tenant ID used to identify the directory in which the application is registered. |
| `client_id` | `str \| None` | Azure Client ID, also known as the application ID, which is used to authenticate the application. |
| `client_secret` | `str \| None` | Azure Client Secret associated with the application, used for authentication. |
| `resource_id` | `str \| None` | Azure Resource ID, including the subscription ID, resource group, and workspace, typically used for personal resources. |
| `ionq_error_mitigation` | `bool` | Should use error mitigation when running on IonQ via Azure. Defaults to `False`. |
| `emulate` | `bool` | When True, request IonQ hardware noise simulation on Azure Quantum for IonQ QPU targets (`ionq.qpu.*`). No effect for `ionq.simulator` or non-IonQ targets. Defaults to `False`. |
## AQTConfig
Configuration specific to AQT (Alpine Quantum Technologies).
**Attributes:**
| Name | Type | Description |
| ----------- | ----- | ---------------------------------------------------------------- |
| `api_key` | `str` | The API key required to access AQT's quantum computing services. |
| `workspace` | `str` | The AQT workspace where the simulator/hardware is located. |
## AliceBobConfig
Configuration specific to Alice\&Bob.
**Attributes:**
| Name | Type | Description |
| -------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `distance` | `int \| None` | The number of times information is duplicated in the repetition code. - **Tooltip**: Phase-flip probability decreases exponentially with this parameter, bit-flip probability increases linearly. - **Supported Values**: 3 to 300, though practical values are usually lower than 30. - **Default**: None. |
| `kappa_1` | `float \| None` | The rate at which the cat qubit loses one photon, creating a bit-flip. - **Tooltip**: Lower values mean lower error rates. - **Supported Values**: 10 to 10^5. Current hardware is at \~10^3. - **Default**: None. |
| `kappa_2` | `float \| None` | The rate at which the cat qubit is stabilized using two-photon dissipation. - **Tooltip**: Higher values mean lower error rates. - **Supported Values**: 100 to 10^9. Current hardware is at \~10^5. - **Default**: None. |
| `average_nb_photons` | `float \| None` | The average number of photons. - **Tooltip**: Bit-flip probability decreases exponentially with this parameter, phase-flip probability increases linearly. - **Supported Values**: 4 to 10^5, though practical values are usually lower than 30. - **Default**: None. |
## ProviderConfig
Provider-specific configuration data for execution, such as API keys and
machine-specific parameters.
## ExecutionSession
A session for executing a quantum program or OpenQASM source text.
`ExecutionSession` allows to execute the quantum program with different parameters and operations without the need to re-synthesize the model.
The session must be closed in order to ensure resources are properly cleaned up. It's recommended to use `ExecutionSession` as a context manager for this purpose. Alternatively, you can directly use the `close` method.
**Methods:**
| Name | Description |
| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| [close](#close) | Close the session and clean up its resources. |
| [get\_session\_id](#get_session_id) | |
| [update\_execution\_preferences](#update_execution_preferences) | Update the execution preferences for the session. |
| [sample](#sample) | Samples the quantum program with the given parameters, if any. |
| [submit\_sample](#submit_sample) | Initiates an execution job with the `sample` primitive. |
| [calculate\_state\_vector](#calculate_state_vector) | Calculate the state vector of the quantum program. |
| [submit\_calculate\_state\_vector](#submit_calculate_state_vector) | Initiates an execution job with the `calculate_state_vector` primitive. |
| [calculate\_unitary](#calculate_unitary) | Calculate the unitary matrix of the quantum program. |
| [submit\_calculate\_unitary](#submit_calculate_unitary) | Initiates an execution job with the `calculate_unitary` primitive. |
| [batch\_sample](#batch_sample) | Samples the quantum program multiple times with the given parameters for each iteration. |
| [submit\_batch\_sample](#submit_batch_sample) | Initiates an execution job with the `batch_sample` primitive. |
| [observe](#observe) | Estimates the expectation value of the given Hamiltonian using the quantum program. |
| [submit\_observe](#submit_observe) | Initiates an execution job with the `observe` primitive. |
| [estimate](#estimate) | Estimates the expectation value of the given Hamiltonian using the quantum program. |
| [submit\_estimate](#submit_estimate) | Initiates an execution job with the `estimate` primitive. |
| [batch\_estimate](#batch_estimate) | Estimates the expectation value of the given Hamiltonian multiple times using the quantum program, with the given parameters for each iteration. |
| [submit\_batch\_estimate](#submit_batch_estimate) | Initiates an execution job with the `batch_estimate` primitive. |
| [variational\_minimize](#variational_minimize) | Variationally minimizes the given cost function using the quantum program. |
| [minimize](#minimize) | . |
| [submit\_variational\_minimize](#submit_variational_minimize) | Initiates an execution job with the variational minimization primitive. |
| [submit\_minimize](#submit_minimize) | . |
| [estimate\_cost](#estimate_cost) | Estimates circuit cost using a classical cost function. |
| [set\_measured\_state\_filter](#set_measured_state_filter) | When simulating on a statevector simulator, emulate the behavior of postprocessing by discarding amplitudes for which their states are "undesirable". |
**Attributes:**
| Name | Type | Description |
| --------- | ---------------- | -------------------------------------------------------------------------------------------------------------- |
| `program` | `QuantumProgram` | The quantum program to execute, or a placeholder when the first constructor argument was OpenQASM source text. |
### close
close(
self:
) -> None
Close the session and clean up its resources.
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### get\_session\_id
get\_session\_id(
self:
) -> str
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### update\_execution\_preferences
update\_execution\_preferences(
self: ,
execution\_preferences: ExecutionPreferences | None
) -> None
Update the execution preferences for the session.
**Parameters:**
| Name | Type | Description | Default |
| ----------------------- | ----------------------------------------------------- | ------------------------------------ | ---------- |
| `self` | \`\` | | *required* |
| `execution_preferences` | [ExecutionPreferences](#executionpreferences) \| None | The execution preferences to update. | *required* |
**Returns:**
* **Type:** `None`
### sample
sample(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionDetails | list\[ExecutionDetails]
Samples the quantum program with the given parameters, if any.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `ExecutionDetails \| list[ExecutionDetails]`
* The result of the sampling, or a list of results when
* `parameters` is a list.
### submit\_sample
submit\_sample(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
Initiates an execution job with the `sample` primitive.
This is a non-blocking version of `sample`: it gets the same parameters and initiates the same execution job, but instead
of waiting for the result, it returns the job object immediately.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### calculate\_state\_vector
calculate\_state\_vector(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
filters: dict\[str, Any] | None = None,
amplitude\_threshold: float = 0.0,
verbose: bool = True
) -> DataFrame | list\[DataFrame]
Calculate the state vector of the quantum program.
The session must be configured with a Classiq simulator
(`"classiq/simulator"`, `"classiq/nvidia_simulator"`) or
`"google/cuquantum"`. The corresponding statevector variant is
selected automatically; callers do not need to know about the
`_statevector` backend names.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. | None |
| `filters` | `dict[str, Any] \| None` | Only states where the variables match these values will be included in the state vector. | None |
| `amplitude_threshold` | `float` | If provided, only states whose amplitude magnitude is strictly greater than this value will be included in the result. Defaults to 0 (filters exactly zero-amplitude states). | 0.0 |
| `verbose` | `bool` | Whether to print the "Submitting state-vector job to..." progress line. Set to `False` to suppress it, for example when calling `calculate_state_vector` repeatedly in a loop. Defaults to `True`. | True |
**Returns:**
* **Type:** `DataFrame \| list[DataFrame]`
* A dataframe containing the state vector, or a list of dataframes when
* `parameters` is a list.
### submit\_calculate\_state\_vector
submit\_calculate\_state\_vector(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
filters: dict\[str, Any] | None = None,
amplitude\_threshold: float = 0.0,
verbose: bool = True
) -> ExecutionJob
Initiates an execution job with the `calculate_state_vector` primitive.
This is a non-blocking version of [calculate\_state\_vector()](#calculate_state_vector): it gets
the same parameters and initiates the same execution job, but instead of
waiting for the result, it returns the job object immediately.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------------------------- | ---------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | See [calculate\_state\_vector()](#calculate_state_vector). | None |
| `filters` | `dict[str, Any] \| None` | See [calculate\_state\_vector()](#calculate_state_vector). | None |
| `amplitude_threshold` | `float` | See [calculate\_state\_vector()](#calculate_state_vector). | 0.0 |
| `verbose` | `bool` | See [calculate\_state\_vector()](#calculate_state_vector). | True |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### calculate\_unitary
calculate\_unitary(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
amplitude\_threshold: float = 0.0
) -> DataFrame | list\[DataFrame]
Calculate the unitary matrix of the quantum program.
The session must be configured with a Classiq simulator
(`"classiq/simulator"`, `"classiq/nvidia_simulator"`,
`"classiq/dgx_simulator"`) or `"google/cuquantum"`.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. | None |
| `amplitude_threshold` | `float` | If provided, matrix elements whose magnitude is below this threshold are zeroed (same cutoff semantics as `calculate_state_vector`). | 0.0 |
**Returns:**
* **Type:** `DataFrame \| list[DataFrame]`
* A dataframe containing the unitary matrix, or a list of dataframes when
* `parameters` is a list.
### submit\_calculate\_unitary
submit\_calculate\_unitary(
self: ,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
amplitude\_threshold: float = 0.0
) -> ExecutionJob
Initiates an execution job with the `calculate_unitary` primitive.
Promotes the session backend to a unitary simulator and runs the `sample`
primitive on a dedicated unitary session. Program size limits are enforced
server-side.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | | None |
| `amplitude_threshold` | `float` | | 0.0 |
### batch\_sample
batch\_sample(
self: ,
parameters: list\[ExecutionParams]
) -> list\[ExecutionDetails]
Samples the quantum program multiple times with the given parameters for each iteration. The number of samples is determined by the length of the parameters list.
**Deprecated:** Pass a list of parameter dicts to [sample()](#sample) instead.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `list[ExecutionParams]` | A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | *required* |
**Returns:**
* **Type:** `list[ExecutionDetails]`
* List\[ExecutionDetails]: The results of all the sampling iterations.
### submit\_batch\_sample
submit\_batch\_sample(
self: ,
parameters: list\[ExecutionParams]
) -> ExecutionJob
Initiates an execution job with the `batch_sample` primitive.
**Deprecated:** Pass a list of parameter dicts to [submit\_sample()](#submit_sample) instead.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `parameters` | `list[ExecutionParams]` | A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | *required* |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### observe
observe(
self: ,
hamiltonian: Hamiltonian,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> EstimationResult | list\[EstimationResult]
Estimates the expectation value of the given Hamiltonian using the quantum program.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | The Hamiltonian to estimate the expectation value of. | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `EstimationResult \| list[EstimationResult]`
* The estimation result, or a list of results when `parameters`
* is a list.
### submit\_observe
submit\_observe(
self: ,
hamiltonian: Hamiltonian,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
Initiates an execution job with the `observe` primitive.
This is a non-blocking version of [observe()](#observe): it gets the same
parameters and initiates the same execution job, but instead of waiting
for the result, it returns the job object immediately.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | The Hamiltonian to estimate the expectation value of. | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### estimate
estimate(
self: ,
hamiltonian: Hamiltonian,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> EstimationResult | list\[EstimationResult]
Estimates the expectation value of the given Hamiltonian using the quantum program.
**Deprecated:** `estimate` is deprecated and will no longer be supported starting on 2026-06-22. Use [observe()](#observe) instead.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | | None |
| `num_shots` | `int \| None` | | None |
| `run_via_classiq` | `bool \| None` | | None |
### submit\_estimate
submit\_estimate(
self: ,
hamiltonian: Hamiltonian,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
Initiates an execution job with the `estimate` primitive.
**Deprecated:** `submit_estimate` is deprecated and will no longer be supported starting on 2026-06-22. Use [submit\_observe()](#submit_observe) instead.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | | *required* |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | | None |
| `num_shots` | `int \| None` | | None |
| `run_via_classiq` | `bool \| None` | | None |
### batch\_estimate
batch\_estimate(
self: ,
hamiltonian: Hamiltonian,
parameters: list\[ExecutionParams]
) -> list\[EstimationResult]
Estimates the expectation value of the given Hamiltonian multiple times using the quantum program, with the given parameters for each iteration. The number of estimations is determined by the length of the parameters list.
**Deprecated:** Pass a list of parameter dicts to [observe()](#observe) instead.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | The Hamiltonian to estimate the expectation value of. | *required* |
| `parameters` | `list[ExecutionParams]` | A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | *required* |
**Returns:**
* **Type:** `list[EstimationResult]`
* List\[EstimationResult]: The results of all the estimation iterations.
### submit\_batch\_estimate
submit\_batch\_estimate(
self: ,
hamiltonian: Hamiltonian,
parameters: list\[ExecutionParams]
) -> ExecutionJob
Initiates an execution job with the `batch_estimate` primitive.
**Deprecated:** Pass a list of parameter dicts to [submit\_observe()](#submit_observe) instead.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `hamiltonian` | `Hamiltonian` | The Hamiltonian to estimate the expectation value of. | *required* |
| `parameters` | `list[ExecutionParams]` | A list of the parameters for each iteration. Each item is a dictionary where each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | *required* |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job.
### variational\_minimize
variational\_minimize(
self: ,
cost\_function: Hamiltonian | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
quantile: float = 1.0,
tolerance: float | None = None,
hosted: bool = False,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> list\[tuple\[float, ExecutionParams]]
Variationally minimizes the given cost function using the quantum program.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_function` | `Hamiltonian \| QmodExpressionCreator` | The cost function to minimize. It can be one of the following: - A quantum cost function defined by a Hamiltonian. - A classical cost function represented as a callable that returns a Qmod expression. The callable should accept `QVar`s as arguments and use names matching the Model outputs. | *required* |
| `initial_params` | `ExecutionParams` | The initial parameters for the minimization. Only Models with exactly one execution parameter are supported. This parameter must be of type `CReal` or `CArray`. The dictionary must contain a single key-value pair, where: - The key is the name of the parameter. - The value is either a float or a list of floats. | *required* |
| `max_iteration` | `int` | The maximum number of iterations for the minimization. | *required* |
| `quantile` | `float` | The quantile to use for cost estimation. | 1.0 |
| `tolerance` | `float \| None` | The tolerance for the minimization. | None |
| `hosted` | `bool` | When `True` on an IonQ backend, submit a Classiq execution job that runs the optimization loop on IonQ Hosted Hybrid in the backend. Defaults to `False`. | False |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `list[tuple[float, ExecutionParams]]`
* A list of tuples, each containing the estimated cost and the corresponding parameters for that iteration. `cost` is a float, and `parameters` is a dictionary matching the execution parameter format.
### minimize
minimize(
self: ,
cost\_function: Hamiltonian | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
quantile: float = 1.0,
tolerance: float | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> list\[tuple\[float, ExecutionParams]]
**Deprecated:** Use [variational\_minimize()](#variational_minimize) instead.
This name is kept for backward compatibility and will be removed in a future release.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_function` | `Hamiltonian \| QmodExpressionCreator` | | *required* |
| `initial_params` | `ExecutionParams` | | *required* |
| `max_iteration` | `int` | | *required* |
| `quantile` | `float` | | 1.0 |
| `tolerance` | `float \| None` | | None |
| `num_shots` | `int \| None` | | None |
| `run_via_classiq` | `bool \| None` | | None |
### submit\_variational\_minimize
submit\_variational\_minimize(
self: ,
cost\_function: Hamiltonian | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
quantile: float = 1.0,
tolerance: float | None = None,
hosted: bool = False,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
Initiates an execution job with the variational minimization primitive.
Non-blocking counterpart of [variational\_minimize()](#variational_minimize): same parameters and job,
but returns the [ExecutionJob](#executionjob) immediately.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_function` | `Hamiltonian \| QmodExpressionCreator` | The cost function to minimize. It can be one of the following: - A quantum cost function defined by a Hamiltonian. - A classical cost function represented as a callable that returns a Qmod expression. The callable should accept `QVar`s as arguments and use names matching the Model outputs. | *required* |
| `initial_params` | `ExecutionParams` | The initial parameters for the minimization. Only Models with exactly one execution parameter are supported. This parameter must be of type `CReal` or `CArray`. The dictionary must contain a single key-value pair, where: - The key is the name of the parameter. - The value is either a float or a list of floats. | *required* |
| `max_iteration` | `int` | The maximum number of iterations for the minimization. | *required* |
| `quantile` | `float` | The quantile to use for cost estimation. | 1.0 |
| `tolerance` | `float \| None` | The tolerance for the minimization. | None |
| `hosted` | `bool` | When `True` on an IonQ backend, submit a Classiq execution job that runs the optimization loop on IonQ Hosted Hybrid in the backend. Defaults to `False`. | False |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `ExecutionJob`
* The execution job. When `hosted=True` on an IonQ backend, the backend
* worker submits and polls IonQ Hosted Hybrid while this job tracks
* progress through the standard Classiq execution API.
### submit\_minimize
submit\_minimize(
self: ,
cost\_function: Hamiltonian | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
quantile: float = 1.0,
tolerance: float | None = None,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> ExecutionJob
**Deprecated:** Use [submit\_variational\_minimize()](#submit_variational_minimize) instead.
This name is kept for backward compatibility and will be removed in a future release.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_function` | `Hamiltonian \| QmodExpressionCreator` | | *required* |
| `initial_params` | `ExecutionParams` | | *required* |
| `max_iteration` | `int` | | *required* |
| `quantile` | `float` | | 1.0 |
| `tolerance` | `float \| None` | | None |
| `num_shots` | `int \| None` | | None |
| `run_via_classiq` | `bool \| None` | | None |
### estimate\_cost
estimate\_cost(
self: ,
cost\_func: Callable\[\[ParsedState], float],
parameters: ExecutionParams | None = None,
quantile: float = 1.0,
num\_shots: int | None = None,
run\_via\_classiq: bool | None = None
) -> float
Estimates circuit cost using a classical cost function.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | -------------------------------- | --------------------------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `cost_func` | `Callable[[ParsedState], float]` | classical circuit sample cost function | *required* |
| `parameters` | `ExecutionParams \| None` | execution parameters sent to 'sample' | None |
| `quantile` | `float` | drop cost values outside the specified quantile | 1.0 |
| `num_shots` | `int \| None` | Number of shots for this call only; overrides the session default when set. | None |
| `run_via_classiq` | `bool \| None` | Run via Classiq credentials for this call only; overrides the session default when set. | None |
**Returns:**
* **Type:** `float`
* cost estimation
### set\_measured\_state\_filter
set\_measured\_state\_filter(
self: ,
output\_name: str,
condition: Callable
) -> None
When simulating on a statevector simulator, emulate the behavior of postprocessing
by discarding amplitudes for which their states are "undesirable".
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ---------- | --------------------------------------------------------------------- | ---------- |
| `self` | \`\` | | *required* |
| `output_name` | `str` | The name of the register to filter | *required* |
| `condition` | `Callable` | Filter out values of the statevector for which this callable is False | *required* |
## ExecutionPreferences
Represents the execution settings for running a quantum program.
Execution preferences for running a quantum program.
For more details, refer to:
ExecutionPreferences example: [ExecutionPreferences](https://docs.classiq.io/latest/user-guide/execution/#execution-preferences)..
**Attributes:**
| Name | Type | Description |
| -------------------------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `include_zero_amplitude_outputs` | `bool` | |
| `amplitude_threshold` | `float` | |
| `noise_properties` | `Optional[NoiseProperties]` | Properties defining the noise in the quantum circuit. Defaults to `None`. |
| `random_seed` | `int` | The random seed used for the execution. Defaults to a randomly generated seed. |
| `backend_preferences` | `BackendPreferencesTypes` | Preferences for the backend used to execute the circuit. Defaults to the Classiq Simulator. |
| `num_shots` | `Optional[pydantic.PositiveInt]` | The number of shots (executions) to be performed. |
| `transpile_to_hardware` | `TranspilationOption` | Option to transpile the circuit to the hardware's basis gates before execution. Defaults to `TranspilationOption.DECOMPOSE`. |
| `job_name` | `Optional[str]` | The name of the job, with a minimum length of 1 character. |
## CostEstimateResult
Result of sample cost estimation.
**Attributes:**
| Name | Type | Description |
| ---------- | ------- | ----------- |
| `cost` | `float` | |
| `currency` | `str` | |
## BackendPreferences
Preferences for the execution of the quantum program.
**Methods:**
| Name | Description |
| ----------------------------------------- | ----------- |
| [batch\_preferences](#batch_preferences) | |
| [is\_nvidia\_backend](#is_nvidia_backend) | |
**Attributes:**
| Name | Type | Description |
| -------------------------- | ---------- | ---------------------------------------------------- |
| `hw_provider` | `Provider` | |
| `backend_service_provider` | `str` | Provider company or cloud for the requested backend. |
| `backend_name` | `str` | Name of the requested backend or target. |
### batch\_preferences
batch\_preferences(
cls: ,
backend\_names: Iterable\[str],
kwargs: Any =
) -> list\[BackendPreferences]
**Parameters:**
| Name | Type | Description | Default |
| --------------- | --------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `backend_names` | `Iterable[str]` | | *required* |
| `kwargs` | `Any` | | |
### is\_nvidia\_backend
is\_nvidia\_backend(
self:
) -> bool
**Parameters:**
| Name | Type | Description | Default |
| -------- | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| Members: | | | |
| Name | Description |
| ----------------------- | ---------------------------------------------------------------------------------- |
| `program_id_scope` | Within the scope, HTTP spans emitted by Client.request stamp `classiq.program.id`. |
| `ExecutionJobResults` | Results from `ExecutionJob.result()`: list-like with job-level metadata. |
| `SubmittedCircuit` | A quantum circuit that was submitted to the provider. |
| `ExecutionJobFilters` | Filter parameters for querying execution jobs. |
| `get_execution_jobs` | Query execution jobs. |
| `get_execution_actions` | Query execution jobs with optional filters. |
### program\_id\_scope
program\_id\_scope(
program\_id: str | None
) -> Generator\[None, None, None]
Within the scope, HTTP spans emitted by Client.request stamp
`classiq.program.id`. None = no-op, leaves any outer scope intact.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ------------- | ----------- | ---------- |
| `program_id` | `str \| None` | | *required* |
## ExecutionJobResults
Results from `ExecutionJob.result()`: list-like with job-level metadata.
**Attributes:**
| Name | Type | Description |
| -------------------------------- | ------------- | ----------- |
| `hardware_execution_duration_ms` | `int \| None` | |
## SubmittedCircuit
A quantum circuit that was submitted to the provider.
Wraps the circuit in QASM format. Use to\_qasm() for the text representation
or to\_qiskit() for a Qiskit QuantumCircuit (requires qiskit).
**Methods:**
| Name | Description |
| ------------------------ | ---------------------------------------------------------- |
| [to\_qasm](#to_qasm) | Return the circuit as a QASM string (OpenQASM 2.0 or 3.0). |
| [to\_qiskit](#to_qiskit) | Return the circuit as a Qiskit QuantumCircuit. |
### to\_qasm
to\_qasm(
self:
) -> str
Return the circuit as a QASM string (OpenQASM 2.0 or 3.0).
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### to\_qiskit
to\_qiskit(
self:
) -> Any
Return the circuit as a Qiskit QuantumCircuit. Requires qiskit.
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
## ExecutionJobFilters
Filter parameters for querying execution jobs.
All filters are combined using AND logic: only jobs matching all specified filters are returned.
Range filters (with \_min/\_max suffixes) are inclusive.
Datetime filters are compared against the job's timestamps.
**Methods:**
| Name | Description |
| ---------------------------------- | ------------------------------------------------------------------------------------ |
| [format\_filters](#format_filters) | Convert filter fields to API kwargs, excluding None values and converting datetimes. |
**Attributes:**
| Name | Type | Description |
| ---------------- | ------------------- | ----------- |
| `id` | `str \| None` | |
| `session_id` | `str \| None` | |
| `status` | `JobStatus \| None` | |
| `name` | `str \| None` | |
| `provider` | `str \| None` | |
| `backend` | `str \| None` | |
| `program_id` | `str \| None` | |
| `total_cost_min` | `float \| None` | |
| `total_cost_max` | `float \| None` | |
| `start_time_min` | `datetime \| None` | |
| `start_time_max` | `datetime \| None` | |
| `end_time_min` | `datetime \| None` | |
| `end_time_max` | `datetime \| None` | |
### format\_filters
format\_filters(
self:
) -> dict\[str, Any]
Convert filter fields to API kwargs, excluding None values and converting datetimes.
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### get\_execution\_jobs
get\_execution\_jobs(
offset: int = 0,
limit: int = 50
) -> list\[ExecutionJob]
Query execution jobs.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ----- | ------------------------------------------------- | ------- |
| `offset` | `int` | Number of results to skip (default: 0) | 0 |
| `limit` | `int` | Maximum number of results to return (default: 50) | 50 |
**Returns:**
* **Type:** `list[ExecutionJob]`
* List of ExecutionJob objects.
### get\_execution\_actions
get\_execution\_actions(
offset: int = 0,
limit: int = 50,
filters: ExecutionJobFilters | None = None
) -> pd.DataFrame
Query execution jobs with optional filters.
**Parameters:**
| Name | Type | Description | Default |
| --------- | ----------------------------- | ----------------------------------------------------------------- | ------- |
| `offset` | `int` | Number of results to skip (default: 0) | 0 |
| `limit` | `int` | Maximum number of results to return (default: 50) | 50 |
| `filters` | `ExecutionJobFilters \| None` | Optional ExecutionJobFilters object containing filter parameters. | None |
**Returns:**
* **Type:** `pd.DataFrame`
* pandas.DataFrame containing execution job information with columns:
* id, name, start\_time, end\_time, provider, backend\_name, status,
* num\_shots, program\_id, error, total\_cost, currency\_code, runtime\_ms
* (provider-reported hardware execution duration in milliseconds when available).
## BenchmarkClass
Benchmark problem classes supported by the Classiq platform.
**Attributes:**
| Name | Type | Description |
| ------------------- | --------------------- | ----------- |
| `ADDER` | `'ADDER'` | |
| `GHZ` | `'GHZ'` | |
| `QFT` | `'QFT'` | |
| `STATE_PREPARATION` | `'STATE_PREPARATION'` | |
## BenchmarkRequest
Request body for `run_benchmark`.
Submits one benchmark class across multiple `problem_sizes` and backend
targets in a single asynchronous session.
**Attributes:**
| Name | Type | Description |
| ----------------- | ------------------------------- | ----------- |
| `benchmark_class` | `BenchmarkClass` | |
| `backends` | `list[BackendExecutionDetails]` | |
| `problem_sizes` | `list[int]` | |
## BackendExecutionDetails
Execution configuration for a benchmark backend target.
The object defines how all requested `problem_sizes` should run on a
specific backend.
**Attributes:**
| Name | Type | Description |
| ---------------------- | --------------------- | ----------- |
| `backend_name` | `str` | |
| `run_via_classiq` | `bool` | |
| `transpilation_option` | `TranspilationOption` | |
| `shots` | `int` | |
| `provider_config` | `dict[str, Any]` | |
## BenchmarkSession
A handle to a submitted benchmark run.
This is the same serializable session object the API returns from the submit
endpoint (so SDK users and other services share the contract), extended with
convenience methods for fetching results from Python.
`run_benchmark` returns the session immediately, without waiting for
the executions to finish. Use `fetch_results` (or
`fetch_results_async`) to retrieve the current status and result of
every submitted job; results that reached a final status are cached and not
re-fetched.
**Methods:**
| Name | Description |
| --------------------------------------------- | ---------------------------------------------------------------------- |
| [fetch\_results\_async](#fetch_results_async) | Fetch the current status and result of every submitted job. |
| [fetch\_results](#fetch_results) | Synchronous wrapper for `fetch_results_async`. |
| [cancel\_async](#cancel_async) | Request cancellation of all incomplete jobs in this benchmark session. |
| [cancel](#cancel) | Synchronous wrapper for `cancel_async`. |
| [to\_dataframe](#to_dataframe) | Per-target benchmark table built from the results fetched so far. |
### fetch\_results\_async
fetch\_results\_async(
self: ,
\_http\_client: httpx.AsyncClient | None = None
) -> list\[BackendBenchmarkResult]
Fetch the current status and result of every submitted job.
**Parameters:**
| Name | Type | Description | Default |
| -------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `_http_client` | `httpx.AsyncClient \| None` | | None |
**Returns:**
* **Type:** list\[[BackendBenchmarkResult](#backendbenchmarkresult)]
* Latest per-job results for all successfully submitted targets in this session.
### fetch\_results
fetch\_results(
self: ,
\_http\_client: httpx.AsyncClient | None = None
) -> list\[BackendBenchmarkResult]
Synchronous wrapper for `fetch_results_async`.
**Parameters:**
| Name | Type | Description | Default |
| -------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `_http_client` | `httpx.AsyncClient \| None` | | None |
**Returns:**
* **Type:** list\[[BackendBenchmarkResult](#backendbenchmarkresult)]
* Latest per-job results for all successfully submitted targets in this session.
### cancel\_async
cancel\_async(
self: ,
\_http\_client: httpx.AsyncClient | None = None
) -> None
Request cancellation of all incomplete jobs in this benchmark session.
**Parameters:**
| Name | Type | Description | Default |
| -------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `_http_client` | `httpx.AsyncClient \| None` | | None |
### cancel
cancel(
self: ,
\_http\_client: httpx.AsyncClient | None = None
) -> None
Synchronous wrapper for `cancel_async`.
Request cancellation of all incomplete jobs in this benchmark session
**Parameters:**
| Name | Type | Description | Default |
| -------------- | --------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `_http_client` | `httpx.AsyncClient \| None` | | None |
### to\_dataframe
to\_dataframe(
self:
) -> BenchmarkResponse
Per-target benchmark table built from the results fetched so far.
Columns: problem\_size, success, error, run\_via\_classiq,
transpilation\_option, score, cost, submission\_date.
Targets whose result has not been fetched (or is still pending) appear as
unsuccessful rows with a missing score.
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
## BenchmarkSessionTarget
A single execution target within a benchmark session.
`job_id` is the internal handle used to fetch this target's result; it is
`None` when the submission itself failed (`submission_error` is then
populated). `execution_job_id` is the actual execution job id when it is
known.
**Attributes:**
| Name | Type | Description |
| ---------------------- | ------------------------------ | ----------- |
| `problem_size` | `int` | |
| `backend_name` | `str` | |
| `run_via_classiq` | `bool` | |
| `transpilation_option` | `TranspilationOption` | |
| `shots` | `int` | |
| `job_id` | `str \| None` | |
| `execution_job_id` | `str \| None` | |
| `submission_error` | `BenchmarkTargetError \| None` | |
## BenchmarkSessionsQueryResults
List response payload for benchmark session queries.
**Attributes:**
| Name | Type | Description |
| ---------- | ------------------------ | ----------- |
| `sessions` | `list[BenchmarkSession]` | |
## BenchmarkJobStatus
Status of an asynchronously tracked benchmark job.
`PENDING` means the job is still in progress.
`COMPLETED` means execution and scoring succeeded.
`FAILED` means execution or scoring failed.
`CANCELLED` means the job was cancelled before completion.
**Attributes:**
| Name | Type | Description |
| ----------- | ------------- | ----------- |
| `PENDING` | `'PENDING'` | |
| `COMPLETED` | `'COMPLETED'` | |
| `FAILED` | `'FAILED'` | |
| `CANCELLED` | `'CANCELLED'` | |
## BackendBenchmarkResult
Asynchronously-fetched result for a previously submitted benchmark job.
**Attributes:**
| Name | Type | Description |
| ------------------- | ------------------------------ | ----------- |
| `job_id` | `str` | |
| `execution_job_id` | `str \| None` | |
| `problem_size` | `int` | |
| `status` | `BenchmarkJobStatus` | |
| `backend_benchmark` | `BackendBenchmark \| None` | |
| `error` | `BenchmarkTargetError \| None` | |
## BackendBenchmarkResponse
Benchmark execution outcome for a single backend target.
**Attributes:**
| Name | Type | Description |
| ------------------- | ------------------------------ | ----------- |
| `success` | `bool` | |
| `backend_benchmark` | `BackendBenchmark \| None` | |
| `error` | `BenchmarkTargetError \| None` | |
## BenchmarkResponse
Tabular benchmark response wrapper returned by `BenchmarkSession.to_dataframe`.
**Attributes:**
| Name | Type | Description |
| -------------- | -------------- | ----------- |
| `model_config` | | |
| `data` | `pd.DataFrame` | |
## BenchmarkTargetError
Structured error details for a benchmark target failure.
**Attributes:**
| Name | Type | Description |
| -------------- | ------------- | ----------- |
| `backend_name` | `str \| None` | |
| `message` | `str` | |
## BackendBenchmark
Benchmark score payload for a completed backend run.
**Attributes:**
| Name | Type | Description |
| ----------------- | ------------------- | ----------- |
| `benchmark_class` | `BenchmarkClass` | |
| `problem_size` | `int` | |
| `score` | `float` | |
| `metadata` | `BenchmarkMetadata` | |
## BenchmarkMetadata
Metadata captured for a completed benchmark target run.
**Attributes:**
| Name | Type | Description |
| --------------------------- | --------------------------------- | ----------- |
| `benchmark_class_version` | `int` | |
| `execution_duration_ms` | `int \| None` | |
| `cost` | `float \| None` | |
| `submission_date` | `str \| None` | |
| `backend_execution_details` | `BackendExecutionDetailsResponse` | |
## BackendExecutionDetailsResponse
Backend execution settings recorded in benchmark result metadata.
**Attributes:**
| Name | Type | Description |
| ---------------------- | --------------------- | ----------- |
| `backend_name` | `str` | |
| `run_via_classiq` | `bool` | |
| `transpilation_option` | `TranspilationOption` | |
| `shots` | `int` | |
## BenchmarkClassMetadata
Metadata associated with a benchmark class.
**Attributes:**
| Name | Type | Description |
| -------- | --------------------------- | ------------------------------------------------------ |
| `limits` | `ProblemSizeLimits \| None` | Optional problem-size bounds for this benchmark class. |
## ProblemSizeLimits
Optional lower/upper bounds for valid problem sizes of a class.
**Attributes:**
| Name | Type | Description |
| ----- | ------------- | ------------------------------------------------------- |
| `min` | `int \| None` | Inclusive minimum supported problem size, when defined. |
| `max` | `int \| None` | Inclusive maximum supported problem size, when defined. |
## Functions
### calculate\_state\_vector
calculate\_state\_vector(
qprog: QuantumProgram,
backend: str | None = None,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
filters: dict\[str, Any] | None = None,
random\_seed: int | None = None,
transpilation\_option: TranspilationOption = TranspilationOption.DECOMPOSE,
amplitude\_threshold: float = 0.0,
verbose: bool = True
) -> DataFrame | list\[DataFrame]
Calculate the state vector of a quantum program.
This function is only available for Classiq simulators
(e.g. `"classiq/simulator"`).
**Parameters:**
| Name | Type | Description | Default |
| ---------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| `qprog` | `QuantumProgram` | The quantum program to be executed. | *required* |
| `backend` | `str \| None` | The simulator on which to simulate the quantum program. Specified as `"provider/backend_name"`. Use the `get_backend_details` function to see supported backends. Only Classiq simulators are supported. | None |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `filters` | `dict[str, Any] \| None` | Only states where the variables match these values will be included in the state vector. | None |
| `random_seed` | `int \| None` | The random seed for reproducibility. | None |
| `transpilation_option` | `TranspilationOption` | Advanced configuration for hardware-specific transpilation. | TranspilationOption.DECOMPOSE |
| `amplitude_threshold` | `float` | If provided, only states whose amplitude magnitude is strictly greater than this value will be included in the result. Defaults to 0 (filters exactly zero-amplitude states). | 0.0 |
| `verbose` | `bool` | Whether to print the "Submitting state-vector job to..." progress line. Set to `False` to suppress it, for example when calling `calculate_state_vector` repeatedly in a loop. Defaults to `True`. | True |
**Returns:**
* **Type:** `DataFrame \| list[DataFrame]`
* A dataframe containing the state vector, or a list of dataframes when
* `parameters` is a list.
### calculate\_unitary
calculate\_unitary(
qprog: QuantumProgram,
backend: str | None = None,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
amplitude\_threshold: float = 0.0,
random\_seed: int | None = None,
transpilation\_option: TranspilationOption = TranspilationOption.DECOMPOSE
) -> DataFrame | list\[DataFrame]
Calculate the unitary matrix of a quantum program.
This function is only available for Classiq simulators
(e.g. `"classiq/simulator"`, `"classiq/nvidia_simulator"`,
`"classiq/dgx_simulator"`) and `"google/cuquantum"`.
**Parameters:**
| Name | Type | Description | Default |
| ---------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------- |
| `qprog` | `QuantumProgram` | The quantum program to be executed. | *required* |
| `backend` | `str \| None` | The simulator on which to simulate the quantum program. Specified as `"provider/backend_name"`. | None |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. | None |
| `amplitude_threshold` | `float` | If provided, matrix elements whose magnitude is below this threshold are zeroed (same cutoff semantics as `calculate_state_vector`). | 0.0 |
| `random_seed` | `int \| None` | The random seed for reproducibility. | None |
| `transpilation_option` | `TranspilationOption` | Advanced configuration for hardware-specific transpilation. | TranspilationOption.DECOMPOSE |
**Returns:**
* **Type:** `DataFrame \| list[DataFrame]`
* A dataframe containing the unitary matrix, or a list of dataframes when
* `parameters` is a list.
### observe
observe(
qprog: QuantumProgram,
observable: SparsePauliOp,
backend: str | None = None,
estimate: bool = True,
parameters: ExecutionParams | list\[ExecutionParams] | None = None,
config: dict\[str, Any] | ProviderConfig | None = None,
num\_shots: int | None = None,
random\_seed: int | None = None,
transpilation\_option: TranspilationOption = TranspilationOption.DECOMPOSE,
run\_via\_classiq: bool = False,
verbose: bool = True
) -> float | list\[float]
Get the expectation value of the observable O with respect to the state
`\|psi>`, which is prepared by the provided quantum program.
**Parameters:**
| Name | Type | Description | Default |
| ---------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| `qprog` | `QuantumProgram` | The quantum program that generates the state \`\|psi>\` to be observed. | *required* |
| `observable` | `SparsePauliOp` | The observable O, a Hermitian operator defined as a `SparsePauliOp` (sum of Pauli terms). | *required* |
| `backend` | `str \| None` | The hardware or simulator on which to run the quantum program. Use `"simulator"` for Classiq's default simulator, or specify a backend as `"provider/backend_name"`. Use the `get_backend_details` function to see supported devices. | None |
| `estimate` | `bool` | Whether to estimate the expectation value by repeatedly measuring the circuit `num_shots` times, or calculate the exact expectation value using a simulated statevector. Note that the available options depend on the specified backend. Defaults to `True`. | True |
| `parameters` | `ExecutionParams \| list[ExecutionParams] \| None` | A dictionary of parameter values, or a list of dictionaries for batch execution. Each key should be the name of a parameter in the quantum program (parameters of the main function), and the value should be the value to set for that parameter. | None |
| `config` | dict\[str, Any] \| [ProviderConfig](#providerconfig) \| None | Provider-specific configuration, such as API keys. For full details, see the SDK reference under Providers. | None |
| `num_shots` | `int \| None` | The number of measurement shots. Only relevant when `estimate=True`. | None |
| `random_seed` | `int \| None` | The random seed for reproducibility. | None |
| `transpilation_option` | `TranspilationOption` | Advanced configuration for hardware-specific transpilation. | TranspilationOption.DECOMPOSE |
| `run_via_classiq` | `bool` | Run via Classiq's credentials while using your allocated budget. Defaults to `False`. | False |
| `verbose` | `bool` | Whether to print the "Submitting job to..." and "Job: ..." progress lines. Set to `False` to suppress them, for example when calling `observe` repeatedly in a loop. Defaults to `True`. | True |
**Returns:**
* **Type:** `float \| list[float]`
* The expectation value as a float, or a list of floats when
* `parameters` is a list.
### variational\_minimize
variational\_minimize(
qprog: QuantumProgram,
cost\_function: SparsePauliOp | QmodExpressionCreator,
initial\_params: ExecutionParams,
max\_iteration: int,
backend: str | None = None,
quantile: float = 1.0,
tolerance: float | None = None,
hosted: bool = False,
config: dict\[str, Any] | ProviderConfig | None = None,
random\_seed: int | None = None,
transpilation\_option: TranspilationOption = TranspilationOption.DECOMPOSE,
run\_via\_classiq: bool = False,
verbose: bool = True
) -> list\[tuple\[float, ExecutionParams]]
Minimize the given cost function over the parameter values of the provided
quantum program.
**Parameters:**
| Name | Type | Description | Default |
| ---------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| `qprog` | `QuantumProgram` | The parametric quantum program that generates the state (ansatz). Only quantum programs with exactly one execution parameter are supported. | *required* |
| `cost_function` | `SparsePauliOp \| QmodExpressionCreator` | The cost function to minimize. It can be one of the following: - A quantum cost function defined by a Hamiltonian. - A classical cost function represented as a callable that returns a Qmod expression. The callable should accept `QVar`s as arguments and use names matching the Model outputs. | *required* |
| `initial_params` | `ExecutionParams` | The initial parameter values for the minimization. This parameter must be of type `CReal` or `CArray`. The dictionary must contain a single key-value pair, where: - The key is the name of the parameter. - The value is either a float or a list of floats. | *required* |
| `max_iteration` | `int` | The maximum number of iterations for the minimization. | *required* |
| `backend` | `str \| None` | The hardware or simulator on which to run the quantum programs. Use `"simulator"` for Classiq's default simulator, or specify a backend as `"provider/backend_name"`. Use the `get_backend_details` function to see supported devices. | None |
| `quantile` | `float` | The quantile to use for cost estimation. | 1.0 |
| `tolerance` | `float \| None` | The tolerance for the minimization. | None |
| `hosted` | `bool` | When `True` and the configured backend is IonQ, delegate the optimization loop to IonQ's Hosted Hybrid Service instead of running it locally. Defaults to `False`. | False |
| `config` | dict\[str, Any] \| [ProviderConfig](#providerconfig) \| None | Provider-specific configuration, such as API keys. For full details, see the SDK reference under Providers. | None |
| `random_seed` | `int \| None` | The random seed for reproducibility. | None |
| `transpilation_option` | `TranspilationOption` | Advanced configuration for hardware-specific transpilation. | TranspilationOption.DECOMPOSE |
| `run_via_classiq` | `bool` | Run via Classiq's credentials while using your allocated budget. Defaults to `False`. | False |
| `verbose` | `bool` | Whether to print the "Submitting job to..." progress line. Set to `False` to suppress it, for example when calling `variational_minimize` repeatedly in a loop. Defaults to `True`. | True |
**Returns:**
* **Type:** `list[tuple[float, ExecutionParams]]`
* A list of tuples, each containing the estimated cost and the
* corresponding parameters for that iteration. `cost` is a float,
* and `parameters` is a dictionary matching the execution parameter
* format.
### execute
execute(
quantum\_program: QuantumProgram
) -> ExecutionJob
Execute a quantum program. The preferences for execution are set on the quantum program using the method `set_execution_preferences`.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | ---------------- | ---------------------------------------------------------------------------- | ---------- |
| `quantum_program` | `QuantumProgram` | The quantum program to execute. This is the result of the synthesize method. | *required* |
**Returns:**
* **Type:** `ExecutionJob`
* The result of the execution.
### estimate\_sample\_cost
estimate\_sample\_cost(
quantum\_program: QuantumProgram,
execution\_options: ExecutionPreferences | str,
config: dict\[str, Any] | None = None,
num\_shots: int | None = None,
transpilation\_option: TranspilationOption = TranspilationOption.DECOMPOSE
) -> CostEstimateResult
Estimate the cost for sampling a quantum program.
`execution_options` may be a full `ExecutionPreferences` object, or the same
**backend specifier string** used by `sample()` (for example `"braket/SV1"` or
`"azure/ionq.simulator"`). When it is a string, optional `config`,
`num_shots`, and `transpilation_option` are applied like the `sample()` helpers.
String backends are always resolved with **run via Classiq** when the provider supports
it (no user cloud credentials required for cost estimation).
**Parameters:**
| Name | Type | Description | Default |
| ---------------------- | ---------------------------------------------------- | -------------------------------------------------------------------------------- | ----------------------------- |
| `quantum_program` | `QuantumProgram` | The quantum program (output of synthesize). | *required* |
| `execution_options` | [ExecutionPreferences](#executionpreferences) \| str | Execution preferences or a backend specifier string. | *required* |
| `config` | `dict[str, Any] \| None` | Passed only for string backends (non-credential options, e.g. Azure `location`). | None |
| `num_shots` | `int \| None` | Shots when using a string backend; ignored when using `ExecutionPreferences`. | None |
| `transpilation_option` | `TranspilationOption` | Transpilation when using a string backend; ignored otherwise. | TranspilationOption.DECOMPOSE |
**Returns:**
* **Type:** [CostEstimateResult](#costestimateresult)
* CostEstimateResult with cost and currency.
### estimate\_sample\_batch\_cost
estimate\_sample\_batch\_cost(
quantum\_program: QuantumProgram,
execution\_backend: BackendPreferencesTypes | str,
transpilation\_level: TranspilationOption = TranspilationOption.DECOMPOSE,
shots: int = 1000,
params: list\[dict] | None = None,
config: dict\[str, Any] | None = None
) -> CostEstimateResult
Estimate the cost for batch sampling a quantum program.
`execution_backend` may be backend preferences or a `sample()`-style specifier string.
With a string backend, pass non-credential options in `config`; resolution uses **run via
Classiq** whenever the provider supports it (same rule as `estimate_sample_cost`).
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | -------------------------------- | --------------------------------------------------------------------- | ----------------------------- |
| `quantum_program` | `QuantumProgram` | The quantum program (output of synthesize). | *required* |
| `execution_backend` | `BackendPreferencesTypes \| str` | Backend preferences or specifier string. | *required* |
| `transpilation_level` | `TranspilationOption` | Transpilation option for the circuit. | TranspilationOption.DECOMPOSE |
| `shots` | `int` | Number of shots per sample. | 1000 |
| `params` | `list[dict] \| None` | Optional list of parameter sets for batch. If None, single sample. | None |
| `config` | `dict[str, Any] \| None` | Non-credential provider options when `execution_backend` is a string. | None |
**Returns:**
* **Type:** [CostEstimateResult](#costestimateresult)
* CostEstimateResult with cost and currency.
### assign\_parameters
assign\_parameters(
quantum\_program: QuantumProgram,
parameters: ExecutionParams
) -> QuantumProgram
Assign parameters to a parametric quantum program.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | ----------------- | -------------------------------------------------------------------------------- | ---------- |
| `quantum_program` | `QuantumProgram` | The quantum program to be assigned. This is the result of the synthesize method. | *required* |
| `parameters` | `ExecutionParams` | The parameter assignments. | *required* |
**Returns:**
* **Type:** `QuantumProgram`
* The quantum program after assigning parameters.
### transpile
transpile(
quantum\_program: QuantumProgram,
preferences: Preferences | None = None
) -> QuantumProgram
Transpiles a quantum program.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | --------------------- | ------------------------------------------------------------------------------ | ---------- |
| `quantum_program` | `QuantumProgram` | The quantum program to transpile. This is the result of the synthesize method. | *required* |
| `preferences` | `Preferences \| None` | The transpilation preferences. | None |
**Returns:**
* **Type:** `QuantumProgram`
* The result of the transpilation (Optional).
### get\_budget
get\_budget(
provider: ProviderVendor | None = None
) -> UserBudgets
Retrieve the user's budget information for quantum computing resources.
**Parameters:**
| Name | Type | Description | Default |
| ---------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | ------- |
| `provider` | `ProviderVendor \| None` | (Optional) The quantum backend provider to filter budgets by. If not provided, budgets for all providers will be returned. | None |
**Returns:**
* **Type:** `UserBudgets`
* An object containing the user's budget information.
### set\_budget\_limit
set\_budget\_limit(
provider: ProviderVendor,
limit: float
) -> UserBudgets
Set a budget limit for a specific quantum backend provider.
**Parameters:**
| Name | Type | Description | Default |
| ---------- | ---------------- | --------------------------------------------------------------------------------------- | ---------- |
| `provider` | `ProviderVendor` | The quantum backend provider for which to set the budget limit. | *required* |
| `limit` | `float` | The budget limit to set. Must be greater than zero and not exceed the available budget. | *required* |
**Returns:**
* **Type:** `UserBudgets`
* An object containing the updated budget information.
### clear\_budget\_limit
clear\_budget\_limit(
provider: ProviderVendor
) -> UserBudgets
Clear the budget limit for a specific quantum backend provider.
**Parameters:**
| Name | Type | Description | Default |
| ---------- | ---------------- | ----------------------------------------------------------------- | ---------- |
| `provider` | `ProviderVendor` | The quantum backend provider for which to clear the budget limit. | *required* |
**Returns:**
* **Type:** `UserBudgets`
* An object containing the updated budget information.
### run\_benchmark
run\_benchmark(
request: BenchmarkRequest
) -> BenchmarkSession
Submit a benchmark class across problem sizes and execution targets.
Every backend in `request.backends` is paired with every value in
`request.problem_sizes` and submitted up front. The call returns
immediately with a `BenchmarkSession` and does not wait for
executions to complete.
Use `BenchmarkSession.fetch_results` or `BenchmarkSession.fetch_results_async`
to poll statuses and fetch
results. Targets that fail during submission are still included in the
session with `submission_error` populated and no `job_id`.
**Parameters:**
| Name | Type | Description | Default |
| --------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `request` | [BenchmarkRequest](#benchmarkrequest) | Benchmark submission settings including benchmark class, requested problem sizes, and per-target backend execution configuration. | *required* |
**Returns:**
* **Type:** [BenchmarkSession](#benchmarksession)
* A `BenchmarkSession` containing session metadata, per-target submission handles, and any fetched results.
### get\_benchmark\_sessions
get\_benchmark\_sessions() -> list\[BenchmarkSession]
Return all benchmark sessions stored for the user.
**Returns:**
* **Type:** list\[[BenchmarkSession](#benchmarksession)]
* Benchmark sessions for the current user, including session ids and any
* results fetched so far. Use this after reconnecting to resume in-flight runs.
### get\_benchmark\_classes
get\_benchmark\_classes() -> dict\[BenchmarkClass, BenchmarkClassMetadata]
Return benchmark classes supported by the platform.
**Returns:**
* **Type:** dict\[[BenchmarkClass](#benchmarkclass), [BenchmarkClassMetadata](#benchmarkclassmetadata)]
* Mapping from each supported `BenchmarkClass` to `BenchmarkClassMetadata`, including any known problem-size limits.
# Classiq SDK Reference
Source: https://docs.classiq.io/sdk-reference/index
This reference manual provides a comprehensive guide to the Classiq SDK, which facilitates working with quantum models created using the Qmod language. It serves as a resource for understanding the tools and APIs required to synthesize quantum models into executable programs, visualize their structure and behavior, execute them on quantum hardware or simulators, and retrieve execution results.
See the [Qmod Reference](/qmod-reference/index) to learn how to design and define quantum algorithms using the Qmod language. Once your models are ready, use this SDK Reference to transform them into functional quantum applications and analyze their execution outcomes.
# Aws
Source: https://docs.classiq.io/sdk-reference/providers/AWS
For **`emulate`** on Amazon Braket, see [Device emulation (emulate)](../../user-guide/execution/cloud-providers/amazon-backends#device-emulation-emulate) in the execution user guide.
## AwsBackendPreferences
AWS-specific backend preferences for quantum computing tasks using Amazon Braket.
This class contains configuration options specific to Amazon Braket, including the AWS role
ARN, S3 bucket details, and the folder path within the S3 bucket. It extends the base
`BackendPreferences` class to provide additional properties required for interaction with
Amazon Braket.
**Attributes:**
| Name | Type | Description |
| -------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `backend_service_provider` | `ProviderTypeVendor.AMAZON_BRAKET` | The service provider for the backend, which is Amazon Braket. |
| `aws_access_key_id` | `str` | The access key id of AWS user with full braket access |
| `aws_secret_access_key` | `str` | The secret key assigned to the access key id for the user with full braket access. |
| `s3_bucket_name` | `str` | The name of the S3 bucket where results and other related data will be stored. This field should contain a valid S3 bucket name under your AWS account. |
| `s3_folder` | `pydantic_backend.PydanticS3BucketKey` | The folder path within the specified S3 bucket. This allows for organizing results and data under a specific directory within the S3 bucket. |
| `emulate` | `bool` | Whether to run the job on a simulator instead of a real quantum device. |
# Alice And Bob
Source: https://docs.classiq.io/sdk-reference/providers/Alice and Bob
## AliceBobBackendPreferences
Backend preferences specific to Alice\&Bob for quantum computing tasks.
This class includes configuration options for setting up a backend using Alice\&Bob's quantum hardware.
It extends the base `BackendPreferences` class and provides additional parameters required for working
with Alice\&Bob's cat qubits, including settings for photon dissipation rates, repetition code distance,
and the average number of photons.
**Attributes:**
| Name | Type | Description |
| -------------------------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | `dict[str, Any]` | |
| `backend_service_provider` | `ProviderTypeVendor.ALICE_BOB` | The service provider for the backend, which is Alice\&Bob. |
| `distance` | `Optional[int]` | The number of times information is duplicated in the repetition code. - **Tooltip**: Phase-flip probability decreases exponentially with this parameter, bit-flip probability increases linearly. - **Supported Values**: 3 to 300, though practical values are usually lower than 30. - **Default**: None. |
| `kappa_1` | `Optional[float]` | The rate at which the cat qubit loses one photon, creating a bit-flip. - **Tooltip**: Lower values mean lower error rates. - **Supported Values**: 10 to 10^5. Current hardware is at \~10^3. - **Default**: None. |
| `kappa_2` | `Optional[float]` | The rate at which the cat qubit is stabilized using two-photon dissipation. - **Tooltip**: Higher values mean lower error rates. - **Supported Values**: 100 to 10^9. Current hardware is at \~10^5. - **Default**: None. |
| `average_nb_photons` | `Optional[float]` | The average number of photons. - **Tooltip**: Bit-flip probability decreases exponentially with this parameter, phase-flip probability increases linearly. - **Supported Values**: 4 to 10^5, though practical values are usually lower than 30. - **Default**: None. |
| `api_key` | `str` | The API key required to access Alice\&Bob's quantum hardware. - **Required**: Yes. |
## AliceBobBackendNames
Alice & Bob backend names which Classiq Supports running on.
**Attributes:**
| Name | Type | Description |
| ---------------- | ------------------ | ----------- |
| `PERFECT_QUBITS` | `'PERFECT_QUBITS'` | |
| `LOGICAL_TARGET` | `'LOGICAL_TARGET'` | |
| `LOGICAL_EARLY` | `'LOGICAL_EARLY'` | |
| `TRANSMONS` | `'TRANSMONS'` | |
# Azure
Source: https://docs.classiq.io/sdk-reference/providers/Azure
For **`emulate`** on Azure Quantum (IonQ `ionq.qpu.*` targets), see [IonQ hardware noise simulation on Azure Quantum (emulate)](../../user-guide/execution/cloud-providers/azure-backends#ionq-hardware-noise-simulation-on-azure-quantum-emulate) in the execution user guide.
## AzureBackendPreferences
This class inherits from RunViaClassiqBackendPreferences.
This is where you specify Azure Quantum preferences.
See usage in the [Azure Backend Documentation](https://docs.classiq.io/latest/sdk-reference/providers/Azure/).
**Attributes:**
| Name | Type | Description |
| ---------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `backend_service_provider` | `ProviderTypeVendor.AZURE_QUANTUM` | |
| `location` | `str` | Azure personal resource region. Defaults to `"East US"`. |
| `credentials` | `Optional[AzureCredential]` | The service principal credential to access personal quantum workspace. Defaults to `None`. |
| `ionq_error_mitigation_flag` | `Optional[bool]` | Error mitigation configuration upon running on IonQ via Azure. Defaults to `False`. |
| `emulate` | `bool` | If True, request IonQ hardware noise simulation on Azure Quantum when `backend_name` is an IonQ QPU (`ionq.qpu.*`). If the target is not an IonQ QPU (including `ionq.simulator` and non-IonQ providers), the flag has no effect. Defaults to `False`. |
| `run_via_classiq` | `bool` | When omitted, derived from `credentials` (`True` when `credentials` is `None`). |
## AzureCredential
Represents the credentials and configuration required to authenticate with Azure services.
**Attributes:**
| Name | Type | Description |
| --------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `model_config` | | |
| `tenant_id` | `str` | Azure Tenant ID used to identify the directory in which the application is registered. |
| `client_id` | `str` | Azure Client ID, also known as the application ID, which is used to authenticate the application. |
| `client_secret` | `str` | Azure Client Secret associated with the application, used for authentication. |
| `resource_id` | `pydantic_backend.PydanticAzureResourceIDType` | Azure Resource ID, including the subscription ID, resource group, and workspace, typically used for personal resources. |
## AzureQuantumBackendNames
AzureQuantum backend names which Classiq Supports running on.
**Attributes:**
| Name | Type | Description |
| ------------------------------- | --------------------------------- | ----------- |
| `IONQ_ARIA_1` | `'ionq.qpu.aria-1'` | |
| `IONQ_ARIA_2` | `'ionq.qpu.aria-2'` | |
| `IONQ_QPU` | `'ionq.qpu'` | |
| `IONQ_QPU_FORTE` | `'ionq.qpu.forte-1'` | |
| `IONQ_SIMULATOR` | `'ionq.simulator'` | |
| `MICROSOFT_ESTIMATOR` | `'microsoft.estimator'` | |
| `MICROSOFT_FULLSTATE_SIMULATOR` | `'microsoft.simulator.fullstate'` | |
| `RIGETTI_SIMULATOR` | `'rigetti.sim.qvm'` | |
| `RIGETTI_ANKAA2` | `'rigetti.qpu.ankaa-2'` | |
| `RIGETTI_ANKAA9` | `'rigetti.qpu.ankaa-9q-1'` | |
| `QCI_MACHINE1` | `'qci.machine1'` | |
| `QCI_NOISY_SIMULATOR` | `'qci.simulator.noisy'` | |
| `QCI_SIMULATOR` | `'qci.simulator'` | |
| `QUANTINUUM_API_VALIDATOR1_1` | `'quantinuum.sim.h1-1sc'` | |
| `QUANTINUUM_API_VALIDATOR1_2` | `'quantinuum.sim.h1-2sc'` | |
| `QUANTINUUM_API_VALIDATOR2_1` | `'quantinuum.sim.h2-1sc'` | |
| `QUANTINUUM_QPU1_1` | `'quantinuum.qpu.h1-1'` | |
| `QUANTINUUM_QPU1_2` | `'quantinuum.qpu.h1-2'` | |
| `QUANTINUUM_SIMULATOR1_1` | `'quantinuum.sim.h1-1e'` | |
| `QUANTINUUM_SIMULATOR1_2` | `'quantinuum.sim.h1-2e'` | |
| `QUANTINUUM_QPU2` | `'quantinuum.qpu.h2-1'` | |
| `QUANTINUUM_SIMULATOR2` | `'quantinuum.sim.h2-1e'` | |
# Braket
Source: https://docs.classiq.io/sdk-reference/providers/Braket
## AmazonBraketBackendNames
Amazon Braket backend names which Classiq Supports running on.
**Attributes:**
| Name | Type | Description |
| ------------------------ | --------------- | ----------- |
| `AMAZON_BRAKET_SV1` | `'SV1'` | |
| `AMAZON_BRAKET_TN1` | `'TN1'` | |
| `AMAZON_BRAKET_DM1` | `'dm1'` | |
| `AMAZON_BRAKET_ASPEN_11` | `'Aspen-11'` | |
| `AMAZON_BRAKET_M_1` | `'Aspen-M-1'` | |
| `AMAZON_BRAKET_IONQ` | `'IonQ Device'` | |
| `AMAZON_BRAKET_LUCY` | `'Lucy'` | |
# C12
Source: https://docs.classiq.io/sdk-reference/providers/C12
## C12BackendPreferences
Represents the backend preferences specific to C12.
**Attributes:**
| Name | Type | Description |
| -------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `backend_service_provider` | `ProviderTypeVendor.C12` | |
| `parameters` | `dict` | |
| `backend_name` | `str` | Name of the requested backend or target. |
| `result_format` | `str` | Result format of the job; one of "counts", "state\_vector", or "density\_matrix". Defaults to "counts". |
| `inilabel` | `str \| None` | Initial state specified using a binary label format (e.g. "00", "01"). Mutually exclusive with inistatevector. |
| `inistatevector` | `str \| None` | Initial state vector as a comma-separated list of complex values (e.g. "1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j"). Mutually exclusive with inilabel. |
| `ininoisy` | `bool \| None` | Whether to use noisy initialization of the circuit. |
## C12BackendNames
**Attributes:**
| Name | Type | Description |
| ----------- | ----------------- | ----------- |
| `SIMULATOR` | `'c12sim-iswap'` | |
| `SQUARED` | `'squared-iswap'` | |
# Classiq
Source: https://docs.classiq.io/sdk-reference/providers/Classiq
## ClassiqBackendPreferences
Represents backend preferences specific to Classiq quantum computing targets.
This class is used to configure the backend options for executing quantum circuits on Classiq's platform.
The relevant backend names for Classiq targets are specified in `ClassiqSimulatorBackendNames` & `ClassiqNvidiaBackendNames`.
**Methods:**
| Name | Description |
| ----------------------------------------- | ----------- |
| [is\_nvidia\_backend](#is_nvidia_backend) | |
**Attributes:**
| Name | Type | Description |
| -------------------------- | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `backend_service_provider` | `ProviderTypeVendor.CLASSIQ` | The provider vendor (Classiq). |
| `backend_name` | `str` | Name of the requested backend or target. |
| `use_double_precision` | `bool` | When True, Nvidia and Braket Nvidia simulators use double precision; when False (default), they use single precision. Only applies to Nvidia backends; ignored for other Classiq simulators. |
| `noise_model` | `str \| None` | Optional named preset simulator noise (see `CLASSIQ_NOISE_MODELS`). Mutually exclusive with `simulator_noise_spec`. |
| `simulator_noise_spec` | `ClassiqSimulatorNoiseSpecification \| None` | Optional user-defined noise (see `ClassiqSimulatorNoiseSpecification` in `classiq.interface.backend.simulator_noise` for field semantics and usage). Mutually exclusive with `noise_model`. |
### is\_nvidia\_backend
is\_nvidia\_backend(
self:
) -> bool
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
## ClassiqSimulatorBackendNames
The simulator backends available in the Classiq provider.
**Attributes:**
| Name | Type | Description |
| -------------------------------- | ---------------------------------- | ----------- |
| `SIMULATOR` | `'simulator'` | |
| `SIMULATOR_STATEVECTOR` | `'simulator_statevector'` | |
| `SIMULATOR_UNITARY` | `'simulator_unitary'` | |
| `SIMULATOR_DENSITY_MATRIX` | `'simulator_density_matrix'` | |
| `SIMULATOR_MATRIX_PRODUCT_STATE` | `'simulator_matrix_product_state'` | |
## ClassiqNvidiaBackendNames
Classiq's Nvidia simulator backend names.
**Methods:**
| Name | Description |
| -------------------------------------------------------- | ----------- |
| [is\_braket\_nvidia\_backend](#is_braket_nvidia_backend) | |
**Attributes:**
| Name | Type | Description |
| ------------------------------------- | --------------------------------------- | ----------- |
| `SIMULATOR` | `'nvidia_simulator'` | |
| `SIMULATOR_STATEVECTOR` | `'nvidia_simulator_statevector'` | |
| `SIMULATOR_UNITARY` | `'nvidia_simulator_unitary'` | |
| `BRAKET_NVIDIA_SIMULATOR` | `'braket_nvidia_simulator'` | |
| `BRAKET_NVIDIA_SIMULATOR_STATEVECTOR` | `'braket_nvidia_simulator_statevector'` | |
### is\_braket\_nvidia\_backend
is\_braket\_nvidia\_backend(
self:
) -> bool
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
# Gcp
Source: https://docs.classiq.io/sdk-reference/providers/GCP
## GCPBackendPreferences
Represents the backend preferences specific to Google Cloud Platform (GCP) services.
Inherits from `BackendPreferences` and sets the backend service provider to Google.
**Methods:**
| Name | Description |
| ----------------------------------------- | ----------- |
| [is\_nvidia\_backend](#is_nvidia_backend) | |
**Attributes:**
| Name | Type | Description |
| -------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `use_double_precision` | `bool` | |
| `backend_service_provider` | `ProviderTypeVendor.GOOGLE` | Indicates the backend service provider as Google, |
| `noise_model` | `str \| None` | Optional named preset simulator noise (see `CLASSIQ_NOISE_MODELS`). Mutually exclusive with `simulator_noise_spec`. |
| `simulator_noise_spec` | `ClassiqSimulatorNoiseSpecification \| None` | Optional user-defined noise; same type as on `ClassiqBackendPreferences`. Mutually exclusive with `noise_model`. |
### is\_nvidia\_backend
is\_nvidia\_backend(
self:
) -> bool
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
# Ibm
Source: https://docs.classiq.io/sdk-reference/providers/IBM
For **`emulate`** on IBM Quantum, see [IBM hardware noise simulation (emulate)](../../user-guide/execution/cloud-providers/ibm-backends#ibm-hardware-noise-simulation-emulate) in the execution user guide.
## IBMBackendPreferences
Represents the backend preferences specific to IBM Quantum services.
Inherits from `BackendPreferences` and adds additional fields and validations
specific to IBM Quantum backends.
**Attributes:**
| Name | Type | Description |
| -------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `backend_service_provider` | `ProviderTypeVendor.IBM_CLOUD` | Indicates the backend service provider as IBM Cloud. |
| `access_token` | `Optional[str]` | The IBM Cloud access token to be used with IBM Quantum hosted backends. Defaults to `None`. |
| `channel` | `str` | Channel to use for IBM cloud backends. Defaults to `"ibm_cloud"`. |
| `instance_crn` | `str` | The IBM Cloud instance CRN (Cloud Resource Name) for the IBM Quantum service. |
| `run_via_classiq` | `bool` | Run via Classiq's credentials. Defaults to `False`. |
| `emulate` | `bool` | If True, run on a Classiq-hosted simulator with a noise model derived from the IBM backend name. Defaults to `False`. |
# Ionq
Source: https://docs.classiq.io/sdk-reference/providers/IonQ
For **`emulate`** on IonQ (direct API), see [IonQ hardware noise simulation (emulate)](../../user-guide/execution/cloud-providers/ionq-backends#ionq-hardware-noise-simulation-emulate) in the execution user guide.
## IonqBackendPreferences
Represents the backend preferences specific to IonQ services.
Inherits from `BackendPreferences` and adds additional fields and configurations
specific to IonQ backends
**Attributes:**
| Name | Type | Description |
| -------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `parameters` | `dict[str, Any]` | |
| `backend_service_provider` | `ProviderTypeVendor.IONQ` | Indicates the backend service provider as IonQ. |
| `api_key` | `PydanticIonQApiKeyType` | The IonQ API key required for accessing IonQ's quantum computing services. |
| `error_mitigation` | `bool` | A configuration option to enable or disable error mitigation during execution. Defaults to `False`. |
| `run_via_classiq` | `bool` | Running via Classiq's credentials while using user's allocated budget. |
| `emulate` | `bool` | If True, run on the IonQ simulator with a noise model derived from the backend name (e.g. qpu.aria-1 -> aria-1). Defaults to `False`. |
## IonqBackendNames
IonQ backend names which Classiq Supports running on.
**Attributes:**
| Name | Type | Description |
| ----------- | --------------- | ----------- |
| `SIMULATOR` | `'simulator'` | |
| `HARMONY` | `'qpu.harmony'` | |
| `ARIA_1` | `'qpu.aria-1'` | |
| `ARIA_2` | `'qpu.aria-2'` | |
| `FORTE_1` | `'qpu.forte-1'` | |
# Oqc
Source: https://docs.classiq.io/sdk-reference/providers/OQC
## OQCBackendPreferences
This class inherits from `BackendPreferences`.
This is where you specify OQC preferences.
**Attributes:**
| Name | Type | Description |
| -------------------------- | ------------------------ | ------------ |
| `backend_service_provider` | `ProviderTypeVendor.OQC` | |
| `username` | `str` | OQC username |
| `password` | `str` | OQC password |
## OQCBackendNames
OQC backend names which Classiq Supports running on.
**Attributes:**
| Name | Type | Description |
| ------ | -------- | ----------- |
| `LUCY` | `'Lucy'` | |
# Index
Source: https://docs.classiq.io/sdk-reference/providers/index
# Providers
## Provider
This class defines all Providers that Classiq supports.
This is mainly used in backend\_preferences when specifying where do we want to execute the defined model.
**Attributes:**
| Name | Type | Description |
| --------------- | ----------------- | ----------- |
| `IBM_QUANTUM` | `'IBM Quantum'` | |
| `AZURE_QUANTUM` | `'Azure Quantum'` | |
| `AMAZON_BRAKET` | `'Amazon Braket'` | |
| `IONQ` | `'IonQ'` | |
| `CLASSIQ` | `'Classiq'` | |
| `GOOGLE` | `'Google'` | |
| `ALICE_AND_BOB` | `'Alice & Bob'` | |
| `OQC` | `'OQC'` | |
| `INTEL` | `'Intel'` | |
| `AQT` | `'AQT'` | |
| `CINECA` | `'CINECA'` | |
| `JHPC` | `'JHPC'` | |
| `C12` | `'C12'` | |
| `id` | `ProviderIDEnum` | |
# Simulator Noise
Source: https://docs.classiq.io/sdk-reference/providers/simulator-noise
Members:
| Name | Description |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `DepolarizingNoiseOnGate` | Depolarizing noise applied uniformly to every occurrence of a named gate: the same error statistics on all qubit positions where that gate appears. |
| `LocalDepolarizingNoiseOnGate` | Depolarizing noise on a named gate only when it acts on a specific ordered tuple of qubit indices (other placements of the same gate name are unaff... |
| `PauliNoiseTerm` | One Pauli operator and its probability within a mixed Pauli noise channel. |
| `PauliNoiseOnGate` | A mixed Pauli channel applied uniformly to every occurrence of a named gate (same statistics on all positions). |
| `ThermalRelaxationNoiseOnGate` | Single-qubit amplitude-and-phase relaxation over the gate duration `time`. |
| `LocalReadoutNoise` | Readout confusion for one simulator qubit using a full 2-by-2 assignment matrix (see module docstring). |
| `ClassiqSimulatorNoiseSpecification` | Complete custom noise description for Classiq noisy simulators. |
## DepolarizingNoiseOnGate
Depolarizing noise applied uniformly to every occurrence of a named gate: the same
error statistics on all qubit positions where that gate appears.
**Attributes:**
| Name | Type | Description |
| ------------- | -------------------------- | ----------- |
| `gate` | `str` | |
| `probability` | `PydanticProbabilityFloat` | |
| `num_qubits` | `Literal[1, 2]` | |
## LocalDepolarizingNoiseOnGate
Depolarizing noise on a named gate only when it acts on a specific ordered tuple of
qubit indices (other placements of the same gate name are unaffected).
**Attributes:**
| Name | Type | Description |
| -------- | ----------- | ----------- |
| `qubits` | `list[int]` | |
## PauliNoiseTerm
One Pauli operator and its probability within a mixed Pauli noise channel.
**Attributes:**
| Name | Type | Description |
| ------------- | ------- | ----------- |
| `pauli` | `str` | |
| `probability` | `float` | |
## PauliNoiseOnGate
A mixed Pauli channel applied uniformly to every occurrence of a named gate (same
statistics on all positions). Include an identity Pauli term when you want a fraction
of executions to stay error-free.
**Attributes:**
| Name | Type | Description |
| ------------- | ---------------------- | ----------- |
| `gate` | `str` | |
| `num_qubits` | `Literal[1, 2]` | |
| `pauli_terms` | `list[PauliNoiseTerm]` | |
## ThermalRelaxationNoiseOnGate
Single-qubit amplitude-and-phase relaxation over the gate duration `time`.
Use only with single-qubit `gate` names; the channel acts on one tensor factor.
**Attributes:**
| Name | Type | Description |
| -------------------------- | ------- | ----------- |
| `gate` | `str` | |
| `t1` | `float` | |
| `t2` | `float` | |
| `time` | `float` | |
| `excited_state_population` | `float` | |
## LocalReadoutNoise
Readout confusion for one simulator qubit using a full 2-by-2 assignment matrix
(see module docstring).
**Attributes:**
| Name | Type | Description |
| -------------------------- | ------------------- | ----------- |
| `qubit` | `int` | |
| `assignment_probabilities` | `list[list[float]]` | |
## ClassiqSimulatorNoiseSpecification
Complete custom noise description for Classiq noisy simulators. Combine any subset
of the fields; an empty specification means an ideal (noise-free) simulation.
Global readout settings (symmetric bit-flip probability or a shared 2-by-2 assignment
matrix for every qubit) cannot both be set. Per-qubit readout in
`local_readout_errors` uses the same matrix convention as in `LocalReadoutNoise`.
**Attributes:**
| Name | Type | Description |
| ---------------------------------- | ------------------------------------ | ----------- |
| `basis_gates` | `list[str] \| None` | |
| `readout_bit_flip_probability` | `PydanticProbabilityFloat \| None` | |
| `readout_assignment_probabilities` | `list[list[float]] \| None` | |
| `local_readout_errors` | `list[LocalReadoutNoise]` | |
| `gate_depolarizing_errors` | `list[DepolarizingNoiseOnGate]` | |
| `local_depolarizing_errors` | `list[LocalDepolarizingNoiseOnGate]` | |
| `gate_pauli_errors` | `list[PauliNoiseOnGate]` | |
| `gate_thermal_relaxation_errors` | `list[ThermalRelaxationNoiseOnGate]` | |
# Classical Types
Source: https://docs.classiq.io/sdk-reference/qmod/classical-types
This is a list of the classical types that are built-in in `Qmod`.
For more information regarding classical types see: [classical types](/qmod-reference/language-reference/classical-types).
Members:
| Name | Description |
| ----------------- | ------------------------------------------------------------------------------------------ |
| `Pauli` | Enumeration for the Pauli matrices used in quantum computing. |
| `PauliTerm` | A term in a Hamiltonian, represented as a product of single-qubit Pauli matrices. |
| `IndexedPauli` | A single-qubit Pauli matrix on a specific qubit given by its index. |
| `SparsePauliTerm` | A term in the Hamiltonian, represented as a sparse product of single-qubit Pauli matrices. |
| `SparsePauliOp` | Represents a collection of sparse Pauli operators. |
## Pauli
Enumeration for the Pauli matrices used in quantum computing.
Represents the four Pauli matrices used in quantum mechanics: Identity (I), X, Y, and Z operators.
The Pauli matrices are defined as:
$$
I = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix}
$$
$$
X = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}
$$
$$
Y = \begin{pmatrix} 0 & -i \\ i & 0 \end{pmatrix}
$$
$$
Z = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix}
$$
**Attributes:**
| Name | Type | Description |
| ---- | ----- | -------------------------------- |
| `I` | `'0'` | |
| `X` | `'1'` | |
| `Y` | `'2'` | |
| `Z` | `'3'` | |
| `I` | `int` | The identity operator (value 0). |
| `X` | `int` | The Pauli-X operator (value 1). |
| `Y` | `int` | The Pauli-Y operator (value 2). |
| `Z` | `int` | The Pauli-Z operator (value 3). |
## PauliTerm
A term in a Hamiltonian, represented as a product of single-qubit Pauli matrices.
**Attributes:**
| Name | Type | Description |
| ------------- | --------------- | ------------------------------------------------------------------------------------- |
| `pauli` | `CArray[Pauli]` | The list of the chosen Pauli operators in the term, corresponds to a product of them. |
| `coefficient` | `CReal` | The coefficient of the term (floating number). |
## IndexedPauli
A single-qubit Pauli matrix on a specific qubit given by its index.
**Attributes:**
| Name | Type | Description |
| ------- | ------- | ----------------------------------------- |
| `pauli` | `Pauli` | The Pauli operator. |
| `index` | `CInt` | The index of the qubit being operated on. |
## SparsePauliTerm
A term in the Hamiltonian, represented as a sparse product of single-qubit Pauli
matrices.
Attributes:
paulis (CArray\[IndexedPauli]): The list of chosen sparse Pauli operators in the term corresponds to a product of them. (See IndexedPauli)
coefficient (CReal): The coefficient of the term (floating number).
**Methods:**
| Name | Description |
| -------------------------- | ----------- |
| [cmp\_paulis](#cmp_paulis) | |
**Attributes:**
| Name | Type | Description |
| ------------- | ---------------------- | ----------- |
| `paulis` | `CArray[IndexedPauli]` | |
| `coefficient` | `CReal` | |
### cmp\_paulis
cmp\_paulis(
a: SparsePauliTerm,
b: SparsePauliTerm
) -> int
**Parameters:**
| Name | Type | Description | Default |
| ---- | ----------------- | ----------- | ---------- |
| `a` | `SparsePauliTerm` | | *required* |
| `b` | `SparsePauliTerm` | | *required* |
## SparsePauliOp
Represents a collection of sparse Pauli operators.
**Methods:**
| Name | Description |
| --------------------------------------------------------- | ----------- |
| [get\_tuples\_representation](#get_tuples_representation) | |
**Attributes:**
| Name | Type | Description |
| ------------ | ------------------------- | ----------------------------------------------------------------------------------------------- |
| `terms` | `CArray[SparsePauliTerm]` | The list of chosen sparse Pauli terms, corresponds to a product of them. (See: SparsePauliTerm) |
| `num_qubits` | `CInt` | The number of qubits in the Hamiltonian. |
### get\_tuples\_representation
get\_tuples\_representation(
self: ,
reverse\_order: bool
) -> list\[tuple\[str, int | float | complex]]
**Parameters:**
| Name | Type | Description | Default |
| ------------------------------ | ------ | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `reverse_order` | `bool` | | *required* |
| options: | | | |
| show\_source: false | | | |
| show\_if\_no\_docstring: false | | | |
options:
show\_source: false
show\_if\_no\_docstring: false
Members:
| Name | Description |
| --------------- | ------------------------------------------------------------- |
| `SparsePauliOp` | Represents a collection of sparse Pauli operators. |
| `Pauli` | Enumeration for the Pauli matrices used in quantum computing. |
## SparsePauliOp
Represents a collection of sparse Pauli operators.
**Methods:**
| Name | Description |
| --------------------------------------------------------- | ----------- |
| [get\_tuples\_representation](#get_tuples_representation) | |
**Attributes:**
| Name | Type | Description |
| ------------ | ------------------------- | ----------------------------------------------------------------------------------------------- |
| `terms` | `CArray[SparsePauliTerm]` | The list of chosen sparse Pauli terms, corresponds to a product of them. (See: SparsePauliTerm) |
| `num_qubits` | `CInt` | The number of qubits in the Hamiltonian. |
### get\_tuples\_representation
get\_tuples\_representation(
self: ,
reverse\_order: bool
) -> list\[tuple\[str, int | float | complex]]
**Parameters:**
| Name | Type | Description | Default |
| --------------- | ------ | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `reverse_order` | `bool` | | *required* |
## Pauli
Enumeration for the Pauli matrices used in quantum computing.
Represents the four Pauli matrices used in quantum mechanics: Identity (I), X, Y, and Z operators.
The Pauli matrices are defined as:
$$
I = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix}
$$
$$
X = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}
$$
$$
Y = \begin{pmatrix} 0 & -i \\ i & 0 \end{pmatrix}
$$
$$
Z = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix}
$$
**Attributes:**
| Name | Type | Description |
| ------------------------------ | ----- | -------------------------------- |
| `I` | `'0'` | |
| `X` | `'1'` | |
| `Y` | `'2'` | |
| `Z` | `'3'` | |
| `I` | `int` | The identity operator (value 0). |
| `X` | `int` | The Pauli-X operator (value 1). |
| `Y` | `int` | The Pauli-Y operator (value 2). |
| `Z` | `int` | The Pauli-Z operator (value 3). |
| options: | | |
| show\_source: false | | |
| show\_if\_no\_docstring: false | | |
# Allocation
Source: https://docs.classiq.io/sdk-reference/qmod/functions/core_library/allocation
Functions:
| Name | Description |
| ---------------------------- | ------------------------------ |
| `free` | \[Qmod core-library function]. |
| `prepare_state` | \[Qmod core-library function]. |
| `prepare_amplitudes` | \[Qmod core-library function]. |
| `inplace_prepare_state` | \[Qmod core-library function]. |
| `inplace_prepare_amplitudes` | \[Qmod core-library function]. |
| `assign_phase_table` | \[Qmod core-library function]. |
### free
free(
in\_: Input\[QArray\[QBit]]
) -> None
\[Qmod core-library function]
Releases the qubits allocated to a quantum variable, allowing them to be reused.
**Parameters:**
| Name | Type | Description | Default |
| ----- | --------------------- | -------------------------------------------------------------------- | ---------- |
| `in_` | `Input[QArray[QBit]]` | The quantum variable that will be freed. Must be initialized before. | *required* |
### prepare\_state
prepare\_state(
probabilities: CArray\[CReal],
bound: CReal,
out: Output\[QArray\[QBit, Literal\['log(probabilities.len, 2)']]]
) -> None
\[Qmod core-library function]
Initializes a quantum variable in a state corresponding to a given probability distribution:
$$
\left|\text{out}\right\rangle = \sum_{i=0}^{\text{len(probabilities)}-1} \sqrt{\text{probabilities}[i]} \left|i\right\rangle
$$
with $i = 0, 1, 2, ..., \text\{len(amplitudes)\}-1$ corresponding to computational basis states.
**Parameters:**
| Name | Type | Description | Default |
| --------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `probabilities` | `CArray[CReal]` | The probability distribution to initialize the quantum variable. Must be a valid probability distribution, i.e., a list of non-negative real numbers that sum to 1. Must have a valid length (a power of 2). | *required* |
| `bound` | `CReal` | An error bound, expressed as the $L^\{2\}$ norm between the expected and actual distributions. A larger bound can reduce the circuit size at the expense of accuracy. Must be a positive real number. | *required* |
| `out` | `Output[QArray[QBit, Literal['log(probabilities.len, 2)']]]` | The quantum variable that will receive the initialized state. Must be uninitialized. | *required* |
### prepare\_amplitudes
prepare\_amplitudes(
amplitudes: CArray\[CReal],
bound: CReal,
out: Output\[QArray\[QBit, Literal\['log(amplitudes.len, 2)']]]
) -> None
\[Qmod core-library function]
Initializes a quantum variable in a state corresponding to the given amplitudes:
$$
\left|\text{out}\right\rangle = \sum_{i=0}^{\text{len(amplitudes)}-1} \text{amplitudes}[i] \left|i\right\rangle
$$
with $i = 0, 1, 2, ..., \text\{len(amplitudes)\}-1$ corresponding to computational basis states.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `amplitudes` | `CArray[CReal]` | The amplitudes to initialize the quantum variable. Must be a valid real quantum state vector, i.e., the sum of squares should be 1. Must have a valid length (a power of 2). | *required* |
| `bound` | `CReal` | An error bound, expressed as the $L^\{2\}$ norm between the expected and actual distributions. A larger bound can reduce the circuit size at the expense of accuracy. Must be a positive real number. | *required* |
| `out` | `Output[QArray[QBit, Literal['log(amplitudes.len, 2)']]]` | The quantum variable that will receive the initialized state. Must be uninitialized. | *required* |
### inplace\_prepare\_state
inplace\_prepare\_state(
probabilities: CArray\[CReal],
bound: CReal,
target: QArray\[QBit, Literal\['log(probabilities.len, 2)']]
) -> None
\[Qmod core-library function]
Transforms a given quantum variable in the state `|0>` to the state per the specified probability distribution
(similar to `prepare_state` but preformed on an initialized variable).
**Parameters:**
| Name | Type | Description | Default |
| --------------- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `probabilities` | `CArray[CReal]` | The probability distribution corresponding to the quantum variable state. Must be a valid probability distribution, i.e., a list of non-negative real numbers that sum to 1. Must have a valid length (a power of 2). | *required* |
| `bound` | `CReal` | An error bound, expressed as the $L^\{2\}$ norm between the expected and actual distributions. A larger bound can reduce the circuit size at the expense of accuracy. Must be a positive real number. | *required* |
| `target` | `QArray[QBit, Literal['log(probabilities.len, 2)']]` | The quantum variable to act upon. | *required* |
### inplace\_prepare\_amplitudes
inplace\_prepare\_amplitudes(
amplitudes: CArray\[CReal],
bound: CReal,
target: QArray\[QBit, Literal\['log(amplitudes.len, 2)']]
) -> None
\[Qmod core-library function]
Transforms a given quantum variable in the state `|0>` to the state per the specified amplitudes
(similar to `prepare_amplitudes` but preformed on an initialized variable).
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `amplitudes` | `CArray[CReal]` | The amplitudes to initialize the quantum variable. Must be a valid real quantum state vector, i.e., the sum of squares should be 1. Must have a valid length (a power of 2). | *required* |
| `bound` | `CReal` | An error bound, expressed as the $L^\{2\}$ norm between the expected and actual distributions. A larger bound can reduce the circuit size at the expense of accuracy. Must be a positive real number. | *required* |
| `target` | `QArray[QBit, Literal['log(amplitudes.len, 2)']]` | The quantum variable to act upon. | *required* |
### assign\_phase\_table
assign\_phase\_table(
phases: CArray\[CReal],
target: Const\[QArray\[QBit, Literal\['log(phases.len, 2)']]]
) -> None
\[Qmod core-library function]
Transforms a given quantum variable in the state `|n>` to $e^\{i phases[n]\}$ `|n>` for all n, where `|n>` are the computational basis states.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `phases` | `CArray[CReal]` | The phases to rotate the quantum variable. Must be a real vector. Must have a valid length (2 to the power of the number of qubits in the target variable). | *required* |
| `target` | `Const[QArray[QBit, Literal['log(phases.len, 2)']]]` | The quantum variable to act upon. | *required* |
# Arithmetic
Source: https://docs.classiq.io/sdk-reference/qmod/functions/core_library/arithmetic
Functions:
| Name | Description |
| ----------------------------- | ------------------------------ |
| `unitary` | \[Qmod core-library function]. |
| `multiply` | \[Qmod core-library function]. |
| `multiply_constant` | \[Qmod core-library function]. |
| `canonical_add` | \[Qmod core-library function]. |
| `canonical_add_constant` | \[Qmod core-library function]. |
| `canonical_multiply` | \[Qmod core-library function]. |
| `canonical_multiply_constant` | \[Qmod core-library function]. |
| `canonical_square` | \[Qmod core-library function]. |
### unitary
unitary(
elements: CArray\[CArray\[CReal]],
target: QArray\[QBit, Literal\['log(elements\[0].len, 2)']]
) -> None
\[Qmod core-library function]
Applies a unitary matrix on a quantum state.
**Parameters:**
| Name | Type | Description | Default |
| ---------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------- | ---------- |
| `elements` | `CArray[CArray[CReal]]` | A 2d array of complex numbers representing the unitary matrix. This matrix must be unitary. | *required* |
| `target` | `QArray[QBit, Literal['log(elements[0].len, 2)']]` | The quantum state to apply the unitary on. Should be of corresponding size. | *required* |
### multiply
multiply(
left: Const\[QNum],
right: Const\[QNum],
result: Output\[QNum]
) -> None
\[Qmod core-library function]
Multiplies two quantum numeric variables:
$$
\left|\text{left}\right\rangle \left|\text{right}\right\rangle
\mapsto
\left|\text{left}\right\rangle \left|\text{right}\right\rangle
\left|\text{left} \cdot \text{right} \right\rangle
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | -------------- | ------------------------------------------------------- | ---------- |
| `left` | `Const[QNum]` | The first argument for the multiplication. | *required* |
| `right` | `Const[QNum]` | The second argument for the multiplication. | *required* |
| `result` | `Output[QNum]` | The quantum variable to hold the multiplication result. | *required* |
### multiply\_constant
multiply\_constant(
left: CReal,
right: Const\[QNum],
result: Output\[QNum]
) -> None
\[Qmod core-library function]
Multiplies a quantum numeric variable with a constant:
$$
\left|\text{right}\right\rangle
\mapsto
\left|\text{right}\right\rangle
\left|\text{left} \cdot \text{right} \right\rangle
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | -------------- | ------------------------------------------------------- | ---------- |
| `left` | `CReal` | The constant argument for the multiplication. | *required* |
| `right` | `Const[QNum]` | The variable argument for the multiplication. | *required* |
| `result` | `Output[QNum]` | The quantum variable to hold the multiplication result. | *required* |
### canonical\_add
canonical\_add(
left: Const\[QArray],
extend\_left: CBool,
right: QArray
) -> None
\[Qmod core-library function]
Adds two quantum variables representing integers (signed or unsigned), storing the
result in the second variable (in-place):
$$
\left|\text{left}\right\rangle \left|\text{right}\right\rangle
\mapsto
\left|\text{left}\right\rangle \left|\left(\text{right} +
\text{left}\right) \bmod 2^{\text{right.size}} \right\rangle
$$
**Parameters:**
| Name | Type | Description | Default |
| ------------- | --------------- | --------------------------------------------------------------- | ---------- |
| `left` | `Const[QArray]` | The out-of-place argument for the addition. | *required* |
| `extend_left` | `CBool` | Whether to sign-extend the left argument. | *required* |
| `right` | `QArray` | The in-place argument for the addition, holds the final result. | *required* |
### canonical\_add\_constant
canonical\_add\_constant(
left: CInt,
right: QArray
) -> None
\[Qmod core-library function]
Adds an integer constant to a quantum variable representing an integer (signed or
unsigned):
$$
\left|\text{right}\right\rangle
\mapsto
\left|\left(\text{right} +
\text{left}\right) \bmod 2^{\text{right.size}} \right\rangle
$$
**Parameters:**
| Name | Type | Description | Default |
| ------- | -------- | -------------------------------------------------------------- | ---------- |
| `left` | `CInt` | The constant argument for the addition. | *required* |
| `right` | `QArray` | The quantum argument for the addition, holds the final result. | *required* |
### canonical\_multiply
canonical\_multiply(
left: Const\[QArray],
extend\_left: CBool,
right: Const\[QArray],
extend\_right: CBool,
result: QArray,
trim\_result\_lsb: CBool
) -> None
\[Qmod core-library function]
Multiplies two quantum variables representing integers (signed or unsigned) into the
result variable which is assumed to start in the $|0\rangle$ state.
If `trim_result_lsb` is `False`, applies the transformation:
$$
\left|\text{left}\right\rangle \left|\text{right}\right\rangle
\left|0\right\rangle \mapsto \left|\text{left}\right\rangle
\left|\text{right}\right\rangle \left|\left( \text{left} \cdot
\text{right} \right) \bmod 2^{\text{result.size}} \right\rangle
$$
If `trim_result_lsb` is `True`, the function avoids computing the result's LSB and
applies the transformation:
$$
\left|\text{left}\right\rangle \left|\text{right}\right\rangle
\left|0\right\rangle \mapsto \left|\text{left}\right\rangle
\left|\text{right}\right\rangle \left|\left( \text{left} \cdot
\text{right} \right) \gg 1 \bmod 2^{\text{result.size}} \right\rangle
$$
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | --------------- | ------------------------------------------------------- | ---------- |
| `left` | `Const[QArray]` | The first argument for the multiplication. | *required* |
| `extend_left` | `CBool` | Whether to sign-extend the left argument. | *required* |
| `right` | `Const[QArray]` | The second argument for the multiplication. | *required* |
| `extend_right` | `CBool` | Whether to sign-extend the right argument. | *required* |
| `result` | `QArray` | The quantum variable to hold the multiplication result. | *required* |
| `trim_result_lsb` | `CBool` | Whether to avoid computing the result's LSB. | *required* |
### canonical\_multiply\_constant
canonical\_multiply\_constant(
left: CInt,
right: Const\[QArray],
extend\_right: CBool,
result: QArray,
trim\_result\_lsb: CBool
) -> None
\[Qmod core-library function]
Multiplies a quantum variable representing an integer (signed or unsigned) with a
constant, into the result variable which is assumed to start in the $|0\rangle$ state.
If `trim_result_lsb` is `False`, applies the transformation:
$$
\left|\text{right}\right\rangle \left|0\right\rangle \mapsto
\left|\text{right}\right\rangle \left|\left( \text{left} \cdot
\text{right} \right) \bmod 2^{\text{result.size}} \right\rangle
$$
If `trim_result_lsb` is `True`, the function avoids computing the result's LSB and
applies the transformation:
$$
\left|\text{right}\right\rangle \left|0\right\rangle \mapsto
\left|\text{right}\right\rangle \left|\left( \text{left} \cdot
\text{right} \right) \gg 1 \bmod 2^{\text{result.size}} \right\rangle
$$
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | --------------- | ------------------------------------------------------- | ---------- |
| `left` | `CInt` | The constant argument for the multiplication. | *required* |
| `right` | `Const[QArray]` | The variable argument for the multiplication. | *required* |
| `extend_right` | `CBool` | Whether to sign-extend the right argument. | *required* |
| `result` | `QArray` | The quantum variable to hold the multiplication result. | *required* |
| `trim_result_lsb` | `CBool` | Whether to avoid computing the result's LSB. | *required* |
### canonical\_square
canonical\_square(
arg: Const\[QArray],
extend\_arg: CBool,
result: QArray,
trim\_result\_lsb: CBool
) -> None
\[Qmod core-library function]
Squares a quantum variable representing an integer (signed or unsigned), into
the result variable which is assumed to start in the $|0\rangle$ state.
If `trim_result_lsb` is `False`, applies the transformation:
$$
\left|\text{arg}\right\rangle \left|0\right\rangle \mapsto
\left|\text{arg}\right\rangle \left|\left( \text{arg}^{2}\right)
\bmod 2^{\text{result.size}} \right\rangle
$$
If `trim_result_lsb` is `True`, the function avoids computing the result's LSB and
applies the transformation:
$$
\left|\text{arg}\right\rangle \left|0\right\rangle \mapsto
\left|\text{arg}\right\rangle \left|\left( \text{arg}^{2} \right)
\gg 1 \bmod 2^{\text{result.size}} \right\rangle
$$
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | --------------- | ------------------------------------------------ | ---------- |
| `arg` | `Const[QArray]` | The argument to square. | *required* |
| `extend_arg` | `CBool` | Whether to sign-extend the argument. | *required* |
| `result` | `QArray` | The quantum variable to hold the squared result. | *required* |
| `trim_result_lsb` | `CBool` | Whether to avoid computing the result's LSB. | *required* |
# Exponentiation
Source: https://docs.classiq.io/sdk-reference/qmod/functions/core_library/exponentiation
Functions:
| Name | Description |
| --------------------------- | ------------------------------ |
| `single_pauli_exponent` | \[Qmod core-library function]. |
| `commuting_paulis_exponent` | \[Qmod core-library function]. |
| `suzuki_trotter` | \[Qmod core-library function]. |
| `multi_suzuki_trotter` | \[Qmod core-library function]. |
| `sequential_suzuki_trotter` | \[Qmod core-library function]. |
| `qdrift` | \[Qmod core-library function]. |
| `exponentiate` | \[Qmod core-library function]. |
### single\_pauli\_exponent
single\_pauli\_exponent(
pauli\_string: CArray\[Pauli],
coefficient: CReal,
qbv: QArray\[QBit, Literal\['pauli\_string.len']]
) -> None
\[Qmod core-library function]
Exponentiates the specified single Pauli operator multiplied by some coefficient.
**Parameters:**
| Name | Type | Description | Default |
| -------------- | ------------------------------------------- | -------------------------------------------------- | ---------- |
| `pauli_string` | `CArray[Pauli]` | The Pauli operator to be exponentiated. | *required* |
| `coefficient` | `CReal` | A coefficient multiplying the Pauli operator. | *required* |
| `qbv` | `QArray[QBit, Literal['pauli_string.len']]` | The target quantum variable of the exponentiation. | *required* |
### commuting\_paulis\_exponent
commuting\_paulis\_exponent(
pauli\_operator: CArray\[PauliTerm],
evolution\_coefficient: CReal,
qbv: QArray\[QBit, Literal\['pauli\_operator\[0].pauli.len']]
) -> None
\[Qmod core-library function]
Exponentiates the specified commutative Pauli operator.
As all the Pauli operator's terms commute, the exponential of the whole operator
is exactly the product of exponentials of each term.
Calling this funciton with a non-commutative Pauli operator will issue an error.
**Parameters:**
| Name | Type | Description | Default |
| ----------------------- | ------------------------------------------------------ | -------------------------------------------------------------- | ---------- |
| `pauli_operator` | `CArray[PauliTerm]` | The Pauli operator to be exponentiated. | *required* |
| `evolution_coefficient` | `CReal` | A global evolution coefficient multiplying the Pauli operator. | *required* |
| `qbv` | `QArray[QBit, Literal['pauli_operator[0].pauli.len']]` | The target quantum variable of the exponentiation. | *required* |
### suzuki\_trotter
suzuki\_trotter(
pauli\_operator: SparsePauliOp,
evolution\_coefficient: CReal,
order: CInt,
repetitions: CInt,
qbv: QArray\[QBit]
) -> None
\[Qmod core-library function]
Applies the Suzuki-Trotter decomposition to a Pauli operator.
The Suzuki-Trotter decomposition is a method for approximating the exponential of a sum of operators by a product of exponentials of each operator.
The Suzuki-Trotter decomposition of a given order nullifies the error of the Taylor series expansion of the product of exponentials up to that order.
The error of a Suzuki-Trotter decomposition decreases as the order and number of repetitions increase.
**Parameters:**
| Name | Type | Description | Default |
| ----------------------- | --------------- | -------------------------------------------------------------- | ---------- |
| `pauli_operator` | `SparsePauliOp` | The Pauli operator to be exponentiated. | *required* |
| `evolution_coefficient` | `CReal` | A global evolution coefficient multiplying the Pauli operator. | *required* |
| `order` | `CInt` | The order of the Suzuki-Trotter decomposition. | *required* |
| `repetitions` | `CInt` | The number of repetitions of the Suzuki-Trotter decomposition. | *required* |
| `qbv` | `QArray[QBit]` | The target quantum variable of the exponentiation. | *required* |
### multi\_suzuki\_trotter
multi\_suzuki\_trotter(
hamiltonians: CArray\[SparsePauliOp],
evolution\_coefficients: CArray\[CReal, Literal\['hamiltonians.len']],
order: CInt,
repetitions: CInt,
qbv: QArray
) -> None
\[Qmod core-library function]
Applies the Suzuki-Trotter decomposition jointly to a sum of Hamiltonians
(represented as Pauli operators), each with its separate evolution coefficient,
approximating $\exp\{-i(H_1t_1+H_2t_2+\dots)\}$ with a specified order and number of
repetitions.
The Suzuki-Trotter decomposition is a method for approximating the exponential of a sum of operators by a product of exponentials of each operator.
The Suzuki-Trotter decomposition of a given order nullifies the error of the Taylor series expansion of the product of exponentials up to that order.
The error of a Suzuki-Trotter decomposition decreases as the order and number of repetitions increase.
**Parameters:**
| Name | Type | Description | Default |
| ------------------------ | -------------------------------------------- | --------------------------------------------------------------- | ---------- |
| `hamiltonians` | `CArray[SparsePauliOp]` | The hamiltonians to be exponentiated, in sparse representation. | *required* |
| `evolution_coefficients` | `CArray[CReal, Literal['hamiltonians.len']]` | The hamiltonian coefficients (can be link-time). | *required* |
| `order` | `CInt` | The order of the Suzuki-Trotter decomposition. | *required* |
| `repetitions` | `CInt` | The number of repetitions of the Suzuki-Trotter decomposition. | *required* |
| `qbv` | `QArray` | The target quantum variable of the exponentiation. | *required* |
### sequential\_suzuki\_trotter
sequential\_suzuki\_trotter(
hamiltonians: CArray\[SparsePauliOp],
evolution\_coefficients: CArray\[CReal, Literal\['hamiltonians.len']],
order: CInt,
repetitions: CInt,
qbv: QArray
) -> None
\[Qmod core-library function]
Applies the Suzuki-Trotter decomposition jointly to a sum of Hamiltonians
(represented as Pauli operators), each with its separate evolution coefficient,
approximating $\exp\{-i(H_1t_1+H_2t_2+\dots)\}$ with a specified order and number of
repetitions. Does not reorder the Pauli terms.
The Suzuki-Trotter decomposition is a method for approximating the exponential of a sum of operators by a product of exponentials of each operator.
The Suzuki-Trotter decomposition of a given order nullifies the error of the Taylor series expansion of the product of exponentials up to that order.
The error of a Suzuki-Trotter decomposition decreases as the order and number of repetitions increase.
**Parameters:**
| Name | Type | Description | Default |
| ------------------------ | -------------------------------------------- | --------------------------------------------------------------- | ---------- |
| `hamiltonians` | `CArray[SparsePauliOp]` | The hamiltonians to be exponentiated, in sparse representation. | *required* |
| `evolution_coefficients` | `CArray[CReal, Literal['hamiltonians.len']]` | The hamiltonian coefficients (can be link-time). | *required* |
| `order` | `CInt` | The order of the Suzuki-Trotter decomposition. | *required* |
| `repetitions` | `CInt` | The number of repetitions of the Suzuki-Trotter decomposition. | *required* |
| `qbv` | `QArray` | The target quantum variable of the exponentiation. | *required* |
### qdrift
qdrift(
pauli\_operator: SparsePauliOp,
evolution\_coefficient: CReal,
num\_qdrift: CInt,
qbv: QArray\[QBit, Literal\['pauli\_operator.num\_qubits']]
) -> None
\[Qmod core-library function]
Exponentiates a Pauli operator using the QDrift method. The QDrift method is a stochastic method based on the Trotter decomposition for approximating the exponential of a sum of operators by a product of exponentials of each operator.
The QDrift method randomizes the order of the operators in the product of exponentials to stochastically reduce the error of the approximation.
The error of the QDrift method decreases as the number of QDrift steps increases.
**Parameters:**
| Name | Type | Description | Default |
| ----------------------- | ---------------------------------------------------- | -------------------------------------------------------------- | ---------- |
| `pauli_operator` | `SparsePauliOp` | The Pauli operator to be exponentiated. | *required* |
| `evolution_coefficient` | `CReal` | A global evolution coefficient multiplying the Pauli operator. | *required* |
| `num_qdrift` | `CInt` | | *required* |
| `qbv` | `QArray[QBit, Literal['pauli_operator.num_qubits']]` | The target quantum variable of the exponentiation. | *required* |
### exponentiate
exponentiate(
hamiltonian: SparsePauliOp,
evolution\_coefficient: CReal,
qbv: QArray\[QBit]
) -> None
\[Qmod core-library function]
Exponentiates a Pauli operator.
**Parameters:**
| Name | Type | Description | Default |
| ----------------------- | --------------- | ---------------------------------------------------- | ---------- |
| `hamiltonian` | `SparsePauliOp` | The Pauli operator to be exponentiated. | *required* |
| `evolution_coefficient` | `CReal` | A global coefficient multiplying the Pauli operator. | *required* |
| `qbv` | `QArray[QBit]` | The target quantum variable of the exponentiation. | *required* |
# Gray Code
Source: https://docs.classiq.io/sdk-reference/qmod/functions/core_library/gray_code
Functions:
| Name | Description |
| ------------------- | ------------------------------ |
| `select_rotation` | \[Qmod core-library function]. |
| `select_z_rotation` | \[Qmod core-library function]. |
### select\_rotation
select\_rotation(
basis: Pauli,
angles: CArray\[CReal],
selector: Const\[QNum],
target: QBit
) -> None
\[Qmod core-library function]
Applies a set of controlled single-qubit rotations to a target qubit, using
a specified rotation axis and a list of rotation angles.
**Parameters:**
| Name | Type | Description | Default |
| ---------- | --------------- | ------------------------------------------------------------------------------------- | ---------- |
| `basis` | `Pauli` | The Pauli operator defining the rotation axis. | *required* |
| `angles` | `CArray[CReal]` | The list of rotation angles in radians. The list must have length 2\*\*selector.size. | *required* |
| `selector` | `Const[QNum]` | The qubits that act as the selection register. | *required* |
| `target` | `QBit` | The qubit on which the selected rotation is applied. | *required* |
### select\_z\_rotation
select\_z\_rotation(
angles: CArray\[CReal],
selector: Const\[QNum],
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Applies a set of controlled single-qubit Z rotations to a target qubit, using
a list of rotation angles.
**Parameters:**
| Name | Type | Description | Default |
| ---------- | --------------- | ------------------------------------------------------------------------------------- | ---------- |
| `angles` | `CArray[CReal]` | The list of rotation angles in radians. The list must have length 2\*\*selector.size. | *required* |
| `selector` | `Const[QNum]` | The qubits that act as the selection register. | *required* |
| `target` | `Const[QBit]` | The qubit on which the selected rotation is applied. | *required* |
# Mid Circuit Measurement
Source: https://docs.classiq.io/sdk-reference/qmod/functions/core_library/mid_circuit_measurement
Functions:
| Name | Description |
| ------- | -------------------------------------------- |
| `RESET` | Resets the target qubit to the `\|0>` state. |
### RESET
RESET(
target: QBit
) -> None
Resets the target qubit to the `|0>` state.
Performed by measuring the qubit and applying an X gate if necessary.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------ | ------------------ | ---------- |
| `target` | `QBit` | the qubit to reset | *required* |
# Standard Gates
Source: https://docs.classiq.io/sdk-reference/qmod/functions/core_library/standard_gates
Functions:
| Name | Description |
| ---------- | ------------------------------ |
| `H` | \[Qmod core-library function]. |
| `X` | \[Qmod core-library function]. |
| `Y` | \[Qmod core-library function]. |
| `Z` | \[Qmod core-library function]. |
| `I` | \[Qmod core-library function]. |
| `S` | \[Qmod core-library function]. |
| `T` | \[Qmod core-library function]. |
| `SDG` | \[Qmod core-library function]. |
| `TDG` | \[Qmod core-library function]. |
| `PHASE` | \[Qmod core-library function]. |
| `RX` | \[Qmod core-library function]. |
| `RY` | \[Qmod core-library function]. |
| `RZ` | \[Qmod core-library function]. |
| `R` | \[Qmod core-library function]. |
| `RXX` | \[Qmod core-library function]. |
| `RYY` | \[Qmod core-library function]. |
| `RZZ` | \[Qmod core-library function]. |
| `CH` | \[Qmod core-library function]. |
| `CX` | \[Qmod core-library function]. |
| `CY` | \[Qmod core-library function]. |
| `CZ` | \[Qmod core-library function]. |
| `CRX` | \[Qmod core-library function]. |
| `CRY` | \[Qmod core-library function]. |
| `CRZ` | \[Qmod core-library function]. |
| `CPHASE` | \[Qmod core-library function]. |
| `SWAP` | \[Qmod core-library function]. |
| `IDENTITY` | \[Qmod core-library function]. |
| `U` | \[Qmod core-library function]. |
| `CCX` | \[Qmod core-library function]. |
### H
H(
target: QBit
) -> None
\[Qmod core-library function]
Performs the Hadamard gate on a qubit.
This operation is represented by the following matrix:
$$
H = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------ | ---------------------------------------- | ---------- |
| `target` | `QBit` | The qubit to apply the Hadamard gate to. | *required* |
### X
X(
target: QBit
) -> None
\[Qmod core-library function]
Performs the Pauli-X gate on a qubit.
This operation is represented by the following matrix:
$$
X = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------ | --------------------------------------- | ---------- |
| `target` | `QBit` | The qubit to apply the Pauli-X gate to. | *required* |
### Y
Y(
target: QBit
) -> None
\[Qmod core-library function]
Performs the Pauli-Y gate on a qubit.
This operation is represented by the following matrix:
$$
Y = \begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------ | --------------------------------------- | ---------- |
| `target` | `QBit` | The qubit to apply the Pauli-Y gate to. | *required* |
### Z
Z(
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Performs the Pauli-Z gate on a qubit.
This operation is represented by the following matrix:
$$
Z = \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | --------------------------------------- | ---------- |
| `target` | `Const[QBit]` | The qubit to apply the Pauli-Z gate to. | *required* |
### I
I(
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Performs the identity gate on a qubit.
This operation is represented by the following matrix:
$$
I = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ---------------------------------------- | ---------- |
| `target` | `Const[QBit]` | The qubit to apply the identity gate to. | *required* |
### S
S(
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Performs the S gate on a qubit.
This operation is represented by the following matrix:
$$
S = \begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | --------------------------------- | ---------- |
| `target` | `Const[QBit]` | The qubit to apply the S gate to. | *required* |
### T
T(
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Performs the T gate on a qubit.
This operation is represented by the following matrix:
$$
T = \begin{bmatrix} 1 & 0 \\ 0 & e^{i\frac{\pi}{4}} \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | --------------------------------- | ---------- |
| `target` | `Const[QBit]` | The qubit to apply the T gate to. | *required* |
### SDG
SDG(
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Performs the S-dagger gate on a qubit.
This operation is represented by the following matrix:
$$
S^\dagger = \begin{bmatrix} 1 & 0 \\ 0 & -i \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ---------------------------------------- | ---------- |
| `target` | `Const[QBit]` | The qubit to apply the S-dagger gate to. | *required* |
### TDG
TDG(
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Performs the T-dagger gate on a qubit.
This operation is represented by the following matrix:
$$
T^\dagger = \begin{bmatrix} 1 & 0 \\ 0 & e^{-i\frac{\pi}{4}} \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ---------------------------------------- | ---------- |
| `target` | `Const[QBit]` | The qubit to apply the T-dagger gate to. | *required* |
### PHASE
PHASE(
theta: CReal,
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Performs the phase gate on a qubit.
This operation is represented by the following matrix:
$$
PHASE(\theta) = \begin{bmatrix} 1 & 0 \\ 0 & e^{i\theta} \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ------------------------------------- | ---------- |
| `theta` | `CReal` | The phase angle in radians. | *required* |
| `target` | `Const[QBit]` | The qubit to apply the phase gate to. | *required* |
### RX
RX(
theta: CReal,
target: QBit
) -> None
\[Qmod core-library function]
Performs the Pauli-X rotation gate on a qubit.
This operation is represented by the following matrix:
$$
R_X(\theta) = e^{-i\frac{\theta}{2}X}
= \begin{bmatrix} cos(\frac{\theta}{2}) & -i sin(\frac{\theta}{2}) \\ -i sin(\frac{\theta}{2}) & cos(\frac{\theta}{2}) \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------- | ------------------------------------------------ | ---------- |
| `theta` | `CReal` | The rotation angle in radians. | *required* |
| `target` | `QBit` | The qubit to apply the Pauli-X rotation gate to. | *required* |
### RY
RY(
theta: CReal,
target: QBit
) -> None
\[Qmod core-library function]
Performs the Pauli-Y rotation gate on a qubit.
This operation is represented by the following matrix:
$$
R_Y(\theta) = e^{-i\frac{\theta}{2}Y}
= \begin{bmatrix} cos(\frac{\theta}{2}) & -sin(\frac{\theta}{2}) \\ sin(\frac{\theta}{2}) & cos(\frac{\theta}{2}) \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------- | ------------------------------------------------ | ---------- |
| `theta` | `CReal` | The rotation angle in radians. | *required* |
| `target` | `QBit` | The qubit to apply the Pauli-Y rotation gate to. | *required* |
### RZ
RZ(
theta: CReal,
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Performs the Pauli-Z rotation gate on a qubit.
This operation is represented by the following matrix:
$$
R_Z(\theta) = e^{-i\frac{\theta}{2}Z}
= \begin{bmatrix} e^{-i\frac{\theta}{2}} & 0 \\ 0 & e^{i\frac{\theta}{2}} \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ------------------------------------------------ | ---------- |
| `theta` | `CReal` | The rotation angle in radians. | *required* |
| `target` | `Const[QBit]` | The qubit to apply the Pauli-Z rotation gate to. | *required* |
### R
R(
theta: CReal,
phi: CReal,
target: QBit
) -> None
\[Qmod core-library function]
Performs a rotation of $\theta$ around the $cos(\phi)\hat\{x\} + sin(\phi)\hat\{y\}$ axis on a qubit.
This operation is represented by the following matrix:
$$
R(\theta, \phi) = e^{-i \frac{\theta}{2} (cos(\phi)X + sin(\phi)Y)}
= \begin{bmatrix} cos(\frac{\theta}{2}) & -i e^{-i\phi} sin(\frac{\theta}{2}) \\ -i e^{i\phi} sin(\frac{\theta}{2}) & cos(\frac{\theta}{2}) \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------- | ------------------------------------------------------------- | ---------- |
| `theta` | `CReal` | The rotation angle in radians. | *required* |
| `phi` | `CReal` | The phase angle in radians. | *required* |
| `target` | `QBit` | The qubit to apply the general single-qubit rotation gate to. | *required* |
### RXX
RXX(
theta: CReal,
target: QArray\[QBit, Literal\[2]]
) -> None
\[Qmod core-library function]
Performs the XX rotation gate on a pair of qubits.
This operation is represented by the following matrix:
$$
R_{XX}(\theta) = e^{-i\frac{\theta}{2}X \otimes X}
= \begin{bmatrix} cos(\frac{\theta}{2}) & 0 & 0 & -i sin(\frac{\theta}{2}) \\ 0 & cos(\frac{\theta}{2}) & -i sin(\frac{\theta}{2}) & 0 \\ 0 & -i sin(\frac{\theta}{2}) & cos(\frac{\theta}{2}) & 0 \\ -i sin(\frac{\theta}{2}) & 0 & 0 & cos(\frac{\theta}{2}) \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | -------------------------- | ---------------------------------------------------- | ---------- |
| `theta` | `CReal` | The rotation angle in radians. | *required* |
| `target` | `QArray[QBit, Literal[2]]` | The pair of qubits to apply the XX rotation gate to. | *required* |
### RYY
RYY(
theta: CReal,
target: QArray\[QBit, Literal\[2]]
) -> None
\[Qmod core-library function]
Performs the YY rotation gate on a pair of qubits.
This operation is represented by the following matrix:
$$
R_{YY}(\theta) = e^{-i\frac{\theta}{2}Y \otimes Y}
= \begin{bmatrix} cos(\frac{\theta}{2}) & 0 & 0 & -sin(\frac{\theta}{2}) \\ 0 & cos(\frac{\theta}{2}) & sin(\frac{\theta}{2}) & 0 \\ 0 & sin(\frac{\theta}{2}) & cos(\frac{\theta}{2}) & 0 \\ -sin(\frac{\theta}{2}) & 0 & 0 & cos(\frac{\theta}{2}) \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | -------------------------- | ---------------------------------------------------- | ---------- |
| `theta` | `CReal` | The rotation angle in radians. | *required* |
| `target` | `QArray[QBit, Literal[2]]` | The pair of qubits to apply the YY rotation gate to. | *required* |
### RZZ
RZZ(
theta: CReal,
target: Const\[QArray\[QBit, Literal\[2]]]
) -> None
\[Qmod core-library function]
Performs the ZZ rotation gate on a pair of qubits.
This operation is represented by the following matrix:
$$
R_{ZZ}(\theta) = e^{-i\frac{\theta}{2}Z \otimes Z}
= \begin{bmatrix} e^{-i\frac{\theta}{2}} & 0 & 0 & 0 \\ 0 & e^{i\frac{\theta}{2}} & 0 & 0 \\ 0 & 0 & e^{i\frac{\theta}{2}} & 0 \\ 0 & 0 & 0 & e^{-i\frac{\theta}{2}} \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | --------------------------------- | ---------------------------------------------------- | ---------- |
| `theta` | `CReal` | The rotation angle in radians. | *required* |
| `target` | `Const[QArray[QBit, Literal[2]]]` | The pair of qubits to apply the ZZ rotation gate to. | *required* |
### CH
CH(
ctrl: Const\[QBit],
target: QBit
) -> None
\[Qmod core-library function]
Applies the Hadamard gate to the target qubit, conditioned on the control qubit.
This operation is represented by the following matrix:
$$
CH = \frac{1}{\sqrt{2}} \begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 1 \\
0 & 0 & 1 & -1
\end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ---------------------------------------- | ---------- |
| `ctrl` | `Const[QBit]` | The control qubit. | *required* |
| `target` | `QBit` | The qubit to apply the Hadamard gate on. | *required* |
### CX
CX(
ctrl: Const\[QBit],
target: QBit
) -> None
\[Qmod core-library function]
Applies the Pauli-X gate to the target qubit, conditioned on the control qubit.
This operation is represented by the following matrix:
$$
CX = \begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1 \\
0 & 0 & 1 & 0
\end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | --------------------------------------- | ---------- |
| `ctrl` | `Const[QBit]` | The control qubit. | *required* |
| `target` | `QBit` | The qubit to apply the Pauli-X gate on. | *required* |
### CY
CY(
ctrl: Const\[QBit],
target: QBit
) -> None
\[Qmod core-library function]
Applies the Pauli-Y gate to the target qubit, conditioned on the control qubit.
This operation is represented by the following matrix:
$$
CY = \begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & -i \\
0 & 0 & i & 0
\end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | --------------------------------------- | ---------- |
| `ctrl` | `Const[QBit]` | The control qubit. | *required* |
| `target` | `QBit` | The qubit to apply the Pauli-Y gate on. | *required* |
### CZ
CZ(
ctrl: Const\[QBit],
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Applies the Pauli-Z gate to the target qubit, conditioned on the control qubit.
This operation is represented by the following matrix:
$$
CZ = \begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & -1
\end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | --------------------------------------- | ---------- |
| `ctrl` | `Const[QBit]` | The control qubit. | *required* |
| `target` | `Const[QBit]` | The qubit to apply the Pauli-Z gate on. | *required* |
### CRX
CRX(
theta: CReal,
ctrl: Const\[QBit],
target: QBit
) -> None
\[Qmod core-library function]
Applies the RX gate to the target qubit, conditioned on the control qubit.
This operation is represented by the following matrix:
$$
CRX = \begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & cos(\frac{\theta}{2}) & -i*sin(\frac{\theta}{2}) \\
0 & 0 & -i*sin(\frac{\theta}{2}) & cos(\frac{\theta}{2})
\end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ---------------------------------- | ---------- |
| `theta` | `CReal` | The rotation angle in radians. | *required* |
| `ctrl` | `Const[QBit]` | The control qubit. | *required* |
| `target` | `QBit` | The qubit to apply the RX gate on. | *required* |
### CRY
CRY(
theta: CReal,
ctrl: Const\[QBit],
target: QBit
) -> None
\[Qmod core-library function]
Applies the RY gate to the target qubit, conditioned on the control qubit.
This operation is represented by the following matrix:
$$
CRY = \begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & cos(\frac{\theta}{2}) & -sin(\frac{\theta}{2}) \\
0 & 0 & sin(\frac{\theta}{2}) & cos(\frac{\theta}{2})
\end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ---------------------------------- | ---------- |
| `theta` | `CReal` | The rotation angle in radians. | *required* |
| `ctrl` | `Const[QBit]` | The control qubit. | *required* |
| `target` | `QBit` | The qubit to apply the RY gate on. | *required* |
### CRZ
CRZ(
theta: CReal,
ctrl: Const\[QBit],
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Applies the RZ gate to the target qubit, conditioned on the control qubit.
This operation is represented by the following matrix:
$$
CRZ = \begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & e^{-i\frac{\theta}{2}} & 0 \\
0 & 0 & 0 & e^{i\frac{\theta}{2}}
\end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ---------------------------------- | ---------- |
| `theta` | `CReal` | The rotation angle in radians. | *required* |
| `ctrl` | `Const[QBit]` | The control qubit. | *required* |
| `target` | `Const[QBit]` | The qubit to apply the RZ gate on. | *required* |
### CPHASE
CPHASE(
theta: CReal,
ctrl: Const\[QBit],
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Applies the PHASE gate to the target qubit, conditioned on the control qubit.
This operation is represented by the following matrix:
$$
CPHASE = \begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & e^{i\theta}
\end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | ------------------------------------- | ---------- |
| `theta` | `CReal` | The rotation angle in radians. | *required* |
| `ctrl` | `Const[QBit]` | The control qubit. | *required* |
| `target` | `Const[QBit]` | The qubit to apply the PHASE gate on. | *required* |
### SWAP
SWAP(
qbit0: QBit,
qbit1: QBit
) -> None
\[Qmod core-library function]
Swaps the states of two qubits.
This operation is represented by the following matrix:
$$
SWAP = \begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1
\end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| ------- | ------ | ----------------- | ---------- |
| `qbit0` | `QBit` | The first qubit. | *required* |
| `qbit1` | `QBit` | The second qubit. | *required* |
### IDENTITY
IDENTITY(
target: Const\[QArray\[QBit]]
) -> None
\[Qmod core-library function]
Does nothing.
This operation is represented by the following matrix:
$$
IDENTITY = {\begin{bmatrix}
1 & 0 \\
0 & 1
\end{bmatrix}} ^{\otimes n}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | --------------------- | ----------------------------------------- | ---------- |
| `target` | `Const[QArray[QBit]]` | The qubits to apply the IDENTITY gate on. | *required* |
### U
U(
theta: CReal,
phi: CReal,
lam: CReal,
gam: CReal,
target: QBit
) -> None
\[Qmod core-library function]
Performs a general single-qubit unitary gate that applies phase and rotation with three Euler angles on a qubit.
This operation is represented by the following matrix:
$$
U(\theta, \phi, \lambda, \gamma) = e^{i \gamma}
\begin{bmatrix}
cos(\theta/2) & -e^{i(\lambda)} sin(\theta/2) \\
e^{i\phi} sin(\theta/2) & e^{i(\phi + \lambda)} cos(\theta/2)
\end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------- | ------------------------------------------------------------ | ---------- |
| `theta` | `CReal` | The first Euler angle in radians. | *required* |
| `phi` | `CReal` | The second Euler angle in radians. | *required* |
| `lam` | `CReal` | The third Euler angle in radians. | *required* |
| `gam` | `CReal` | The global phase angle in radians. | *required* |
| `target` | `QBit` | The qubit to apply the general single-qubit unitary gate to. | *required* |
### CCX
CCX(
ctrl: Const\[QArray\[QBit, Literal\[2]]],
target: QBit
) -> None
\[Qmod core-library function]
Applies the Pauli-X gate to the target qubit, conditioned on the two control qubits (Toffoli).
This operation is represented by the following matrix:
$$
CCX = \begin{bmatrix}
1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\
0 & 0 & 0 & 0 & 0 & 0 & 1 & 0
\end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | --------------------------------- | --------------------------------------------------- | ---------- |
| `ctrl` | `Const[QArray[QBit, Literal[2]]]` | The control qubits. | *required* |
| `target` | `QBit` | The qubit to apply the conditioned Pauli-X gate on. | *required* |
# Amplitude Amplification
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/amplitude_amplification
Functions:
| Name | Description |
| ------------------------------- | --------------------------------- |
| `amplitude_amplification` | \[Qmod Classiq-library function]. |
| `exact_amplitude_amplification` | \[Qmod Classiq-library function]. |
### amplitude\_amplification
amplitude\_amplification(
reps: CInt,
oracle: QCallable\[QArray\[QBit]],
space\_transform: QCallable\[QArray\[QBit]],
packed\_qvars: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies the Amplitude Amplification algorithm; Prepares a state using the given `space_transform` function, and applies `reps` repetititions
of the grover operator, using the given `oracle` functions which marks the "good" states.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `reps` | `CInt` | Number of repetitions to apply the grover operator on the initial state. Should be determined by the user, according to the calculated amplification. | *required* |
| `oracle` | `QCallable[QArray[QBit]]` | The oracle operator that marks the "good" states. This operator should flip the sign of the amplitude of the "good" state. | *required* |
| `space_transform` | `QCallable[QArray[QBit]]` | The space transform operator (which is known also the state preparation operator). First applied to prepare the state before the amplification, then used inside the Grover operator. | *required* |
| `packed_qvars` | `QArray[QBit]` | | *required* |
### exact\_amplitude\_amplification
exact\_amplitude\_amplification(
amplitude: CReal,
oracle: QCallable\[QArray\[QBit]],
space\_transform: QCallable\[QArray\[QBit]],
packed\_qvars: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies an exact version of the Amplitude Amplification algorithm, assuming knowledge of the amplitude of the marked state.
The function should be applied on the zero state, and it takes care for preparing the initial state before amplification using the `space_transform`.
Based on the algorithm in [Quantum state preparation without coherent arithmetic](https://arxiv.org/abs/2210.14892).
Assuming the `space_transform` creates a state $|\psi\rangle = a|\psi_\{good\}\rangle + \sqrt\{1-a\}|\psi_\{bad\}\rangle$, given `a` as the `amplitude`
argument, the function will load exactly the state $|\psi_\{good\}\rangle$.
Note: if the `amplitude` argument is not exact, the resulting state will not be exactly $|\psi_\{good\}\rangle$, and there will be additional internal auxilliary of the function that is not released correctly.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `amplitude` | `CReal` | The amplitude of the state $\|\psi_\{good\}\rangle$ with regards to the initial state prepared by `space_transform`. | *required* |
| `oracle` | `QCallable[QArray[QBit]]` | The oracle operator that marks the "good" states. This operator should flip the sign of the amplitude of the "good" state. | *required* |
| `space_transform` | `QCallable[QArray[QBit]]` | The space transform operator (which is known also the state preparation operator). First applied to prepare the state before the amplification, then used inside the Grover operator. | *required* |
| `packed_qvars` | `QArray[QBit]` | | *required* |
# Amplitude Estimation
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/amplitude_estimation
Functions:
| Name | Description |
| ---------------------- | --------------------------------- |
| `amplitude_estimation` | \[Qmod Classiq-library function]. |
### amplitude\_estimation
amplitude\_estimation(
oracle: QCallable\[QArray\[QBit]],
space\_transform: QCallable\[QArray\[QBit]],
phase: QNum,
packed\_vars: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Estimate the probability of a state being marked by the operand `oracle` as a "good state."
The algorithm prepares the state in the `packed_vars` register and estimates the probability of this state being marked by the oracle as a "good state."
This is done using the Quantum Phase Estimation (QPE) algorithm, where the unitary for QPE is the Grover operator, which is composed of the `oracle` and `space_transform` operators.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `oracle` | `QCallable[QArray[QBit]]` | The oracle operator that marks the "good" state. This operator should flip the sign of the amplitude of the "good" state. | *required* |
| `space_transform` | `QCallable[QArray[QBit]]` | The space transform operator (which is known also the state preparation operator), which is first applied to prepare the state before the QPE, and then used inside the Grover operator. | *required* |
| `phase` | `QNum` | Assuming this variable starts from the zero state -this variable output holds the $phase=\theta$ result in the \[0,1] domain, which relates to the estimated probability $a$ through $a=\sin^2(\pi \theta)$. | *required* |
| `packed_vars` | `QArray[QBit]` | The variable that holds the state to be estimated. Assumed to be in the zero state at the beginning of the algorithm. | *required* |
# Amplitude Loading
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/amplitude_loading
Functions:
| Name | Description |
| ------------------------ | --------------------------------- |
| `assign_amplitude_table` | \[Qmod Classiq-library function]. |
### assign\_amplitude\_table
assign\_amplitude\_table(
amplitudes: list\[float],
index: Const\[QArray],
indicator: QBit
) -> None
\[Qmod Classiq-library function]
Load a specified list of real amplitudes into a quantum variable using an extra indicator qubit:
( |i\rangle|0\rangle \rightarrow a(i)\ |i\rangle|1\rangle + \sqrt\ |i\rangle|0\rangle ).
Here, (a(i)) is the i-th amplitude, determined by the QNum when the index is in state (i).
A list extracted from a given classical function (f(x)), with indexing according to a given QNum, can be obtained via the utility SDK function `lookup_table`.
This function expects the indicator qubit to be initialized to (|0\rangle).
**Parameters:**
| Name | Type | Description | Default |
| ------------ | --------------- | -------------------------------------------------------- | ---------- |
| `amplitudes` | `list[float]` | Real values for the amplitudes. Must be between -1 and 1 | *required* |
| `index` | `Const[QArray]` | The quantum variable used for amplitude indexing | *required* |
| `indicator` | `QBit` | The quantum indicator qubit | *required* |
# Bit Operations
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/bit_operations
Functions:
| Name | Description |
| -------------------- | -------------------------------------------------------------------------------------------- |
| `cyclic_shift_left` | Performs a left shift on the quantum register array `reg` using SWAP gates. |
| `cyclic_shift_right` | Performs a right shift on the quantum register array `reg` by inverting cyclic\_shift\_left. |
| `bitwise_negate` | Negates each bit of the input x. |
### cyclic\_shift\_left
cyclic\_shift\_left(
reg: QArray\[QBit]
) -> None
Performs a left shift on the quantum register array `reg` using SWAP gates.
**Parameters:**
| Name | Type | Description | Default |
| ----- | -------------- | ----------- | ---------- |
| `reg` | `QArray[QBit]` | | *required* |
### cyclic\_shift\_right
cyclic\_shift\_right(
reg: QArray\[QBit]
) -> None
Performs a right shift on the quantum register array `reg` by inverting cyclic\_shift\_left.
**Parameters:**
| Name | Type | Description | Default |
| ----- | -------------- | ----------- | ---------- |
| `reg` | `QArray[QBit]` | | *required* |
### bitwise\_negate
bitwise\_negate(
x: QArray\[QBit]
) -> None
Negates each bit of the input x.
**Parameters:**
| Name | Type | Description | Default |
| ---- | -------------- | ----------- | ---------- |
| `x` | `QArray[QBit]` | | *required* |
# Discrete Sine Cosine Transform
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/discrete_sine_cosine_transform
Functions:
| Name | Description |
| --------------- | --------------------------------- |
| `qct_qst_type1` | \[Qmod Classiq-library function]. |
| `qct_qst_type2` | \[Qmod Classiq-library function]. |
| `qct_type2` | \[Qmod Classiq-library function]. |
| `qst_type2` | \[Qmod Classiq-library function]. |
### qct\_qst\_type1
qct\_qst\_type1(
x: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies the quantum discrete cosine (DCT) and sine (DST)
transform of type 1 to the qubit array `x`.
Corresponds to the matrix (with $n\equiv$`x.len`):
$$
\left(
egin{array}{ccc|c}
{} &{} &{} \
{}&{
m DCT}^{(1)}(2^{n-1}+1) & {}& 0\
{} &{} &{} \
\hline
{} & 0 & {} & i{
m DST}^{(1)}(2^{n-1}-1)
\end{array}
ight)
$$
**Parameters:**
| Name | Type | Description | Default |
| ---- | -------------- | ------------------------------------------ | ---------- |
| `x` | `QArray[QBit]` | The qubit array to apply the transform to. | *required* |
### qct\_qst\_type2
qct\_qst\_type2(
x: QArray\[QBit],
q: Const\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies the quantum discrete cosine (DCT) and sine (DST)
transform of type 2 to the qubit array `x` concatenated with `q`, with `q` being the MSB.
Corresponds to the matrix (with $n\equiv$`x.len`+1):
$$
\left(
egin{array}{c|c}
{
m DCT}^{(2)}(2^{n-1}) & 0\
\hline
0 & -{
m DST}^{(2)}(2^{n-1})
\end{array}
ight)
$$
**Parameters:**
| Name | Type | Description | Default |
| ---- | -------------- | ---------------------------------------------------------- | ---------- |
| `x` | `QArray[QBit]` | The LSB part of the qubit array to apply the transform to. | *required* |
| `q` | `Const[QBit]` | The MSB of the qubit array to apply the transform to. | *required* |
### qct\_type2
qct\_type2(
x: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies the quantum discrete cosine (DCT)
transform of type 2, $\{
m DCT\}^\{(2)\}$, to the qubit array `x`.
**Parameters:**
| Name | Type | Description | Default |
| ---- | -------------- | ------------------------------------------ | ---------- |
| `x` | `QArray[QBit]` | The qubit array to apply the transform to. | *required* |
### qst\_type2
qst\_type2(
x: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies the quantum discrete sine (DST)
transform of type 2, $\{
m DST\}^\{(2)\}$, to the qubit array `x`.
**Parameters:**
| Name | Type | Description | Default |
| ---- | -------------- | ------------------------------------------ | ---------- |
| `x` | `QArray[QBit]` | The qubit array to apply the transform to. | *required* |
# Encodings
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/encodings
Functions:
| Name | Description |
| --------------------------- | ------------------------------------------------------------------------------ |
| `binary_to_one_hot` | Conversion of binary encoded value to one-hot encoding. |
| `binary_to_unary` | Conversion of binary encoded value to unary encoding. |
| `one_hot_to_unary` | Conversion of one-hot encoded value to unary encoding. |
| `one_hot_to_binary` | Conversion of one-hot encoded value to binary encoding. |
| `unary_to_one_hot` | Conversion of unary encoded value to one-hot encoding. |
| `unary_to_binary` | Conversion of unary encoded value to binary encoding. |
| `inplace_binary_to_one_hot` | Conversion of binary encoded value to one-hot encoding. |
| `inplace_one_hot_to_unary` | Inplace conversion of one-hot encoded value to unary encoding. |
| `pad_zeros` | Pad the input qvar with additional qubits at the end to reach the total\_size. |
### binary\_to\_one\_hot
binary\_to\_one\_hot(
binary: Input\[QNum],
one\_hot: Output\[QArray]
) -> None
Conversion of binary encoded value to one-hot encoding. The output `one_hot` variable
is of size 2^n, where n is the number of bits in the binary representation.
For example, the state `|01>`=`|2>` will be converted to `|0010>` (one-hot for 2).
**Parameters:**
| Name | Type | Description | Default |
| --------- | ---------------- | ---------------------------------------------------------- | ---------- |
| `binary` | `Input[QNum]` | binary input variable to be converted to one-hot encoding. | *required* |
| `one_hot` | `Output[QArray]` | one-hot output array. | *required* |
### binary\_to\_unary
binary\_to\_unary(
binary: Input\[QNum],
unary: Output\[QArray]
) -> None
Conversion of binary encoded value to unary encoding. The output `unary` variable
is of size 2^n - 1, where n is the number of bits in the binary representation.
For example, the state `|01>`=`|2>` will be converted to `|110>` (unary for 2).
**Parameters:**
| Name | Type | Description | Default |
| -------- | ---------------- | -------------------------------------------------------- | ---------- |
| `binary` | `Input[QNum]` | binary input variable to be converted to unary encoding. | *required* |
| `unary` | `Output[QArray]` | unary output array. | *required* |
### one\_hot\_to\_unary
one\_hot\_to\_unary(
one\_hot: Input\[QArray],
unary: Output\[QArray]
) -> None
Conversion of one-hot encoded value to unary encoding. The output `unary` variable
is smaller in 1 qubit than the input `one_hot` variable.
For example, the state `|0010>` (one-hot for 2) will be converted to `|110>` (unary for 2).
**Parameters:**
| Name | Type | Description | Default |
| --------- | ---------------- | ------------------------------------------------------ | ---------- |
| `one_hot` | `Input[QArray]` | one-hot input array to be converted to unary encoding. | *required* |
| `unary` | `Output[QArray]` | unary output array. | *required* |
### one\_hot\_to\_binary
one\_hot\_to\_binary(
one\_hot: Input\[QArray],
binary: Output\[QNum\[Literal\['ceiling(log(one\_hot.len, 2))']]]
) -> None
Conversion of one-hot encoded value to binary encoding. The output `binary` variable
is of size log2(one\_hot.size) rounded up.
For example, the state `|0010>` (one-hot for 2) will be converted to `|01>`=`|2>`.
**Parameters:**
| Name | Type | Description | Default |
| --------- | ------------------------------------------------------- | ------------------------------------------------------- | ---------- |
| `one_hot` | `Input[QArray]` | one-hot input array to be converted to binary encoding. | *required* |
| `binary` | `Output[QNum[Literal['ceiling(log(one_hot.len, 2))']]]` | binary output variable. | *required* |
### unary\_to\_one\_hot
unary\_to\_one\_hot(
unary: Input\[QArray],
one\_hot: Output\[QArray]
) -> None
Conversion of unary encoded value to one-hot encoding. The output `one_hot` variable
is larger in 1 qubit than the input `unary` variable.
For example, the state `|110>` (unary for 2) will be converted to `|0010>` (one-hot for 2).
**Parameters:**
| Name | Type | Description | Default |
| --------- | ---------------- | ------------------------------------------------------ | ---------- |
| `unary` | `Input[QArray]` | unary input array to be converted to one-hot encoding. | *required* |
| `one_hot` | `Output[QArray]` | one-hot output array. | *required* |
### unary\_to\_binary
unary\_to\_binary(
unary: Input\[QArray],
binary: Output\[QNum]
) -> None
Conversion of unary encoded value to binary encoding. The output `binary` variable
is of size log2(unary.size + 1) rounded up.
For example, the state `|110>` (unary for 2) will be converted to `|01>`=`|2>`.
**Parameters:**
| Name | Type | Description | Default |
| -------- | --------------- | ----------------------------------------------------- | ---------- |
| `unary` | `Input[QArray]` | unary input array to be converted to binary encoding. | *required* |
| `binary` | `Output[QNum]` | binary output variable. | *required* |
### inplace\_binary\_to\_one\_hot
inplace\_binary\_to\_one\_hot(
source: Input\[QArray],
target: Output\[QArray]
) -> None
Conversion of binary encoded value to one-hot encoding.
The implementation is based on [https://quantumcomputing.stackexchange.com/questions/5526/garbage-free-reversible-binary-to-unary-decoder-construction](https://quantumcomputing.stackexchange.com/questions/5526/garbage-free-reversible-binary-to-unary-decoder-construction).
The input is assumed to be of size 2^n, where n is the number of bits in the binary representation.
For example, the state `|01000>`=`|2>` will be converted to `|00100>` (one-hot for 2).
**Parameters:**
| Name | Type | Description | Default |
| -------- | ---------------- | ----------------------------------------------------------------------- | ---------- |
| `source` | `Input[QArray]` | binary input array padded with 0's to be converted to one-hot encoding. | *required* |
| `target` | `Output[QArray]` | one-hot output array. | *required* |
### inplace\_one\_hot\_to\_unary
inplace\_one\_hot\_to\_unary(
qvar: QArray
) -> None
Inplace conversion of one-hot encoded value to unary encoding.
The input is assumed to be of size n, where n is the number of bits in the one-hot representation.
The remaining unary representation will at the higher n-1 bits, where the lsb is cleared to 0.
For example, the state `|0010>` (one-hot for 2) will be converted to `|0>``|110>` (unary for 2).
**Parameters:**
| Name | Type | Description | Default |
| ------ | -------- | ------------------------------------------------------ | ---------- |
| `qvar` | `QArray` | one-hot input array to be converted to unary encoding. | *required* |
### pad\_zeros
pad\_zeros(
total\_size: int,
qvar: Input\[QArray],
padded: Output\[QArray]
) -> None
Pad the input qvar with additional qubits at the end to reach the total\_size.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ---------------- | --------------------------------------- | ---------- |
| `total_size` | `int` | The desired total size after padding. | *required* |
| `qvar` | `Input[QArray]` | The input quantum array to be padded. | *required* |
| `padded` | `Output[QArray]` | The output quantum array after padding. | *required* |
# Grover
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/grover
Functions:
| Name | Description |
| -------------------- | --------------------------------- |
| `phase_oracle` | \[Qmod Classiq-library function]. |
| `reflect_about_zero` | \[Qmod Classiq-library function]. |
| `grover_diffuser` | \[Qmod Classiq-library function]. |
| `grover_operator` | \[Qmod Classiq-library function]. |
| `grover_search` | \[Qmod Classiq-library function]. |
### phase\_oracle
phase\_oracle(
predicate: QPerm\[Const\[QArray\[QBit]], QBit],
target: Const\[QArray\[QBit]]
) -> None
\[Qmod Classiq-library function]
Creates a phase oracle operator based on a predicate function.
Applies a predicate function and marks "good" and "bad" states with a phase flip.
If the predicate is marked as $\chi$, and the oracle is marked as $S_\{\chi\}$, then:
$$
S_{\chi}\lvert x \rangle =
\begin{cases}
-\lvert x \rangle & \text{if } \chi(x) = 1 \\
\phantom{-} \lvert x \rangle & \text{if } \chi(x) = 0
\end{cases}
$$
**Parameters:**
| Name | Type | Description | Default |
| ----------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `predicate` | `QPerm[Const[QArray[QBit]], QBit]` | A predicate function that takes a QArray of QBits and sets a single QBit \`\|1>` if the predicate is true, and \`\|0>\` otherwise. | *required* |
| `target` | `Const[QArray[QBit]]` | The target QArray of QBits to apply the phase oracle to. | *required* |
### reflect\_about\_zero
reflect\_about\_zero(
qvar: Const\[QArray\[QBit]]
) -> None
\[Qmod Classiq-library function]
Reflects the state about the `|0>` state (i.e. applies a (-1) phase to all states
besides the `|0>` state). Implements the operator $S_0$:
$$
\begin{equation}
S_0|{x}\rangle = (-1)^{(x\ne0)}|{x}\rangle= (2|{0}\rangle\langle{0}|-I)|{x}\rangle
\end{equation}
$$
**Parameters:**
| Name | Type | Description | Default |
| ------ | --------------------- | ----------------------------- | ---------- |
| `qvar` | `Const[QArray[QBit]]` | The quantum state to reflect. | *required* |
### grover\_diffuser
grover\_diffuser(
space\_transform: QCallable\[QArray\[QBit]],
packed\_vars: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Reflects the given state about the A`|0>` state, where A
is the `space_transform` parameter. It is defined as:
$$
\begin{equation}
D = A S_0 A^{\dagger}
\end{equation}
$$
where $S_0$ is the reflection about the `|0>` state (see `reflect_about_zero`).
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | ------------------------- | -------------------------------------------------- | ---------- |
| `space_transform` | `QCallable[QArray[QBit]]` | The operator which encodes the axis of reflection. | *required* |
| `packed_vars` | `QArray[QBit]` | The state to which to apply the diffuser. | *required* |
### grover\_operator
grover\_operator(
oracle: QCallable\[QArray\[QBit]],
space\_transform: QCallable\[QArray\[QBit]],
packed\_vars: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies the grover operator, defined by:
$$
Q=S_{\psi_0}S_{\psi_1}
$$
where $S_\{\psi_1\}$ is a reflection about the non-marked states, and $S_\{\psi_0\}$ is a reflection
about a given state defined by $|\psi_0\rangle = A|0\rangle$.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------- | ---------- |
| `oracle` | `QCallable[QArray[QBit]]` | A unitary operator which adds a phase of (-1) to marked states. | *required* |
| `space_transform` | `QCallable[QArray[QBit]]` | The operator which creates $\|\psi_0\rangle$, the initial state, used by the diffuser to reflect about it. | *required* |
| `packed_vars` | `QArray[QBit]` | The state to which to apply the grover operator. | *required* |
### grover\_search
grover\_search(
reps: CInt,
oracle: QCallable\[QArray\[QBit]],
packed\_vars: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies Grover search algorithm.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ------------------------- | ------------------------------------------------------------ | ---------- |
| `reps` | `CInt` | Number of repetitions of the grover operator. | *required* |
| `oracle` | `QCallable[QArray[QBit]]` | An oracle that marks the solution. | *required* |
| `packed_vars` | `QArray[QBit]` | Packed form of the variable to apply the grover operator on. | *required* |
# Hea
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/hea
Functions:
| Name | Description |
| ---------- | --------------------------------- |
| `full_hea` | \[Qmod Classiq-library function]. |
### full\_hea
full\_hea(
num\_qubits: CInt,
is\_parametrized: CArray\[CInt],
angle\_params: CArray\[CReal],
connectivity\_map: CArray\[CArray\[CInt]],
reps: CInt,
operands\_1qubit: QCallableList\[Annotated\[CReal, angle], Annotated\[QBit, q]],
operands\_2qubit: QCallableList\[Annotated\[CReal, angle], Annotated\[QBit, q1], Annotated\[QBit, q2]],
x: QArray\[QBit, Literal\['num\_qubits']]
) -> None
\[Qmod Classiq-library function]
Implements an ansatz on a qubit array `x` with the given 1-qubit and 2-qubit operations.
The number of ansatz layers is given in argument `reps`.
Each layer applies the 1-qubit operands in `operands_1qubit` to all the qubits in `x`.
Next, it applies the 2-qubit operands in `operands_2qubit` to qubits (i, j) for each
pair of indices (i, j) in `connectivity_map`.
The list `is_parametrized` specifies whether the operands in `operands_1qubit` and
`operands_2qubit` are parametric (expect a classical argument).
`is_parametrized` is a list of flags (0 and 1 integers) of length
`len(operands_1qubit) + len(operands_2qubit)`.
The first `len(operands_1qubit)` flags refer to the `operands_1qubit` operands and
the next `len(operands_2qubit)` flags refer to the `operands_2qubit` operands.
The classical arguments to the parametric operands are given in argument
`angle_params`.
`angle_params` concatenates a set of arguments for each ansatz layer.
Each set contains an argument for each qubit in `x` times the number
of parametric operands in `operands_1qubit`.
These are followed by an argument for each mapping pair in `connectivity_map` times
the number of parametric operands in `operands_2qubit`.
**Parameters:**
| Name | Type | Description | Default |
| ------------------ | ---------------------------------------------------------------------------------- | -------------------------------------------------- | ---------- |
| `num_qubits` | `CInt` | The length of qubit array x | *required* |
| `is_parametrized` | `CArray[CInt]` | A list of 0 and 1 flags | *required* |
| `angle_params` | `CArray[CReal]` | | *required* |
| `connectivity_map` | `CArray[CArray[CInt]]` | A list of pairs of qubit indices | *required* |
| `reps` | `CInt` | The number of ansatz layers | *required* |
| `operands_1qubit` | `QCallableList[Annotated[CReal, angle], Annotated[QBit, q]]` | A list of operations on a single qubit | *required* |
| `operands_2qubit` | `QCallableList[Annotated[CReal, angle], Annotated[QBit, q1], Annotated[QBit, q2]]` | A list of operations on two qubits | *required* |
| `x` | `QArray[QBit, Literal['num_qubits']]` | The quantum object to be transformed by the ansatz | *required* |
# Linear Combination Of Unitaries
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/linear_combination_of_unitaries
Functions:
| Name | Description |
| ---------------- | --------------------------------- |
| `lcu` | \[Qmod Classiq-library function]. |
| `lcu_pauli` | \[Qmod Classiq-library function]. |
| `prepare_select` | \[Qmod Classiq-library function]. |
### lcu
lcu(
coefficients: list\[float],
unitaries: QCallableList,
block: QNum\[Literal\['max(ceiling(log(coefficients.len, 2)), 1)']]
) -> None
\[Qmod Classiq-library function]
Implements a general linear combination of unitaries (LCU) procedure. The algorithm prepares a superposition
over the `unitaries` according to the given `coefficients`, and then conditionally applies each unitary controlled by the `block`.
The operation is of the form:
$\sum_j \alpha_j U_j$
where $U_j$ is a unitary operation applied to `data`.
**Parameters:**
| Name | Type | Description | Default |
| -------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | ---------- |
| `coefficients` | `list[float]` | L1-normalized array of $\\{ \alpha_j \\}$ of the LCU coefficients. | *required* |
| `unitaries` | `QCallableList` | A list of quantum callable functions to be applied conditionally. | *required* |
| `block` | `QNum[Literal['max(ceiling(log(coefficients.len, 2)), 1)']]` | Quantum variable that holds the superposition index used for conditional application of each unitary. | *required* |
### lcu\_pauli
lcu\_pauli(
operator: SparsePauliOp,
data: QArray\[QBit, Literal\['operator.num\_qubits']],
block: QNum\[Literal\['max(ceiling(log(operator.terms.len, 2)), 1)']]
) -> None
\[Qmod Classiq-library function]
Applies a linear combination of unitaries (LCU) where each unitary is a Pauli term,
represented as a tensor product of Pauli operators. The function prepares a superposition
over the unitaries according to the given magnitudes and phases, and applies the corresponding
Pauli operators conditionally.
This is useful for implementing Hamiltonian terms of the form:
$H=\sum_j \alpha_j P_j$
where $P_j$ is a tensor product of Pauli operators.
The SELECT operator (`_select_paulis`) loads each data qubit's Pauli column from the
`block` index using gray-code uniformly-controlled RZ/RY rotations; the resulting
per-term phases are folded into the coefficients so that the single phase table inside
`prepare_select` corrects them together with the coefficient signs/phases.
**Parameters:**
| Name | Type | Description | Default |
| ---------- | -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `operator` | `SparsePauliOp` | Operator consists of pauli strings with their coefficients, represented in a sparse format. | *required* |
| `data` | `QArray[QBit, Literal['operator.num_qubits']]` | Quantum Variable on which the Pauli operators act. Its size must match the number of qubits required by the Pauli operator. | *required* |
| `block` | `QNum[Literal['max(ceiling(log(operator.terms.len, 2)), 1)']]` | Quantum variable that holds the superposition index used for conditional application of each term. | *required* |
### prepare\_select
prepare\_select(
coefficients: list\[float],
select: QCallable\[QNum],
block: QNum\[Literal\['max(ceiling(log(coefficients.len, 2)), 1)']]
) -> None
\[Qmod Classiq-library function]
Applies the 'Prepare-Select' scheme used for Linear Combination of Unitaries (LCU).
Compared to the `lcu` function, here the Select operator should be provided directly, allowing to take advantage of some structure for
the unitaries of the LCU.
The select operator is defined by: $\mathrm\{SELECT\} = \sum_\{j=0\}^\{m-1\} |j\rangle\!\langle j|_\{block\} \otimes U_j$.
**Parameters:**
| Name | Type | Description | Default |
| -------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `coefficients` | `list[float]` | L1-normalized array of $\\{ \alpha_j \\}$ of the LCU coefficients. | *required* |
| `select` | `QCallable[QNum]` | A quantum callable to be applied between the state preparation and its inverse. Its input is the `block` variable, labeling the index of the unitaries in the LCU. | *required* |
| `block` | `QNum[Literal['max(ceiling(log(coefficients.len, 2)), 1)']]` | A Quantum variable that holds the index used as input for the 'select' operator. | *required* |
# Linear Pauli Rotation
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/linear_pauli_rotation
Functions:
| Name | Description |
| ------------------------ | --------------------------------- |
| `linear_pauli_rotations` | \[Qmod Classiq-library function]. |
### linear\_pauli\_rotations
linear\_pauli\_rotations(
bases: CArray\[Pauli],
slopes: CArray\[CReal],
offsets: CArray\[CReal],
x: QArray\[QBit],
q: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Performs a rotation on a series of $m$ target qubits,
where the rotation angle is a linear function of an $n$-qubit
control register.
Corresponds to the braket notation:
$$
\left|x\right\rangle _{n}\left|q\right\rangle
_{m}\rightarrow\left|x\right\rangle
_{n}\prod_{k=1}^{m}\left(\cos\left(\frac{a_{k}}{2}x+\frac{b_{k}}{2}\right)-
i\sin\left(\frac{a_{k}}{2}x+\frac{b_{k}}{2}\right)P_{k}\right)\left|q_{k}\right\rangle
$$
where $\left|x\right\rangle$ is the control register,
$\left|q\right\rangle$ is the target register, each $P_\{k\}$ is one of
the three Pauli matrices $X$, $Y$, or $Z$, and $a_\{k\}$, $b_\{k\}$ are
the user given slopes and offsets, respectively.
**Parameters:**
| Name | Type | Description | Default |
| --------- | --------------- | ----------------------------------------------------------- | ---------- |
| `bases` | `CArray[Pauli]` | List of Pauli Enums. | *required* |
| `slopes` | `CArray[CReal]` | Rotation slopes for each of the given Pauli bases. | *required* |
| `offsets` | `CArray[CReal]` | Rotation offsets for each of the given Pauli bases. | *required* |
| `x` | `QArray[QBit]` | Quantum state to apply the rotation based on its value. | *required* |
| `q` | `QArray[QBit]` | List of indicator qubits for each of the given Pauli bases. | *required* |
# Modular Arithmetics
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/modular_arithmetics
Functions:
| Name | Description | |
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
| `modular_add_inplace` | \[Qmod Classiq-library function]. | |
| `modular_negate_inplace` | \[Qmod Classiq-library function]. | |
| `modular_subtract_inplace` | \[Qmod Classiq-library function]. | |
| `modular_double_inplace` | \[Qmod Classiq-library function]. | |
| `modular_add_constant_inplace` | \[Qmod Classiq-library function]. | |
| `modular_multiply` | \[Qmod Classiq-library function] Performs the transformation `\|x>``\|y>``\|0>` -> `\|x>``\|y>` | (x\*y mod modulus)>. |
| `modular_square` | \[Qmod Classiq-library function] Performs the transformation `\|x>``\|0>` -> `\|x>` | (x^2 mod modulus)>. |
| `modular_multiply_constant` | \[Qmod Classiq-library function] Performs the transformation `\|x>``\|y>` -> `\|x>` | (x \* a mod modulus)>. |
| `modular_multiply_constant_inplace` | \[Qmod Classiq-library function] In-place modular multiplication of x by a classical constant modulo a symbolic modulus. | |
| `modular_to_montgomery_inplace` | \[Qmod Classiq-library function] Converts a quantum integer `\|x>` into its Montgomery representation modulo modulus in place. | |
| `modular_montgomery_to_standard_inplace` | \[Qmod Classiq-library function] Converts quantum integer `\|x>` from Montgomery representation to standard form in place modulo modulus. | |
| `modular_inverse_inplace` | \[Qmod Classiq-library function] Computes the modular inverse of a quantum number `\|v>` modulo modulus in place, using the Kaliski algorithm. | |
| `kaliski_iteration` | Single iteration of the Kaliski modular inverse algorithm main loop. | |
| `modular_rsub_inplace` | \[Qmod Classiq-library function] Performs the in-place modular right-subtraction `\|x>` -> | (a - x mod modulus)>. |
### modular\_add\_inplace
modular\_add\_inplace(
modulus: CInt,
x: Const\[QNum],
y: QNum
) -> None
\[Qmod Classiq-library function]
Performs the transformation `|x>``|y>` -> `|x>`|(x + y mod modulus)>.
Note:
`\|x>` and `\|y>` should have values smaller than `modulus`.
The modulus should satisfy 1 \< modulus \< 2\*\*n, where n is the size of `|x>` and `|y>`.
Implementation based on: [https://arxiv.org/pdf/1706.06752](https://arxiv.org/pdf/1706.06752) Chapter 3.2 Fig 3
**Parameters:**
| Name | Type | Description | Default |
| --------- | ------------- | ------------------------------------------------------------------------------ | ---------- |
| `modulus` | `CInt` | Classical number modulus (CInt) | *required* |
| `x` | `Const[QNum]` | 1st quantum number input (unsigned). | *required* |
| `y` | `QNum` | 2nd quantum number input (unsigned). Will hold the result after the operation. | *required* |
### modular\_negate\_inplace
modular\_negate\_inplace(
modulus: CInt,
x: QNum
) -> None
\[Qmod Classiq-library function]
Performs the transformation `|x>` -> |(-x mod modulus)>.
Note:
`\|x>` should have values smaller than `modulus`.
The modulus should satisfy 1 \< modulus \< 2\*\*n, where n is the size of `|x>`.
**Parameters:**
| Name | Type | Description | Default |
| --------- | ------ | -------------------------------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus | *required* |
| `x` | `QNum` | Quantum number input (unsigned). Will hold the result after the operation. | *required* |
### modular\_subtract\_inplace
modular\_subtract\_inplace(
modulus: CInt,
x: Const\[QNum],
y: QNum
) -> None
\[Qmod Classiq-library function]
Performs the transformation `|x>``|y>` -> `|x>`|(x - y mod modulus)>.
Note:
`\|x>` and `\|y>` should have values smaller than `modulus`.
The modulus should satisfy 1 \< modulus \< 2\*\*n, where n is the size of `|x>` and `|y>`.
**Parameters:**
| Name | Type | Description | Default |
| --------- | ------------- | ----------------------------------------------------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus | *required* |
| `x` | `Const[QNum]` | 1st quantum number input (unsigned). Const. | *required* |
| `y` | `QNum` | 2nd quantum number input (unsigned). In-place target, will hold the result after the operation. | *required* |
### modular\_double\_inplace
modular\_double\_inplace(
modulus: CInt,
x: QNum
) -> None
\[Qmod Classiq-library function]
Performs the transformation `|x>` -> |(2x mod modulus)>.
Note:
`\|x>` should have a value smaller than `modulus`.
The modulus must be a constant odd integer.
The modulus should satisfy 1 \< modulus \< 2\*\*n, where n is the size of `|x>`.
Implementation based on: [https://arxiv.org/pdf/1706.06752](https://arxiv.org/pdf/1706.06752) Chapter 3.2 Fig 4
**Parameters:**
| Name | Type | Description | Default |
| --------- | ------ | -------------------------------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus | *required* |
| `x` | `QNum` | Quantum number input (unsigned). Will hold the result after the operation. | *required* |
### modular\_add\_constant\_inplace
modular\_add\_constant\_inplace(
modulus: CInt,
a: CInt,
x: QNum
) -> None
\[Qmod Classiq-library function]
Performs the transformation `|x>` -> |(x + a mod modulus)>.
Note:
`\|x>` and `a` should have values smaller than `modulus`.
The modulus should satisfy 1 \< modulus \< 2\*\*n, where n is the size of `|x>`.
Implementation is based on the logic in: [https://arxiv.org/pdf/1706.06752](https://arxiv.org/pdf/1706.06752) Chapter 3.2 Fig 3
**Parameters:**
| Name | Type | Description | Default |
| --------- | ------ | -------------------------------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus | *required* |
| `a` | `CInt` | constant unsigned number input for the addition. | *required* |
| `x` | `QNum` | Quantum number input (unsigned). Will hold the result after the operation. | *required* |
### modular\_multiply
modular\_multiply(
modulus: CInt,
x: Const\[QArray\[QBit]],
y: Const\[QArray\[QBit]],
z: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Performs the transformation `|x>``|y>``|0>` -> `|x>``|y>`|(x\*y mod modulus)>
Note:
`\|x>`, `\|y>` should have the same size and have values smaller than `modulus`.
The modulus must be a constant odd integer.
The modulus should satisfy 1 \< modulus \< 2\*\*n, where n is the size of `|x>` and `|y>`.
The output register z must be pre-allocated with the same size as x and y.
Implementation is based on the logic in: [https://arxiv.org/pdf/1706.06752](https://arxiv.org/pdf/1706.06752) Chapter 3.2 Fig 5
**Parameters:**
| Name | Type | Description | Default |
| --------- | --------------------- | ----------------------------------------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus | *required* |
| `x` | `Const[QArray[QBit]]` | Quantum number input (unsigned), multiplicand. | *required* |
| `y` | `Const[QArray[QBit]]` | Quantum number input (unsigned), multiplier. | *required* |
| `z` | `QArray[QBit]` | Quantum number (unsigned), pre-allocated output variable that will hold the result. | *required* |
### modular\_square
modular\_square(
modulus: CInt,
x: Const\[QArray\[QBit]],
z: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Performs the transformation `|x>``|0>` -> `|x>`|(x^2 mod modulus)>.
Note:
`\|x>` should have the same size and have values smaller than `modulus`.
The modulus must be a constant odd integer.
The modulus should satisfy 1 \< modulus \< 2\*\*n, where n is the size of `|x>`.
The output register z must be pre-allocated with the same size as x.
Implementation is based on: [https://arxiv.org/pdf/1706.06752](https://arxiv.org/pdf/1706.06752) Chapter 3.2 Fig 6
**Parameters:**
| Name | Type | Description | Default |
| --------- | --------------------- | ---------------------------------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus | *required* |
| `x` | `Const[QArray[QBit]]` | Quantum number input (unsigned), the input to square. | *required* |
| `z` | `QArray[QBit]` | Quantum number (unsigned), pre-allocated output variable to hold the result. | *required* |
### modular\_multiply\_constant
modular\_multiply\_constant(
modulus: CInt,
x: Const\[QNum],
a: CInt,
y: QNum
) -> None
\[Qmod Classiq-library function]
Performs the transformation `|x>``|y>` -> `|x>`|(x \* a mod modulus)>.
Note:
`\|x>` and `\|y>` should have values smaller than `modulus`.
The modulus must be a constant odd integer.
The modulus should satisfy 1 \< modulus \< 2\*\*n, where n is the size of `|x>` and `|y>`.
**Parameters:**
| Name | Type | Description | Default |
| --------- | ------------- | --------------------------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus | *required* |
| `x` | `Const[QNum]` | Quantum number (unsigned), input variable. | *required* |
| `a` | `CInt` | Classical number constant | *required* |
| `y` | `QNum` | Quantum number (unsigned), output variable that will hold the result. | *required* |
### modular\_multiply\_constant\_inplace
modular\_multiply\_constant\_inplace(
modulus: CInt,
a: CInt,
x: QNum
) -> None
\[Qmod Classiq-library function]
In-place modular multiplication of x by a classical constant modulo a symbolic modulus.
Performs `|x>` -> |(x \* a mod modulus)>.
Note:
`\|x>` should have values smaller than `modulus`.
The modulus should satisfy 1 \< modulus \< 2\*\*n, where n is the size of `|x>`.
The constant `a` should have an inverse modulo `modulus`, i.e. gcd(a, modulus) = 1.
The constant `a` should satisfy 0 \<= a \< modulus.
**Parameters:**
| Name | Type | Description | Default |
| --------- | ------ | ------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus | *required* |
| `a` | `CInt` | Classical number constant | *required* |
| `x` | `QNum` | Quantum number (unsigned), in-place input/output. | *required* |
### modular\_to\_montgomery\_inplace
modular\_to\_montgomery\_inplace(
modulus: CInt,
x: QNum
) -> None
\[Qmod Classiq-library function]
Converts a quantum integer `|x>` into its Montgomery representation modulo modulus in place.
The Montgomery factor is R = 2**n, where n = x.size (the number of qubits in `|x>`).
This function performs the transformation `|x>` -> |(x \* R mod modulus)>.
Note:
`\|x>` should have values smaller than `modulus`.
The modulus should satisfy 1 \< modulus \< 2**n, where n is the size of `|x>`.
The modulus must be odd so that R = 2\*\*n is invertible modulo modulus (gcd(R, modulus) = 1).
**Parameters:**
| Name | Type | Description | Default |
| --------- | ------ | --------------------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus | *required* |
| `x` | `QNum` | Quantum number, in-place operand to convert to Montgomery form. | *required* |
### modular\_montgomery\_to\_standard\_inplace
modular\_montgomery\_to\_standard\_inplace(
modulus: CInt,
x: QNum
) -> None
\[Qmod Classiq-library function]
Converts quantum integer `|x>` from Montgomery representation to standard form in place modulo modulus.
The Montgomery factor is R = 2**n, where n = x.size (the number of qubits in `|x>`).
This function performs the transformation `|x>` -> |(x \* R^-1 mod modulus)>.
Note:
`\|x>` should have values smaller than `modulus`.
The modulus should satisfy 1 \< modulus \< 2**n, where n is the size of `|x>`.
The modulus must be odd so that R = 2\*\*n is invertible modulo modulus (gcd(R, modulus) = 1).
**Parameters:**
| Name | Type | Description | Default |
| --------- | ------ | ----------------------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus | *required* |
| `x` | `QNum` | Quantum number, in-place operand to convert from Montgomery form. | *required* |
### modular\_inverse\_inplace
modular\_inverse\_inplace(
modulus: CInt,
v: QNum,
m: Output\[QArray\[QBit]]
) -> None
\[Qmod Classiq-library function]
Computes the modular inverse of a quantum number `|v>` modulo modulus in place, using the Kaliski algorithm.
Performs the transformation `|v>` -> |(v^-1 mod modulus)>.
Based on: [https://arxiv.org/pdf/2302.06639](https://arxiv.org/pdf/2302.06639) Chapter 5
Note:
`\|v>` should have values smaller than `modulus`.
If `|v>` = 0, the output will be 0 (although 0 does not have an inverse modulo `modulus`).
The modulus should be prime OR at least gcd(v, modulus) = 1.
The modulus must be a constant odd integer.
The modulus should satisfy 1 \< modulus \< 2\*\*n, where n is the size of `|v>`.
The ancilla qubits m are provided as Output, will be allocated to length 2\*n.
**Parameters:**
| Name | Type | Description | Default |
| --------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus | *required* |
| `v` | `QNum` | Quantum number, in-place operand to compute the modular inverse. | *required* |
| `m` | `Output[QArray[QBit]]` | Output quantum array (QArray\[QBit]) allocated to length 2\*n (n = v.size) and used as ancilla during the algorithm. | *required* |
### kaliski\_iteration
kaliski\_iteration(
modulus: CInt,
i: CInt,
v: QNum,
m: QArray\[QBit],
u: QNum,
r: QNum,
s: QNum,
a: QBit,
b: QBit,
f: QBit
) -> None
Single iteration of the Kaliski modular inverse algorithm main loop.
Based on: [https://arxiv.org/pdf/2302.06639](https://arxiv.org/pdf/2302.06639) Figure 15
Note:
Assumes the global inversion constraints (odd modulus, 1 \< modulus \< 2\*\*n).
Called with 0 \<= v \< modulus; per-iteration ancilla bit is m\[i].
**Parameters:**
| Name | Type | Description | Default |
| --------- | -------------- | ----------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus (CInt) | *required* |
| `i` | `CInt` | Loop iteration index. | *required* |
| `v` | `QNum` | The QNum to invert (quantum number, will be mutated). | *required* |
| `m` | `QArray[QBit]` | Quantum array of ancilla qubits (QArray\[QBit]). | *required* |
| `u` | `QNum` | QNum (quantum number, auxiliary for algorithm). | *required* |
| `r` | `QNum` | QNum (quantum number, auxiliary). | *required* |
| `s` | `QNum` | QNum (quantum number, auxiliary). | *required* |
| `a` | `QBit` | QBit (ancilla qubit) | *required* |
| `b` | `QBit` | QBit (ancilla qubit) | *required* |
| `f` | `QBit` | QBit (ancilla qubit) | *required* |
### modular\_rsub\_inplace
modular\_rsub\_inplace(
modulus: CInt,
a: CInt,
x: QNum
) -> None
\[Qmod Classiq-library function]
Performs the in-place modular right-subtraction `|x>` -> |(a - x mod modulus)>.
Note:
`\|x>` should have values smaller than `modulus`.
The modulus should satisfy 1 \< modulus \< 2\*\*n, where n is the size of `|x>`.
The classical constant `a` should be in the range 0 \<= a \< modulus.
**Parameters:**
| Name | Type | Description | Default |
| --------- | ------ | -------------------------------------------------------------------------- | ---------- |
| `modulus` | `CInt` | Classical number modulus | *required* |
| `a` | `CInt` | Classical constant to subtract from | *required* |
| `x` | `QNum` | Quantum number, in-place operand to perform the modular right-subtraction. | *required* |
# Qaoa Penalty
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/qaoa_penalty
Functions:
| Name | Description |
| ------------------ | --------------------------------- |
| `qaoa_mixer_layer` | \[Qmod Classiq-library function]. |
| `qaoa_cost_layer` | \[Qmod Classiq-library function]. |
| `qaoa_layer` | \[Qmod Classiq-library function]. |
| `qaoa_init` | \[Qmod Classiq-library function]. |
| `qaoa_penalty` | \[Qmod Classiq-library function]. |
### qaoa\_mixer\_layer
qaoa\_mixer\_layer(
b: CReal,
target: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies the mixer layer for the QAOA algorithm.
The mixer layer is a sequence of `X` gates applied to each qubit in the target quantum
array variable.
**Parameters:**
| Name | Type | Description | Default |
| -------- | -------------- | ------------------------------------------- | ---------- |
| `b` | `CReal` | The rotation parameter for the mixer layer. | *required* |
| `target` | `QArray[QBit]` | The target quantum array. | *required* |
### qaoa\_cost\_layer
qaoa\_cost\_layer(
g: CReal,
hamiltonian: CArray\[PauliTerm],
target: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies the cost layer to the QAOA model.
This function integrates the problem-specific cost function into the QAOA model's objective function.
The cost layer represents the primary objective that the QAOA algorithm seeks to optimize, such as
minimizing energy or maximizing profit, depending on the application.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ------------------- | ------------------------------------------------------ | ---------- |
| `g` | `CReal` | The rotation parameter for the cost layer (prefactor). | *required* |
| `hamiltonian` | `CArray[PauliTerm]` | The Hamiltonian terms for the QAOA model. | *required* |
| `target` | `QArray[QBit]` | The target quantum array variable. | *required* |
### qaoa\_layer
qaoa\_layer(
g: CReal,
b: CReal,
hamiltonian: CArray\[PauliTerm],
target: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies the QAOA layer, which concatenates the cost layer and the mixer layer.
The `qaoa_layer` function integrates both the cost and mixer layers, essential components of the
Quantum Approximate Optimization Algorithm (QAOA). The cost layer encodes the problem's objective,
while the mixer layer introduces quantum superposition and drives the search across the solution space.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ------------------- | ------------------------------------------- | ---------- |
| `g` | `CReal` | The rotation parameter for the cost layer. | *required* |
| `b` | `CReal` | The rotation parameter for the mixer layer. | *required* |
| `hamiltonian` | `CArray[PauliTerm]` | The Hamiltonian terms for the QAOA model. | *required* |
| `target` | `QArray[QBit]` | The target quantum array variable. | *required* |
### qaoa\_init
qaoa\_init(
target: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Initializes the QAOA circuit by applying the Hadamard gate to all qubits.
In the Quantum Approximate Optimization Algorithm (QAOA), the initial state is a uniform superposition
created by applying the Hadamard gate to each qubit. This function prepares the qubits for the subsequent
application of the cost and mixer layers by preparing them in an equal superposition state.
**Parameters:**
| Name | Type | Description | Default |
| -------- | -------------- | ---------------------------------- | ---------- |
| `target` | `QArray[QBit]` | The target quantum array variable. | *required* |
### qaoa\_penalty
qaoa\_penalty(
num\_qubits: CInt,
params\_list: CArray\[CReal],
hamiltonian: CArray\[PauliTerm],
target: QArray\[QBit, Literal\['num\_qubits']]
) -> None
\[Qmod Classiq-library function]
Applies the penalty layer to the QAOA model.
This function adds a penalty term to the objective function of the QAOA model to
enforce certain constraints (e.g., binary or integer variables) during the
optimization process.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ------------------------------------- | -------------------------------------------- | ---------- |
| `num_qubits` | `CInt` | The number of qubits in the quantum circuit. | *required* |
| `params_list` | `CArray[CReal]` | | *required* |
| `hamiltonian` | `CArray[PauliTerm]` | The Hamiltonian terms for the QAOA model. | *required* |
| `target` | `QArray[QBit, Literal['num_qubits']]` | The target quantum array variable. | *required* |
# Qft Functions
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/qft_functions
Functions:
| Name | Description |
| ------------- | --------------------------------- |
| `qft_no_swap` | \[Qmod Classiq-library function]. |
| `qft` | \[Qmod Classiq-library function]. |
### qft\_no\_swap
qft\_no\_swap(
qbv: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies the Quantum Fourier Transform (QFT) without the swap gates.
**Parameters:**
| Name | Type | Description | Default |
| ----- | -------------- | ----------------------------------------------- | ---------- |
| `qbv` | `QArray[QBit]` | The quantum number to which the QFT is applied. | *required* |
### qft
qft(
target: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Performs the Quantum Fourier Transform (QFT) on `target` in-place.
Implements the following transformation:
$$
y_{k} = \frac{1}{\sqrt{N}} \sum_{j=0}^{N-1} x_j e^{2\pi i \frac{jk}{N}}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | -------------- | ------------------------------------ | ---------- |
| `target` | `QArray[QBit]` | The quantum object to be transformed | *required* |
# Qpe
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/qpe
Functions:
| Name | Description |
| -------------- | --------------------------------- |
| `qpe_flexible` | \[Qmod Classiq-library function]. |
| `qpe` | \[Qmod Classiq-library function]. |
### qpe\_flexible
qpe\_flexible(
unitary\_with\_power: QCallable\[CInt],
phase: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Implements the Quantum Phase Estimation (QPE) algorithm, which estimates the phase (eigenvalue) associated with an eigenstate of a given unitary operator $U$.
This is a flexible version that allows the user to provide a callable that generates the unitary operator $U^k$ for a given integer $k$, offering greater flexibility in handling different quantum circuits using some powering rule.
**Parameters:**
| Name | Type | Description | Default |
| -------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `unitary_with_power` | `QCallable[CInt]` | A callable that returns the unitary operator $U^k$ given an integer $k$. This callable is used to control the application of powers of the unitary operator. | *required* |
| `phase` | `QArray[QBit]` | The quantum variable that represents the estimated phase (eigenvalue), assuming initialized to zero. | *required* |
### qpe
qpe(
unitary: QCallable,
phase: QNum
) -> None
\[Qmod Classiq-library function]
Implements the standard Quantum Phase Estimation (QPE) algorithm, which estimates the phase (eigenvalue) associated with an eigenstate of a given unitary operator $U$.
**Parameters:**
| Name | Type | Description | Default |
| --------- | ----------- | ---------------------------------------------------------------------------------------------------- | ---------- |
| `unitary` | `QCallable` | A callable representing the unitary operator $U$, whose eigenvalue is to be estimated. | *required* |
| `phase` | `QNum` | The quantum variable that represents the estimated phase (eigenvalue), assuming initialized to zero. | *required* |
# Qsvt
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/qsvt
Functions:
| Name | Description |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `qsvt_step` | \[Qmod Classiq-library function]. |
| `qsvt` | \[Qmod Classiq-library function]. |
| `projector_controlled_phase` | \[Qmod Classiq-library function]. |
| `qsvt_inversion` | \[Qmod Classiq-library function]. |
| `projector_controlled_double_phase` | \[Qmod Classiq-library function]. |
| `qsvt_lcu_step` | \[Qmod Classiq-library function]. |
| `qsvt_lcu` | \[Qmod Classiq-library function]. |
| `gqsp` | Implements Generalized Quantum Signal Processing (GQSP), which realizes a (Laurent) polynomial transformation of degree d on the eigenvalues of the... |
### qsvt\_step
qsvt\_step(
phase1: CReal,
phase2: CReal,
proj\_cnot\_1: QCallable\[QBit],
proj\_cnot\_2: QCallable\[QBit],
u: QCallable,
aux: QBit
) -> None
\[Qmod Classiq-library function]
Applies a single QSVT step, composed of 2 projector-controlled-phase rotations, and applications of the block encoding unitary `u` and its inverse:
$$
\Pi_{\phi_2}U^{\dagger}\tilde{\Pi}_{\phi_{1}}U
$$
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `phase1` | `CReal` | 1st rotation phase. | *required* |
| `phase2` | `CReal` | 2nd rotation phase. | *required* |
| `proj_cnot_1` | `QCallable[QBit]` | Projector-controlled-not unitary that locates the encoded matrix columns within U. Accepts a qubit that should be set to \`\|1>\` when the state is in the block. | *required* |
| `proj_cnot_2` | `QCallable[QBit]` | Projector-controlled-not unitary that locates the encoded matrix rows within U. Accepts a qubit that should be set to \`\|1>\` when the state is in the block. | *required* |
| `u` | `QCallable` | A block encoding unitary matrix. | *required* |
| `aux` | `QBit` | A zero auxilliary qubit, used for the projector-controlled-phase rotations. Given as an inout so that qsvt can be used as a building-block in a larger algorithm. | *required* |
### qsvt
qsvt(
phase\_seq: CArray\[CReal],
proj\_cnot\_1: QCallable\[QBit],
proj\_cnot\_2: QCallable\[QBit],
u: QCallable,
aux: QBit
) -> None
\[Qmod Classiq-library function]
Implements the Quantum Singular Value Transformation (QSVT) - an algorithmic framework, used to apply polynomial transformations of degree `d` on the singular values of a block encoded matrix, given as the unitary `u`. Given a unitary $U$, a list of phase angles $\phi_1, \phi_2, ..., \phi_\{d+1\}$ and 2 projector-controlled-not operands $C_\{\Pi\}NOT,C_\{\tilde\{\Pi\}\}NOT$, the QSVT sequence is as follows:
Given a unitary $U$, a list of phase angles $\phi_1, \phi_2, ..., \phi_\{d+1\}$ and 2 projector-controlled-not operands $C_\{\Pi\}NOT,C_\{\tilde\{\Pi\}\}NOT$, the QSVT sequence is as follows:
$$
\tilde{\Pi}_{\phi_{d+1}}U \prod_{k=1}^{(d-1)/2} (\Pi_{\phi_{d-2k}} U^{\dagger}\tilde{\Pi}_{\phi_{d - (2k+1)}}U)\Pi_{\phi_{1}}
$$
for odd $d$, and:
$$
\prod_{k=1}^{d/2} (\Pi_{\phi_{d-(2k-1)}} U^{\dagger}\tilde{\Pi}_{\phi_{d-2k}}U)\Pi_{\phi_{1}}
$$
for even $d$.
Each of the $\Pi$s is a projector-controlled-phase unitary, according to the given projectors.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `phase_seq` | `CArray[CReal]` | A sequence of phase angles of length d+1. | *required* |
| `proj_cnot_1` | `QCallable[QBit]` | Projector-controlled-not unitary that locates the encoded matrix columns within U. Accepts a qubit that should be set to \`\|1>\` when the state is in the block. | *required* |
| `proj_cnot_2` | `QCallable[QBit]` | Projector-controlled-not unitary that locates the encoded matrix rows within U. Accepts a qubit that should be set to \`\|1>\` when the state is in the block. | *required* |
| `u` | `QCallable` | A block encoding unitary matrix. | *required* |
| `aux` | `QBit` | A zero auxilliary qubit, used for the projector-controlled-phase rotations. Given as an inout so that qsvt can be used as a building-block in a larger algorithm. | *required* |
### projector\_controlled\_phase
projector\_controlled\_phase(
phase: CReal,
proj\_cnot: QCallable\[QBit],
aux: QBit
) -> None
\[Qmod Classiq-library function]
Assigns a phase to the entire subspace determined by the given projector. Corresponds to the operation:
$$
\Pi_{\phi} = (C_{\Pi}NOT) e^{-irac{\phi}{2}Z}(C_{\Pi}NOT)
$$
**Parameters:**
| Name | Type | Description | Default |
| ----------- | ----------------- | --------------------------------------------------------------------------------------------------------------- | ---------- |
| `phase` | `CReal` | A rotation phase. | *required* |
| `proj_cnot` | `QCallable[QBit]` | Projector-controlled-not unitary that sets an auxilliary qubit to \`\|1>\` when the state is in the projection. | *required* |
| `aux` | `QBit` | A zero auxilliary qubit, used for the projector-controlled-phase rotation. | *required* |
### qsvt\_inversion
qsvt\_inversion(
phase\_seq: CArray\[CReal],
block\_encoding\_cnot: QCallable\[QBit],
u: QCallable,
aux: QBit
) -> None
\[Qmod Classiq-library function]
Implements matrix inversion on a given block-encoding of a square matrix, using the QSVT framework. Applies a polynomial approximation
of the inverse of the singular values of the matrix encoded in `u`. The phases for the polynomial should be pre-calculated and passed into the function.
**Parameters:**
| Name | Type | Description | Default |
| --------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `phase_seq` | `CArray[CReal]` | A sequence of phase angles of length d+1, corresponding to an odd polynomial approximation of the scaled inverse function. | *required* |
| `block_encoding_cnot` | `QCallable[QBit]` | Projector-controlled-not unitary that locates the encoded matrix columns within U. Accepts a quantum variable that should be set to \`\|1>\` when the state is in the block. | *required* |
| `u` | `QCallable` | A block encoding unitary matrix. | *required* |
| `aux` | `QBit` | A zero auxilliary qubit, used for the projector-controlled-phase rotations. Given as an inout so that qsvt can be used as a building-block in a larger algorithm. | *required* |
### projector\_controlled\_double\_phase
projector\_controlled\_double\_phase(
phase\_even: CReal,
phase\_odd: CReal,
proj\_cnot: QCallable\[QBit],
aux: QBit,
lcu: QBit
) -> None
\[Qmod Classiq-library function]
Assigns 2 phases to the entire subspace determined by the given projector, each one is controlled differentely on a given `lcu` qvar.
Used in the context of the `qsvt_lcu` function. Corresponds to the operation:
$$
\Pi_{\phi_{odd}, \phi_{even}} = (C_{\Pi}NOT) (C_{lcu=1}e^{-i\frac{\phi_{even}}{2}Z}) (C_{lcu=0}e^{-i\frac{\phi_{odd}}{2}Z}) (C_{\Pi}NOT)
$$
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `phase_even` | `CReal` | Rotation phase, corresponds to 'lcu'=0. | *required* |
| `phase_odd` | `CReal` | Rotation phase, corresponds to 'lcu'=1. | *required* |
| `proj_cnot` | `QCallable[QBit]` | Projector-controlled-not unitary that sets an auxilliary qubit to \`\|1>\` when the state is in the projection. | *required* |
| `aux` | `QBit` | A zero auxilliary qubit, used for the projector-controlled-phase rotation. Given as an inout so that qsvt can be used as a building-block in a larger algorithm. | *required* |
| `lcu` | `QBit` | The quantum variable used for controlling the phase assignment. | *required* |
### qsvt\_lcu\_step
qsvt\_lcu\_step(
phases\_even: CArray\[CReal],
phases\_odd: CArray\[CReal],
proj\_cnot\_1: QCallable\[QBit],
proj\_cnot\_2: QCallable\[QBit],
u: QCallable,
aux: QBit,
lcu: QBit
) -> None
\[Qmod Classiq-library function]
Applies a single QSVT-lcu step, composed of 2 double phase projector-controlled-phase rotations, and applications of the block encoding unitary `u` and its inverse:
$$
(C_{lcu=1}\Pi^{even}_{\phi_2})(C_{lcu=0}\Pi^{odd}_{\phi_2})U^{\dagger}(C_{lcu=1}\tilde{\Pi}^{even}_{\phi_1})(C_{lcu=0}\tilde{\Pi}^{odd}_{\phi_1})U
$$
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `phases_even` | `CArray[CReal]` | 2 rotation phases for the even polynomial | *required* |
| `phases_odd` | `CArray[CReal]` | 2 rotation phases for the odd polynomial | *required* |
| `proj_cnot_1` | `QCallable[QBit]` | Projector-controlled-not unitary that locates the encoded matrix columns within U. Accepts a qubit that should be set to \`\|1>\` when the state is in the block. | *required* |
| `proj_cnot_2` | `QCallable[QBit]` | Projector-controlled-not unitary that locates the encoded matrix rows within U. Accepts a qubit that should be set to \`\|1>\` when the state is in the block. | *required* |
| `u` | `QCallable` | A block encoding unitary matrix. | *required* |
| `aux` | `QBit` | A zero auxilliary qubit, used for the projector-controlled-phase rotations. Given as an inout so that qsvt can be used as a building-block in a larger algorithm. | *required* |
| `lcu` | `QBit` | A qubit used for the combination of 2 polynomials within a single qsvt application | *required* |
### qsvt\_lcu
qsvt\_lcu(
phase\_seq\_even: CArray\[CReal],
phase\_seq\_odd: CArray\[CReal],
proj\_cnot\_1: QCallable\[QBit],
proj\_cnot\_2: QCallable\[QBit],
u: QCallable,
aux: QBit,
lcu: QBit
) -> None
\[Qmod Classiq-library function]
Implements the Quantum Singular Value Transformation (QSVT) for a linear combination of odd and even polynomials, so that
it is possible to encode a polynomial of indefinite parity, such as approximation to exp(i\*A) or exp(A). Should work
for Hermitian block encodings.
The function is equivalent to applying the `qsvt` function for odd and even polynomials with a LCU function, but
is more efficient as the two polynomials share the same applications of the given unitary.
The function is intended to be called within a context of LCU, where it is called as the SELECT operator, and wrapped
with initialization of the `lcu` qubit to get the desired combination coefficients.
The even polynomial corresponds to the case where the $lcu=|0\rangle$, while the odd to $lcu=|1\rangle$.
Note: the two polynomials should have the same degree up to a difference of 1.
**Parameters:**
| Name | Type | Description | Default |
| ---------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `phase_seq_even` | `CArray[CReal]` | A sequence of phase angles of length d+(d+1)%2 for the even polynomial. | *required* |
| `phase_seq_odd` | `CArray[CReal]` | A sequence of phase angles of length d+(d%2) for the odd polynomial. | *required* |
| `proj_cnot_1` | `QCallable[QBit]` | Projector-controlled-not unitary that locates the encoded matrix columns within U. Accepts a qubit that should be set to \`\|1>\` when the state is in the block. | *required* |
| `proj_cnot_2` | `QCallable[QBit]` | Projector-controlled-not unitary that locates the encoded matrix rows within U. Accepts a qubit that should be set to \`\|1>\` when the state is in the block. | *required* |
| `u` | `QCallable` | A block encoding unitary matrix. | *required* |
| `aux` | `QBit` | A zero auxilliary qubit, used for the projector-controlled-phase rotations. Given as an inout so that qsvt can be used as a building-block in a larger algorithm. | *required* |
| `lcu` | `QBit` | A qubit used for the combination of 2 polynomials within a single qsvt application | *required* |
### gqsp
gqsp(
u: QCallable,
aux: QBit,
phases: CArray\[CArray\[CReal, Literal\[3]]],
negative\_power: CInt
) -> None
Implements Generalized Quantum Signal Processing (GQSP), which realizes a
(Laurent) polynomial transformation of degree d on the eigenvalues of the given
signal unitary `u`. The protocol is according to [https://arxiv.org/abs/2308.01501](https://arxiv.org/abs/2308.01501)
Fig.2.
Notes:
* The user is encouraged to use the function `gqsp_phases` to find `phases` that
correspond to the wanted polynomial transformation.
* Feasibility: the target polynomial must satisfy $|P(e^\{i*theta\})|$ \<= 1 for all
theta in $[0, 2*pi)$. This ensures a unitary completion exists.
* Using `negative_power = m` (m >= 0) you can realize Laurent polynomials with
negative exponents: the implemented transform is equivalent to applying
$z^\{-m\} * P(z)$ (i.e., shift the minimal degree to -m).
For ordinary (non-Laurent) polynomials, set `negative_power = 0`.
**Parameters:**
| Name | Type | Description | Default |
| ---------------- | ----------------------------------- | ------------------------------------------------------------------------------------------ | ---------- |
| `u` | `QCallable` | The signal unitary. | *required* |
| `aux` | `QBit` | Auxiliary qubit used for the phase rotations. Should start in \`\|0>\`. | *required* |
| `phases` | `CArray[CArray[CReal, Literal[3]]]` | (d+1) x 3 real array of angles: each element is (theta, phi, lambda). | *required* |
| `negative_power` | `CInt` | Integer m in \[0, d]. Encodes the minimal Laurent power -m of the realized transformation. | *required* |
# State Preparation
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/state_preparation
Functions:
| Name | Description |
| ------------------------------------ | --------------------------------- |
| `prepare_uniform_trimmed_state` | \[Qmod Classiq-library function]. |
| `prepare_uniform_interval_state` | \[Qmod Classiq-library function]. |
| `prepare_ghz_state` | \[Qmod Classiq-library function]. |
| `prepare_exponential_state` | \[Qmod Classiq-library function]. |
| `prepare_bell_state` | \[Qmod Classiq-library function]. |
| `inplace_prepare_int` | \[Qmod Classiq-library function]. |
| `prepare_int` | \[Qmod Classiq-library function]. |
| `prepare_complex_amplitudes` | \[Qmod Classiq-library function]. |
| `inplace_prepare_complex_amplitudes` | \[Qmod Classiq-library function]. |
| `prepare_dicke_state` | \[Qmod Classiq-library function]. |
| `prepare_dicke_state_unary_input` | \[Qmod Classiq-library function]. |
| `prepare_basis_state` | \[Qmod Classiq-library function]. |
| `prepare_linear_amplitudes` | \[Qmod Classiq-library function]. |
| `prepare_sparse_amplitudes` | \[Qmod Classiq-library function]. |
| `inplace_prepare_sparse_amplitudes` | \[Qmod Classiq-library function]. |
### prepare\_uniform\_trimmed\_state
prepare\_uniform\_trimmed\_state(
m: CInt,
q: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Initializes a quantum variable in a uniform superposition of the first `m` computational basis states:
$$
\left|\text{q}\right\rangle = \frac{1}{\sqrt{m}}\sum_{i=0}^{m-1}{|i\rangle}
$$
The number of allocated qubits would be $\left\lceil\log_2\{m\}\right\rceil$.
The function is especially useful when `m` is not a power of 2.
**Parameters:**
| Name | Type | Description | Default |
| ---- | -------------- | ------------------------------------------------------------------------------------ | ---------- |
| `m` | `CInt` | The number of states to load in the superposition. | *required* |
| `q` | `QArray[QBit]` | The quantum variable that will receive the initialized state. Must be uninitialized. | *required* |
### prepare\_uniform\_interval\_state
prepare\_uniform\_interval\_state(
start: CInt,
end: CInt,
q: QNum
) -> None
\[Qmod Classiq-library function]
Initializes a quantum variable in a uniform superposition of the specified interval in the computational basis states:
$$
\left|\text{q}\right\rangle = \frac{1}{\sqrt{\text{end} - \text{start}}}\sum_{i=\text{start}}^{\text{end}-1}{|i\rangle}
$$
The number of allocated qubits would be $\left\lceil\log_2\{\left(\text\{end\}\right)\}\right\rceil$.
**Parameters:**
| Name | Type | Description | Default |
| ------- | ------ | ------------------------------------------------------------------------------------ | ---------- |
| `start` | `CInt` | The lower bound of the interval to load (inclusive). | *required* |
| `end` | `CInt` | The upper bound of the interval to load (exclusive). | *required* |
| `q` | `QNum` | The quantum variable that will receive the initialized state. Must be uninitialized. | *required* |
### prepare\_ghz\_state
prepare\_ghz\_state(
size: CInt,
q: Output\[QArray\[QBit]]
) -> None
\[Qmod Classiq-library function]
Initializes a quantum variable in a Greenberger-Horne-Zeilinger (GHZ) state. i.e., a balanced superposition of all ones and all zeros, on an arbitrary number of qubits..
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---------------------- | ------------------------------------------------------------------------------------ | ---------- |
| `size` | `CInt` | The number of qubits in the GHZ state. Must be a positive integer. | *required* |
| `q` | `Output[QArray[QBit]]` | The quantum variable that will receive the initialized state. Must be uninitialized. | *required* |
### prepare\_exponential\_state
prepare\_exponential\_state(
rate: CInt,
q: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Prepares a quantum state with exponentially decreasing amplitudes. The state is prepared in the computational basis, with the amplitudes of the states decreasing exponentially with the index of the state:
$$
P(n) = \frac{1}{Z} e^{- \text{rate} \cdot n}
$$
**Parameters:**
| Name | Type | Description | Default |
| ------ | -------------- | ---------------------------------- | ---------- |
| `rate` | `CInt` | The rate of the exponential decay. | *required* |
| `q` | `QArray[QBit]` | The quantum register to prepare. | *required* |
### prepare\_bell\_state
prepare\_bell\_state(
state\_num: CInt,
qpair: Output\[QArray\[QBit, Literal\[2]]]
) -> None
\[Qmod Classiq-library function]
Initializes a quantum array of size 2 in one of the four Bell states.
**Parameters:**
| Name | Type | Description | Default |
| ----------- | ---------------------------------- | ------------------------------------------------------------------------------------ | ---------- |
| `state_num` | `CInt` | The number of the Bell state to be prepared. Must be an integer between 0 and 3. | *required* |
| `qpair` | `Output[QArray[QBit, Literal[2]]]` | The quantum variable that will receive the initialized state. Must be uninitialized. | *required* |
### inplace\_prepare\_int
inplace\_prepare\_int(
value: CInt,
target: QNum
) -> None
\[Qmod Classiq-library function]
This function is **deprecated**. Use in-place-xor assignment statement in the form *target-var* **^=** *quantum-expression* or **inplace\_xor(***quantum-expression***,** *target-var*\*\*)\*\* instead.
Transitions a quantum variable in the zero state $|0\rangle$ into the computational basis state $|\text\{value\}\rangle$.
In the general case, the function performs a bitwise-XOR, i.e. transitions the state $|\psi\rangle$ into $|\psi \oplus \text\{value\}\rangle$.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------ | -------------------------------------------- | ---------- |
| `value` | `CInt` | The value to assign to the quantum variable. | *required* |
| `target` | `QNum` | The quantum variable to act upon. | *required* |
### prepare\_int
prepare\_int(
value: CInt,
out: Output\[QNum\[Literal\['floor(log(value, 2)) + 1']]]
) -> None
\[Qmod Classiq-library function]
This function is **deprecated**. Use assignment statement in the form *target-var* **|=** *quantum-expression* or **assign(***quantum-expression***,** *target-var*\*\*)\*\* instead.
Initializes a quantum variable to the computational basis state $|\text\{value\}\rangle$.
The number of allocated qubits is automatically computed from the value, and is the minimal number required for representation in the computational basis.
**Parameters:**
| Name | Type | Description | Default |
| ------- | --------------------------------------------------- | ------------------------------------------------------ | ---------- |
| `value` | `CInt` | The value to assign to the quantum variable. | *required* |
| `out` | `Output[QNum[Literal['floor(log(value, 2)) + 1']]]` | The allocated quantum variable. Must be uninitialized. | *required* |
### prepare\_complex\_amplitudes
prepare\_complex\_amplitudes(
magnitudes: CArray\[CReal],
phases: list\[float],
out: Output\[QArray\[QBit, Literal\['log(magnitudes.len, 2)']]]
) -> None
\[Qmod Classiq-library function]
Initializes and prepares a quantum state with amplitudes and phases for each state according to the given parameters, in polar representation.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | --------------------------------------------------------- | --------------------------------------------------------------------------- | ---------- |
| `magnitudes` | `CArray[CReal]` | Absolute values of the state amplitudes. | *required* |
| `phases` | `list[float]` | phases of the state amplitudes. should be of the same size as `amplitudes`. | *required* |
| `out` | `Output[QArray[QBit, Literal['log(magnitudes.len, 2)']]]` | The allocated quantum variable. Must be uninitialized. | *required* |
### inplace\_prepare\_complex\_amplitudes
inplace\_prepare\_complex\_amplitudes(
magnitudes: CArray\[CReal],
phases: list\[float],
target: QArray\[QBit, Literal\['log(magnitudes.len, 2)']]
) -> None
\[Qmod Classiq-library function]
Prepares a quantum state with amplitudes and phases for each state according to the given parameters, in polar representation.
Expects to act on an initialized zero state $|0\rangle$.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ------------------------------------------------- | --------------------------------------------------------------------------- | ---------- |
| `magnitudes` | `CArray[CReal]` | Absolute values of the state amplitudes. | *required* |
| `phases` | `list[float]` | phases of the state amplitudes. should be of the same size as `amplitudes`. | *required* |
| `target` | `QArray[QBit, Literal['log(magnitudes.len, 2)']]` | The quantum variable to act upon. | *required* |
### prepare\_dicke\_state
prepare\_dicke\_state(
k: int,
qvar: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Prepares a Dicke state with k excitations over the provided quantum register.
A Dicke state of n qubits with k excitations is an equal superposition of all basis states
with exactly k qubits in the $|1\rangle$ state and $(n - k)$ qubits in the $|0\rangle$ state.
For example, $\mathrm\{Dicke\}(2, 1) = (|01\rangle + |10\rangle) / \sqrt(2)$.
In the general case it is defined to be:
$\mathrm\{Dicke\}(n, k) = \frac\{1\}\{\sqrt\{\binom\{n\}\{k\}\}\} \sum_\{x \in \\{0,1\\}^n,\, |x| = k\} |x\rangle$
**Parameters:**
| Name | Type | Description | Default |
| ------ | -------------- | ------------------------------------------------------------------------------------------------- | ---------- |
| `k` | `int` | The number of excitations (i.e., number of qubits in state $\|1\rangle$). | *required* |
| `qvar` | `QArray[QBit]` | The quantum register (array of qubits) to initialize. Must be uninitialized and have length >= k. | *required* |
### prepare\_dicke\_state\_unary\_input
prepare\_dicke\_state\_unary\_input(
max\_k: int,
qvar: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Prepares a Dicke state with a variable number of excitations based on a unary-encoded input.
The Dicke state is defined to be:
$\mathrm\{Dicke\}(n, k) = \frac\{1\}\{\sqrt\{\binom\{n\}\{k\}\}\} \sum_\{x \in \\{0,1\\}^n,\, |x| = k\} |x\rangle$
The input register `qvar` is expected to already be initialized in a unary encoding:
the value k is represented by a string of k ones followed by zeros, e.g., k = 3 -> |11100...0>.
The function generates a Dicke state with k excitations over a new quantum register,
where 0 \<= k \< max\_k.
**Parameters:**
| Name | Type | Description | Default |
| ------- | -------------- | ---------------------------------------------------------------------------------- | ---------- |
| `max_k` | `int` | The maximum number of allowed excitations (upper bound for k). | *required* |
| `qvar` | `QArray[QBit]` | Unary-encoded quantum input register of length >= max\_k. Must be pre-initialized. | *required* |
### prepare\_basis\_state
prepare\_basis\_state(
state: list\[bool],
arr: Output\[QArray]
) -> None
\[Qmod Classiq-library function]
Initializes a quantum array in the specified basis state.
**Parameters:**
| Name | Type | Description | Default |
| ------- | ---------------- | ----------------------------- | ---------- |
| `state` | `list[bool]` | | *required* |
| `arr` | `Output[QArray]` | The quantum array to prepare. | *required* |
### prepare\_linear\_amplitudes
prepare\_linear\_amplitudes(
x: QArray
) -> None
\[Qmod Classiq-library function]
Initializes a quantum variable in a state with linear amplitudes:
$$$|\psi
angle = rac\{1\}\{Z\}\sum_\{x=0\}^\{2^n-1\}\{x|x
angle\}$$
Where $Z$ is a normalization constant.
Based on the paper https://quantum-journal.org/papers/q-2024-03-21-1297/pdf/
**Parameters:**
| Name | Type | Description | Default |
| ---- | ---- | ----------- | ------- |
| `x` | `QArray` | The quantum register to prepare. | *required* |
### prepare_sparse_amplitudes
prepare_sparse_amplitudes(
states: list[int],
amplitudes: list[complex],
out: Output[QArray]
) -> None
[Qmod Classiq-library function]
Initializes and prepares a quantum state with the given (complex) amplitudes. The input is given sparse format, as a list of non-zero states and their corresponding amplitudes.
Notice that the function is only suitable sparse states. Inspired by https://arxiv.org/abs/2310.19309.
For example, `prepare_sparse_amplitudes([1, 8], [np.sqrt(0.5), np.sqrt(0.5)], out)` will and allocate it to be of size 4 qubits, and
prepare it in the state sqrt(0.5)`|1>` + sqrt(0.5)`|8>`.
Complexity: Asymptotic gate complexity is $O(dn)$ where d is the number of states and n is the required number of qubits.
**Parameters:**
| Name | Type | Description | Default |
| ---- | ---- | ----------- | ------- |
| `states` | `list[int]` | A list of distinct computational basis indices to populate. Each integer corresponds to the basis state in the computational basis. | *required* |
| `amplitudes` | `list[complex]` | A list of complex amplitudes for the corresponding entries in `states`. Must have the same length as `states`. | *required* |
| `out` | `Output[QArray]` | The allocated quantum variable. | *required* |
### inplace_prepare_sparse_amplitudes
inplace_prepare_sparse_amplitudes(
states: list[int],
amplitudes: list[complex],
target: QArray
) -> None
[Qmod Classiq-library function]
Prepares a quantum state with the given (complex) amplitudes. The input is given sparse format, as a list of non-zero states and their corresponding amplitudes.
Notice that the function is only suitable sparse states. Inspired by https://arxiv.org/abs/2310.19309.
For example, `inplace_prepare_sparse_amplitudes([1, 8], [np.sqrt(0.5), np.sqrt(0.5)], target)` will prepare the state sqrt(0.5)`|1>` + sqrt(0.5)`|8>`
on the target variable, assuming it starts in the `|0>` state.
Complexity: Asymptotic gate complexity is $O(dn)$ where d is the number of states and n is the target number of qubits.
**Parameters:**
| Name | Type | Description | Default |
| ---- | ---- | ----------- | ------- |
| `states` | `list[int]` | A list of distinct computational basis indices to populate. Each integer corresponds to the basis state in the computational basis. | *required* |
| `amplitudes` | `list[complex]` | A list of complex amplitudes for the corresponding entries in `states`. Must have the same length as `states`. | *required* |
| `target` | `QArray` | The quantum variable on which the state is to be prepared. Its size must be sufficient to represent all states in `states`. | *required* |
$$$
# Swap Test
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/swap_test
Functions:
| Name | Description |
| ----------- | --------------------------------- |
| `swap_test` | \[Qmod Classiq-library function]. |
### swap\_test
swap\_test(
state1: QArray\[QBit],
state2: QArray\[QBit],
test: Output\[QBit]
) -> None
\[Qmod Classiq-library function]
Tests the overlap (in terms of fidelity) of two quantum states.
The fidelity of `state1` and `state2` is calculated from the probability of measuring `test` qubit in the state 0 as follows:
$$
|\langle state1 | state2 \rangle |^2 = 2*Prob(test=0)-1
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | -------------- | ----------------------------------------------------------------------------------------------------- | ---------- |
| `state1` | `QArray[QBit]` | A quantum state to check its overlap with state2. | *required* |
| `state2` | `QArray[QBit]` | A quantum state to check its overlap with state1. | *required* |
| `test` | `Output[QBit]` | A qubit for which the probability of measuring 0 is $0.5*(\|\langle state1 \| state2 \rangle \|^2+1)$ | *required* |
# Utility Functions
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/utility_functions
Functions:
| Name | Description |
| -------------------- | --------------------------------- |
| `apply_to_all` | \[Qmod Classiq-library function]. |
| `hadamard_transform` | \[Qmod Classiq-library function]. |
| `modular_increment` | \[Qmod Classiq-library function]. |
### apply\_to\_all
apply\_to\_all(
gate\_operand: QCallable\[Annotated\[QBit, target]],
target: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies the single-qubit operand `gate_operand` to each qubit in the qubit
array `target`.
**Parameters:**
| Name | Type | Description | Default |
| -------------- | ------------------------------------ | ---------------------------------------------------------- | ---------- |
| `gate_operand` | `QCallable[Annotated[QBit, target]]` | The single-qubit gate to apply to each qubit in the array. | *required* |
| `target` | `QArray[QBit]` | The qubit array to apply the gate to. | *required* |
### hadamard\_transform
hadamard\_transform(
target: QArray\[QBit]
) -> None
\[Qmod Classiq-library function]
Applies Hadamard transform to the target qubits.
Corresponds to the braket notation:
$$
H^{\otimes n} |x\rangle = \frac{1}{\sqrt{2^n}} \sum_{y=0}^{2^n - 1} (-1)^{x \\cdot y} |y\rangle
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | -------------- | ----------------------------------------- | ---------- |
| `target` | `QArray[QBit]` | qubits to apply to Hadamard transform to. | *required* |
### modular\_increment
modular\_increment(
a: CInt,
x: QNum
) -> None
\[Qmod Classiq-library function]
Adds $a$ to $x$ modulo the range of $x$, assumed that $x$ is a non-negative integer and $a$ is an integer.
Mathematically it is described as:
$$
x = (x+a)\ \mod \ 2^{x.size}-1
$$
**Parameters:**
| Name | Type | Description | Default |
| ---- | ------ | ------------------------------------------------------------ | ---------- |
| `a` | `CInt` | A classical integer to be added to x. | *required* |
| `x` | `QNum` | A quantum number that is assumed to be non-negative integer. | *required* |
# Variational
Source: https://docs.classiq.io/sdk-reference/qmod/functions/open_library/variational
Functions:
| Name | Description |
| ----------------- | --------------------------------- |
| `encode_in_angle` | \[Qmod Classiq-library function]. |
| `encode_on_bloch` | \[Qmod Classiq-library function]. |
### encode\_in\_angle
encode\_in\_angle(
data: CArray\[CReal],
qba: Output\[QArray\[QBit]]
) -> None
\[Qmod Classiq-library function]
Creates an angle encoding of n data points on n qubits.
Applies RY($\pi$data\[i]) on qba\[i].
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---------------------- | -------------------------------------------------- | ---------- |
| `data` | `CArray[CReal]` | A classical array representing the data to encode. | *required* |
| `qba` | `Output[QArray[QBit]]` | The array of qubits on which the data is encoded. | *required* |
### encode\_on\_bloch
encode\_on\_bloch(
data: CArray\[CReal],
qba: Output\[QArray]
) -> None
\[Qmod Classiq-library function]
Creates a dense angle encoding of n data points on n//2 qubits.
Encodes pairs of data points on a Bloch sphere, via RX($\pi$data\[2*i])RZ($\pi$data\[2*i+1]) on qba\[i].
If the length of the data is odd then RX($\pi$data\[i]) is applied on the last qubit.
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---------------- | -------------------------------------------------- | ---------- |
| `data` | `CArray[CReal]` | A classical array representing the data to encode. | *required* |
| `qba` | `Output[QArray]` | The QArray of QBits on which the data is encoded. | *required* |
# Operations
Source: https://docs.classiq.io/sdk-reference/qmod/operations
This is a list of the operations that are built-in in `Qmod`.
For more information regarding classical types see the `Statements` section in the [language reference](/qmod-reference/language-reference/index).
Members:
| Name | Description |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `QuantumLambdaFunction` | The definition of an anonymous function passed as operand to higher-level functions. |
| `H` | \[Qmod core-library function]. |
| `S` | \[Qmod core-library function]. |
| `QBit` | A type representing a single qubit. |
| `QNum` | QNum is a quantum variable that represents a numeric value, which can be either integer or fixed-point, encoded within a quantum register. |
| `allocate` | Initialize a quantum variable to a new quantum object in the zero state:. |
| `bind` | Reassign qubit or arrays of qubits by redirecting their logical identifiers. |
| `if_` | Conditionally executes quantum operations based on a symbolic or boolean expression. |
| `control` | Conditionally executes quantum operations based on the value of quantum variables or expressions. |
| `skip_control` | Applies quantum statements unconditionally. |
| `assign` | Initialize a scalar quantum variable using an arithmetic expression. |
| `inplace_add` | Add an arithmetic expression to a quantum variable. |
| `inplace_xor` | Bitwise-XOR a quantum variable with an arithmetic expression. |
| `within_apply` | Given two operations $U$ and $V$, performs the composition of operations $U^\{-1\} V U$. |
| `repeat` | Executes a quantum loop a specified number of times, applying a quantum operation on each iteration. |
| `power` | Apply a quantum operation raised to a symbolic or integer power. |
| `invert` | Apply the inverse of a quantum gate. |
| `phase` | Applies a state-dependent or fixed phase shift (Z rotation) to the quantum state. |
| `foreach` | Loops through the elements of a classical list, applying a quantum operation on each iteration. |
| `assign_amplitude_poly_sin` | Encodes the value of the sine/cosine of a polynomial into the amplitude of the respective computational basis state:. |
| `lookup_table` | Reduces a classical function into a lookup table over all the possible values of the quantum numbers. |
## QuantumLambdaFunction
The definition of an anonymous function passed as operand to higher-level functions
**Methods:**
| Name | Description |
| ------------------------------------------------- | ----------- |
| [has\_generative\_blocks](#has_generative_blocks) | |
| [set\_py\_callable](#set_py_callable) | |
| [set\_op\_decl](#set_op_decl) | |
**Attributes:**
| Name | Type | Description |
| ------------------- | ------------------------------- | ----------- |
| `pos_rename_params` | `list[str]` | |
| `body` | `StatementBlock` | |
| `py_callable` | `Callable` | |
| `func_decl` | `AnonQuantumOperandDeclaration` | |
| `named_func_decl` | `AnonQuantumOperandDeclaration` | |
### has\_generative\_blocks
has\_generative\_blocks(
self:
) -> bool
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### set\_py\_callable
set\_py\_callable(
self: ,
py\_callable: Callable
) -> None
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ---------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `py_callable` | `Callable` | | *required* |
### set\_op\_decl
set\_op\_decl(
self: ,
fd: AnonQuantumOperandDeclaration
) -> None
**Parameters:**
| Name | Type | Description | Default |
| ------ | ------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `fd` | `AnonQuantumOperandDeclaration` | | *required* |
### H
H(
target: QBit
) -> None
\[Qmod core-library function]
Performs the Hadamard gate on a qubit.
This operation is represented by the following matrix:
$$
H = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------ | ---------------------------------------- | ---------- |
| `target` | `QBit` | The qubit to apply the Hadamard gate to. | *required* |
### S
S(
target: Const\[QBit]
) -> None
\[Qmod core-library function]
Performs the S gate on a qubit.
This operation is represented by the following matrix:
$$
S = \begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix}
$$
**Parameters:**
| Name | Type | Description | Default |
| -------- | ------------- | --------------------------------- | ---------- |
| `target` | `Const[QBit]` | The qubit to apply the S gate to. | *required* |
## QBit
A type representing a single qubit.
`QBit` serves both as a placeholder for a temporary, non-allocated qubit
and as the type of an allocated physical or logical qubit.
Conceptually, a qubit is a two-level quantum system, described by the
superposition of the computational basis states:
$$
|0\rangle = \begin{pmatrix} 1 \\ 0 \end{pmatrix},
\quad
|1\rangle = \begin{pmatrix} 0 \\ 1 \end{pmatrix}
$$
Therefore, a qubit state is a linear combination:
$$
|\psi\rangle = \alpha |0\rangle + \beta |1\rangle,
$$
where ( \alpha ) and ( \beta ) are complex numbers satisfying:
$$
|\alpha|^2 + |\beta|^2 = 1.
$$
Typical usage includes:
* Representing an unallocated qubit before its allocation.
* Acting as the output type for a qubit or an allocated qubit in the main function after calling an allocation function.
Examples:
**Methods:**
| Name | Description |
| --------------------------------- | ----------- |
| [to\_qvar](#to_qvar) | |
| [get\_qmod\_type](#get_qmod_type) | |
### to\_qvar
to\_qvar(
cls: ,
origin: str | Expr,
type\_hint: Any
) -> QBit
**Parameters:**
| Name | Type | Description | Default |
| ----------- | ------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `origin` | `str \| Expr` | | *required* |
| `type_hint` | `Any` | | *required* |
### get\_qmod\_type
get\_qmod\_type(
self:
) -> ConcreteQuantumType
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
## QNum
QNum is a quantum variable that represents a numeric value, which can be either integer or fixed-point,
encoded within a quantum register. It consists of an array of qubits for quantum representation and
classical metadata (number of fraction digits, sign) to define its numeric behavior.
QNum enables numerical computation in quantum circuits, supporting both signed and unsigned
formats, as well as configurable fixed-point precision. It is a parameterizable scalar type,
meaning its behavior can depend on symbolic or compile-time values. The total number of
qubits (`size`) determines the resolution and range of representable values.
**Methods:**
| Name | Description |
| ------------------------------------------- | ----------- |
| [to\_qvar](#to_qvar) | |
| [get\_qmod\_type](#get_qmod_type) | |
| [get\_maximal\_bounds](#get_maximal_bounds) | |
**Attributes:**
| Name | Type | Description |
| ------------------- | ---------------------- | ----------- |
| `CONSTRUCTOR_DEPTH` | `'3'` | |
| `fraction_digits` | `CParamScalar \| int` | |
| `is_signed` | `CParamScalar \| bool` | |
### to\_qvar
to\_qvar(
cls: ,
origin: str | Expr,
type\_hint: Any
) -> QNum
**Parameters:**
| Name | Type | Description | Default |
| ----------- | ------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `origin` | `str \| Expr` | | *required* |
| `type_hint` | `Any` | | *required* |
### get\_qmod\_type
get\_qmod\_type(
self:
) -> ConcreteQuantumType
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### get\_maximal\_bounds
get\_maximal\_bounds(
self:
) -> tuple\[float, float]
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### allocate
allocate(
args: Any = (),
kwargs: Any =
) -> None
Initialize a quantum variable to a new quantum object in the zero state:
$$
\left|\text{out}\right\rangle = \left|0\right\rangle^{\otimes \text{num_qubits}}
$$
If 'num\_qubits' is not specified, it will be inferred according to the type of 'out'.
In case the quantum variable is of type `QNum`, its numeric attributes can be specified as
well.
**Parameters:**
| Name | Type | Description | Default |
| -------- | ----- | ----------- | ------- |
| `args` | `Any` | | () |
| `kwargs` | `Any` | | |
### bind
bind(
source: Input\[QVar] | list\[Input\[QVar]],
destination: Output\[QVar] | list\[Output\[QVar]]
) -> None
Reassign qubit or arrays of qubits by redirecting their logical identifiers.
This operation rewires the logical identity of the `source` qubits to new objects given in `destination`.
For example, an array of two qubits `X` can be mapped to individual qubits `Y` and `Z`.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ------------------------------------ | ----------------------------------------------------------------------------------------- | ---------- |
| `source` | `Input[QVar] \| list[Input[QVar]]` | A qubit or list of initialized qubits to reassign. | *required* |
| `destination` | `Output[QVar] \| list[Output[QVar]]` | A qubit or list of target qubits to bind to. Must match the number of qubits in `source`. | *required* |
### if\_
if\_(
condition: SymbolicExpr | bool,
then: QCallable | Callable\[\[], Statements],
else\_: QCallable | Callable\[\[], Statements] | int = \_MISSING\_VALUE
) -> None
Conditionally executes quantum operations based on a symbolic or boolean expression.
This function defines classical control flow within a quantum program. It allows quantum operations to be
conditionally executed based on symbolic expressions - such as parameters used in variational algorithms,
loop indices, or other classical variables affecting quantum control flow.
**Parameters:**
| Name | Type | Description | Default |
| ----------- | ---------------------------------------------- | -------------------------------------------------------------------------------------- | ---------------- |
| `condition` | `SymbolicExpr \| bool` | A symbolic or boolean expression evaluated at runtime to determine the execution path. | *required* |
| `then` | `QCallable \| Callable[[], Statements]` | A quantum operation executed when `condition` evaluates to True. | *required* |
| `else_` | `QCallable \| Callable[[], Statements] \| int` | (Optional) A quantum operation executed when `condition` evaluates to False. | \_MISSING\_VALUE |
### control
control(
ctrl: SymbolicExpr | QBit | QArray\[QBit] | list\[QVar],
stmt\_block: QCallable | Callable\[\[], Statements],
else\_block: QCallable | Callable\[\[], Statements] | None = None
) -> None
Conditionally executes quantum operations based on the value of quantum variables or expressions.
This operation enables quantum control flow similar to classical `if` statements. It evaluates a quantum condition
and executes one of the provided quantum code blocks accordingly.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `ctrl` | `SymbolicExpr \| QBit \| QArray[QBit] \| list[QVar]` | A quantum control expression, which can be a logical expression, a single `QBit`, or a `QArray[QBit]`. If `ctrl` is a logical expression, `stmt_block` is executed when it evaluates to `True`. If `ctrl` is a `QBit` or `QArray[QBit]`, `stmt_block` is executed if all qubits are in the \`\|1>\` state. | *required* |
| `stmt_block` | `QCallable \| Callable[[], Statements]` | The quantum operations to execute when the condition holds. This can be a `QCallable` or a function returning a `Statements` block. | *required* |
| `else_block` | `QCallable \| Callable[[], Statements] \| None` | (Optional) Quantum operations to execute when the condition does not hold. | None |
### skip\_control
skip\_control(
stmt\_block: QCallable | Callable\[\[], Statements]
) -> None
Applies quantum statements unconditionally.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | --------------------------------------- | --------------------------------------------- | ---------- |
| `stmt_block` | `QCallable \| Callable[[], Statements]` | A callable that produces a quantum operation. | *required* |
### assign
assign(
expression: SymbolicExpr,
target\_var: QScalar
) -> None
Initialize a scalar quantum variable using an arithmetic expression.
If specified, the variable numeric properties (size, signedness, and fraction
digits) must match the expression properties.
Equivalent to ` |= `.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | -------------- | -------------------------------------------- | ---------- |
| `expression` | `SymbolicExpr` | A classical or quantum arithmetic expression | *required* |
| `target_var` | `QScalar` | An uninitialized scalar quantum variable | *required* |
### inplace\_add
inplace\_add(
expression: SymbolicExpr,
target\_var: QScalar
) -> None
Add an arithmetic expression to a quantum variable.
Equivalent to ` += `.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | -------------- | -------------------------------------------- | ---------- |
| `expression` | `SymbolicExpr` | A classical or quantum arithmetic expression | *required* |
| `target_var` | `QScalar` | A scalar quantum variable | *required* |
### inplace\_xor
inplace\_xor(
expression: SymbolicExpr,
target\_var: QScalar
) -> None
Bitwise-XOR a quantum variable with an arithmetic expression.
Equivalent to ` ^= `.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | -------------- | -------------------------------------------- | ---------- |
| `expression` | `SymbolicExpr` | A classical or quantum arithmetic expression | *required* |
| `target_var` | `QScalar` | A scalar quantum variable | *required* |
### within\_apply
within\_apply(
within: Callable\[\[], Statements],
apply: Callable\[\[], Statements]
) -> None
Given two operations $U$ and $V$, performs the composition of operations $U^\{-1\} V U$.
This operation is used to represent a sequence where the operation `U` is applied, followed by another operation `V`, and then `U^{-1}` is applied to uncompute. This pattern is common in reversible
computation and quantum subroutines.
**Parameters:**
| Name | Type | Description | Default |
| -------- | -------------------------- | ------------------------------------------------------------- | ---------- |
| `within` | `Callable[[], Statements]` | The unitary operation `U` to be computed and then uncomputed. | *required* |
| `apply` | `Callable[[], Statements]` | The operation `V` to be applied within the `U` block. | *required* |
### repeat
repeat(
count: SymbolicExpr | int,
iteration: Callable\[\[int], Statements]
) -> None
Executes a quantum loop a specified number of times, applying a quantum operation on each iteration.
This operation provides quantum control flow similar to a classical `for` loop, enabling repeated
application of quantum operations based on classical loop variables.
**Parameters:**
| Name | Type | Description | Default |
| ----------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------- |
| `count` | `SymbolicExpr \| int` | An integer or symbolic expression specifying the number of loop iterations. | *required* |
| `iteration` | `Callable[[int], Statements]` | A callable that takes a single integer index and returns the quantum operations to be performed at each iteration. | *required* |
### power
power(
exponent: SymbolicExpr | int,
stmt\_block: QCallable | Callable\[\[], Statements]
) -> None
Apply a quantum operation raised to a symbolic or integer power.
This function enables exponentiation of a quantum gate, where the exponent can be a
symbolic expression or an integer. It is typically used within a quantum program
to repeat or scale quantum operations in a parameterized way.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | --------------------------------------- | ------------------------------------------------------------------- | ---------- |
| `exponent` | `SymbolicExpr \| int` | The exponent value, either as an integer or a symbolic expression. | *required* |
| `stmt_block` | `QCallable \| Callable[[], Statements]` | A callable that produces the quantum operation to be exponentiated. | *required* |
### invert
invert(
stmt\_block: QCallable | Callable\[\[], Statements]
) -> Any
Apply the inverse of a quantum gate.
This function allows inversion of a quantum gate. It is typically used within a quantum program
to invert a sequence of operations.
**Parameters:**
| Name | Type | Description | Default |
| ------------ | --------------------------------------- | -------------------------------------------------------------- | ---------- |
| `stmt_block` | `QCallable \| Callable[[], Statements]` | A callable that produces the quantum operation to be inverted. | *required* |
### phase
phase(
phase\_expr: SymbolicExpr | float | None = None,
coefficient: SymbolicExpr | float = 1.0
) -> None
Applies a state-dependent or fixed phase shift (Z rotation) to the quantum state.
This operation multiplies each computational-basis state $|x_1,x_2,\ldots,x_n\rangle$
by a complex phase factor $\text\{coefficient\} * \text\{phase_expr\}(x_1,x_2,\ldots,x_n)$, where
`phase_expr` is a symbolic expression that contains quantum variables $x_1,x_2,\ldots,x_n$,
and `coefficient` is a scalar multiplier. If `phase_expr` contains no quantum variables,
all states are rotated by the same fixed angle.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `phase_expr` | `SymbolicExpr \| float \| None` | A symbolic expression that evaluates to an angle (in radians) as a function of the state of the quantum variables occurring in it, if any, or otherwise a fixed value. Execution parameters are only allowed if no quantum variables occur in the expression. | None |
| `coefficient` | `SymbolicExpr \| float` | (Optional, allowed only together with quantum expressions) A scalar multiplier for the evaluated expression, optionally containing execution parameters. Defaults to 1.0. | 1.0 |
### foreach
foreach(
values: SymbolicExpr | Sequence\[SymbolicExpr | int | float] | Sequence\[Sequence\[SymbolicExpr | int | float]],
iteration: Callable\[..., Statements]
) -> None
Loops through the elements of a classical list, applying a quantum operation on each iteration.
This operation provides quantum control flow similar to a classical `for ... in` loop, enabling repeated
application of quantum operations based on classical loop variables.
The iteration callable accepts one or more classical iteration variables.
If the iteration callable takes a single iteration variable, it will be assigned with the elements of 'values'.
If the iteration callable takes two or more variables, the elements of 'values' will be
unpacked into them.
**Parameters:**
| Name | Type | Description | Default |
| ----------- | ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `values` | `SymbolicExpr \| Sequence[SymbolicExpr \| int \| float] \| Sequence[Sequence[SymbolicExpr \| int \| float]]` | A classical list. | *required* |
| `iteration` | `Callable[..., Statements]` | A callable that takes one or more iteration variables and returns the quantum operations to be performed at each iteration. | *required* |
### assign\_amplitude\_poly\_sin
assign\_amplitude\_poly\_sin(
indicator: QBit,
expr: SymbolicExpr
) -> None
Encodes the value of the sine/cosine of a polynomial into the amplitude of the
respective computational basis state:
$$
\begin{aligned}
|x_1, x_2, \ldots, x_n\rangle|0\rangle &\rightarrow
\cos(\mathrm{poly}(x_1, x_2, \ldots, x_n))|x_1, x_2, \ldots, x_n\rangle|0\rangle \\
&\quad + \sin(\mathrm{poly}(x_1, x_2, \ldots, x_n))|x_1, x_2, \ldots, x_n\rangle|1\rangle
\end{aligned}
$$
**Parameters:**
| Name | Type | Description | Default |
| ----------- | -------------- | --------------------------------------------------------------------- | ---------- |
| `indicator` | `QBit` | The quantum indicator qubit | *required* |
| `expr` | `SymbolicExpr` | A polynomial expression over quantum scalars x\_1, x\_2, \ldots, x\_n | *required* |
### lookup\_table
lookup\_table(
func: RealFunction,
targets: QScalar | list\[QScalar]
) -> list\[float]
Reduces a classical function into a lookup table over all the possible values
of the quantum numbers.
**Parameters:**
| Name | Type | Description | Default |
| --------- | -------------------------- | --------------------------------------- | ---------- |
| `func` | `RealFunction` | A Python function | *required* |
| `targets` | `QScalar \| list[QScalar]` | One or more initialized quantum numbers | *required* |
**Returns:**
* **Type:** `list[float]`
* The function's lookup table
options:
show\_source: false
show\_if\_no\_docstring: false
# Path Operators
Source: https://docs.classiq.io/sdk-reference/qmod/path-operators
This is a list of the path operators available in `Qmod` for accessing
elements and sub-arrays of arrays inside quantum expressions.
Functions:
| Name | Description |
| ----------------------------- | ------------------------------------------------------------------- |
| `python_value_to_qmod_object` | Translate a Python classical value into a QMod object. |
| `subscript` | Return the element of `array` at position `index` in an expression. |
| `slice_` | Return the `array[start:stop]` sub-array in an expression. |
### python\_value\_to\_qmod\_object
python\_value\_to\_qmod\_object(
value: Any,
qmodule: ModelStateContainer
) -> Any
Translate a Python classical value into a QMod object.
numpy values are normalized to native Python, and dataclasses (which are
always classical structs in QMod) become `QmodStructInstance`s with their
declaration registered on `qmodule`. The result is a QMod object from
which both an expression string (via `qmod_val_to_expr_str`) and a
classical type (via `infer_classical_type`) can be derived.
**Parameters:**
| Name | Type | Description | Default |
| --------- | --------------------- | ----------- | ---------- |
| `value` | `Any` | | *required* |
| `qmodule` | `ModelStateContainer` | | *required* |
### subscript
subscript(
array: list | CArray | np.ndarray,
index: Any
) -> Any
Return the element of `array` at position `index` in an expression.
This is the expression-level form of the `array[index]` indexing operator.
**Parameters:**
| Name | Type | Description | Default |
| ------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `array` | `list \| CArray \| np.ndarray` | The array to index into. May be a Python list, a quantum-variable concatenation, a `CArray` parameter, or a numpy array. | *required* |
| `index` | `Any` | The position to read, as a classical expression. | *required* |
### slice\_
slice\_(
array: list | CArray | np.ndarray,
start: Any,
stop: Any
) -> Any
Return the `array[start:stop]` sub-array in an expression.
This is the expression-level form of the `array[start:stop]` slicing operator.
**Parameters:**
| Name | Type | Description | Default |
| ------------------------------ | ------------------------------ | ------------------------------------------------------------------------------------------------------------------- | ---------- |
| `array` | `list \| CArray \| np.ndarray` | The array to slice. May be a Python list, a quantum-variable concatenation, a `CArray` parameter, or a numpy array. | *required* |
| `start` | `Any` | The index of the first element of the slice, inclusive. | *required* |
| `stop` | `Any` | The index one past the last element of the slice, exclusive. | *required* |
| options: | | | |
| show\_source: false | | | |
| show\_if\_no\_docstring: false | | | |
# Symbolic Functions
Source: https://docs.classiq.io/sdk-reference/qmod/symbolic-functions
This is a list of the symbolic functions available in `Qmod` for applying on classical parameters in expressions context.
Functions:
| Name | Description |
| ----------- | ------------------------------------------------------------------- |
| `subscript` | Return the element of `array` at position `index` in an expression. |
### subscript
subscript(
array: list | CArray | np.ndarray,
index: Any
) -> Any
Return the element of `array` at position `index` in an expression.
This is the expression-level form of the `array[index]` indexing operator.
**Parameters:**
| Name | Type | Description | Default |
| ------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `array` | `list \| CArray \| np.ndarray` | The array to index into. May be a Python list, a quantum-variable concatenation, a `CArray` parameter, or a numpy array. | *required* |
| `index` | `Any` | The position to read, as a classical expression. | *required* |
# Synthesis
Source: https://docs.classiq.io/sdk-reference/synthesis
## TargetLanguage
Enum specifying the output format for `export`.
**Attributes:**
| Name | Type | Description |
| ----------- | ------------- | ------------------------------------------ |
| `QASM2` | `'qasm2'` | |
| `QASM3` | `'qasm3'` | |
| `QIR` | `'qir'` | |
| `CIRQ_JSON` | `'cirq_json'` | |
| `QSHARP` | `'qsharp'` | |
| `QASM2` | \`\` | OpenQASM 2.0 (default). |
| `QASM3` | \`\` | OpenQASM 3.0. |
| `QIR` | \`\` | Quantum Intermediate Representation (QIR). |
| `CIRQ_JSON` | \`\` | Cirq JSON format. |
| `QSHARP` | \`\` | Q# (QSharp). |
## TranspilationConfig
Configuration for transpiling a quantum program to a target basis gate set and qubit connectivity.
Pass a `TranspilationConfig` to the `transpilation_config` parameter of
`export` to apply hardware-aware transpilation during export.
**Attributes:**
| Name | Type | Description |
| --------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kind` | `Literal['transpilation']` | |
| `transpilation_level` | `TranspilationOption` | The transpilation strategy to apply. Defaults to `TranspilationOption.AUTO_OPTIMIZE`. |
| `basis_gates` | `list[str] \| None` | The target gate set to decompose the circuit into. If `None`, defaults to single-qubit gates + `cx`. When a `connectivity_map` is provided, defaults to single-qubit gates + `cx`. |
| `connectivity_map` | `ConnectivityMap \| None` | Qubit connectivity constraints of the target hardware - a list of allowed qubit-pair connections. If `None`, no routing is applied. |
| `is_symmetric_connectivity` | `bool` | Whether the connectivity map is symmetric (i.e., if `(i, j)` is allowed then `(j, i)` is also allowed). Defaults to `True`. |
## FaultTolerantTranspilationConfig
Configuration for fault-tolerant transpilation using Clifford+T gate approximation.
Pass a `FaultTolerantTranspilationConfig` to the `transpilation_config`
parameter of `export` to perform fault-tolerant transpilation in two
stages:
1. The circuit is first decomposed into the Clifford+T+RZ gate set
(`h`, `t`, `s`, `tdg`, `cx`, `rz`).
2. The remaining RZ gates are then approximated using the
[gridsynth](https://github.com/quantum-programming/pygridsynth) algorithm,
which finds an efficient Clifford+T sequence achieving the target rotation within
the specified error bound.
**Attributes:**
| Name | Type | Description |
| -------------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `kind` | `Literal['fault_tolerant']` | |
| `transpilation_level` | `TranspilationOption` | The transpilation strategy to apply. Defaults to `TranspilationOption.AUTO_OPTIMIZE`. |
| `clifford_t_approximation_error` | `float` | The maximum total approximation error for the whole circuit. This budget is divided equally across all RZ gates, so each gate is approximated with a per-gate error of `clifford_t_approximation_error / num_rz_gates`. Smaller values yield more accurate circuits at the cost of greater depth. |
| `keep_hierarchy` | `bool` | When `True`, each unique RZ-angle decomposition is emitted as a named custom gate (`rz_approx_0`, `rz_approx_1`, ...) in the target language, and every occurrence of that angle references the gate definition instead of inlining the Clifford+T sequence. When `False` (the default), the decomposition is inlined to produce a flat circuit. |
## QuantumProgram
**Methods:**
| Name | Description |
| ------------------------------------- | --------------------------------------------------------- |
| [to\_base\_program](#to_base_program) | |
| [to\_program](#to_program) | |
| [save\_results](#save_results) | Saves quantum program results as json into a file. |
| [get\_debug\_info](#get_debug_info) | |
| [raise\_warnings](#raise_warnings) | Raises all warnings that were collected during synthesis. |
**Attributes:**
| Name | Type | Description |
| ---------------------------- | ------------------------------- | ----------- |
| `hardware_data` | `SynthesisHardwareData` | |
| `data` | `GeneratedCircuitData` | |
| `model` | `ExecutionModel` | |
| `transpiled_circuit` | `TranspiledCircuitData \| None` | |
| `creation_time` | `str` | |
| `compressed_debug_info` | `bytes \| None` | |
| `program_id` | `str` | |
| `execution_primitives_input` | `PrimitivesInput \| None` | |
| `synthesis_warnings` | `list[str] \| None` | |
| `compressed_compiled_qmod` | `bytes \| None` | |
| `program_circuit` | `CircuitCodeInterface` | |
| `has_compiled_qmod` | `bool` | |
| `compiled_qmod` | `Model \| None` | |
| `qasm` | `Code \| None` | |
### to\_base\_program
to\_base\_program(
self:
) -> quantum\_code.QuantumBaseCode
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### to\_program
to\_program(
self: ,
instruction\_set: QuantumInstructionSet | None = None
) -> quantum\_code.QuantumCode
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | ------------------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `instruction_set` | `QuantumInstructionSet \| None` | | None |
### save\_results
save\_results(
self: ,
filename: str | Path | None = None
) -> None
Saves quantum program results as json into a file.
Parameters:
filename (Union\[str, Path]): Optional, path + filename of file.
If filename supplied add `.json` suffix.
Returns:
None
**Parameters:**
| Name | Type | Description | Default |
| ---------- | --------------------- | ----------- | ---------- |
| `self` | \`\` | | *required* |
| `filename` | `str \| Path \| None` | | None |
### get\_debug\_info
get\_debug\_info(
self:
) -> list\[FunctionDebugInfoInterface] | None
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
### raise\_warnings
raise\_warnings(
self:
) -> None
Raises all warnings that were collected during synthesis.
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
## Preferences
Preferences for synthesizing a quantum circuit.
**Methods:**
| Name | Description |
| ------------------------------------------------------------------------------------------------------------ | ----------- |
| [optimization\_timeout\_less\_than\_generation\_timeout](#optimization_timeout_less_than_generation_timeout) | |
| [make\_output\_format\_list](#make_output_format_list) | |
| [validate\_output\_format](#validate_output_format) | |
| [validate\_backend\_name](#validate_backend_name) | |
| [validate\_backend](#validate_backend) | |
**Attributes:**
| Name | Type | Description |
| ------------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `synthesize_all_separately` | `bool` | |
| `symbolic_loops` | `bool` | |
| `compatibility_mode` | `bool` | |
| `standalone` | `bool` | |
| `backend_preferences` | `BackendPreferences \| None` | |
| `machine_precision` | `int` | Specifies the precision used for quantum operations. Defaults to `DEFAULT_MACHINE_PRECISION`. |
| `backend_service_provider` | `str` | The provider company or cloud service for the requested backend. Defaults to `None`. |
| `backend_name` | `str` | The name of the requested backend or target. Defaults to `None`. |
| `custom_hardware_settings` | `CustomHardwareSettings` | Defines custom hardware settings for optimization. This field is ignored if backend preferences are specified. |
| `debug_mode` | `bool` | If `True`, debug information is added to the synthesized result, potentially slowing down the synthesis. Useful for executing interactive algorithms. Defaults to `True`. |
| `optimization_level` | `OptimizationLevel)` | The optimization level used during synthesis (0-3); |
| `output_format` | `List[QuantumFormat]` | Lists the output format(s) for the quantum circuit. Defaults to `[QuantumFormat.QASM]`. `QuantumFormat` Options: - QASM = "qasm" - QSHARP = "qsharp" - QIR = "qir" - IONQ = "ionq" - CIRQ\_JSON = "cirq\_json" - QASM\_CIRQ\_COMPATIBLE = "qasm\_cirq\_compatible" |
| `qasm3` | `Optional[bool]` | If `True`, outputs OpenQASM 3.0 in addition to 2.0, applicable to relevant attributes in `GeneratedCircuit`. Defaults to `None`. |
| `transpilation_option` | `TranspilationOption` | Sets the transpilation option to optimize the circuit. Defaults to `AUTO_OPTIMIZE`. See `TranspilationOption` |
| `solovay_kitaev_max_iterations` | `Optional[int]` | Specifies the maximum number of iterations for the Solovay-Kitaev algorithm, if used. Defaults to `None`. |
| `timeout_seconds` | `int` | Timeout setting for circuit synthesis in seconds. Defaults to `300`. |
| `optimization_timeout_seconds` | `Optional[int]` | Specifies the timeout for optimization in seconds, or `None` for no optimization timeout. This will still adhere to the overall synthesis timeout. Defaults to `None`. |
| `random_seed` | `int` | Random seed for circuit synthesis. |
### optimization\_timeout\_less\_than\_generation\_timeout
optimization\_timeout\_less\_than\_generation\_timeout(
cls: ,
optimization\_timeout\_seconds: pydantic.PositiveInt | None,
info: ValidationInfo
) -> pydantic.PositiveInt | None
**Parameters:**
| Name | Type | Description | Default |
| ------------------------------ | ------------------------------ | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `optimization_timeout_seconds` | `pydantic.PositiveInt \| None` | | *required* |
| `info` | `ValidationInfo` | | *required* |
### make\_output\_format\_list
make\_output\_format\_list(
cls: ,
output\_format: Any
) -> list
**Parameters:**
| Name | Type | Description | Default |
| --------------- | ----- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `output_format` | `Any` | | *required* |
### validate\_output\_format
validate\_output\_format(
cls: ,
output\_format: PydanticConstrainedQuantumFormatList,
info: ValidationInfo
) -> PydanticConstrainedQuantumFormatList
**Parameters:**
| Name | Type | Description | Default |
| --------------- | -------------------------------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `output_format` | `PydanticConstrainedQuantumFormatList` | | *required* |
| `info` | `ValidationInfo` | | *required* |
### validate\_backend\_name
validate\_backend\_name(
cls: ,
backend\_name: str | None
) -> str | None
**Parameters:**
| Name | Type | Description | Default |
| -------------- | ------------- | ----------- | ---------- |
| `cls` | \`\` | | *required* |
| `backend_name` | `str \| None` | | *required* |
### validate\_backend
validate\_backend(
self:
) -> Self
**Parameters:**
| Name | Type | Description | Default |
| ------ | ---- | ----------- | ---------- |
| `self` | \`\` | | *required* |
## Constraints
Constraints for the quantum circuit synthesis engine.
This class is used to specify constraints such as maximum width, depth,
gate count, and optimization parameters for the synthesis engine,
guiding the generation of quantum circuits that satisfy these constraints.
**Attributes:**
| Name | Type | Description |
| ------------------------ | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `max_width` | `int` | Maximum number of qubits allowed in the generated quantum circuit. Defaults to `None`. |
| `optimization_parameter` | `OptimizationParameterType` | Determines if and how the synthesis engine should optimize the solution. Defaults to `NO_OPTIMIZATION`. See `OptimizationParameterType` |
Functions:
| Name | Description |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `write_qmod` | Creates a native Qmod file from a serialized model and outputs the synthesis options (Preferences and Constraints) to a file. |
### write\_qmod
write\_qmod(
model: SerializedModel | QFunc | GenerativeQFunc,
name: str,
directory: Path | None = None,
decimal\_precision: int = DEFAULT\_DECIMAL\_PRECISION,
symbolic\_only: bool = True
) -> None
Creates a native Qmod file from a serialized model and outputs the synthesis options (Preferences and Constraints) to a file.
The native Qmod file may be uploaded to the Classiq IDE.
**Parameters:**
| Name | Type | Description | Default |
| ------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- |
| `model` | `SerializedModel \| QFunc \| GenerativeQFunc` | The entry point of the Qmod model - a qfunc named 'main' (or alternatively the output of 'create\_model'). | *required* |
| `name` | `str` | The name to save the file by. | *required* |
| `directory` | `Path \| None` | The directory to save the files in. If None, the current working directory is used. | None |
| `decimal_precision` | `int` | The number of decimal places to use for numbers, set to 4 by default. | DEFAULT\_DECIMAL\_PRECISION |
| `symbolic_only` | `bool` | If True keep function definitions un-expanded and symbolic (note that Qmod functions with parameters of Python types are not supported in this mode) | True |
**Returns:**
* **Type:** `None`
## Functions
### synthesize
synthesize(
model: SerializedModel | BaseQFunc,
auto\_show: bool = False,
constraints: Constraints | None = None,
preferences: Preferences | None = None
) -> QuantumProgram
Synthesize a model with the Classiq engine to receive a quantum program.
[More details](https://docs.classiq.io/latest/sdk-reference/synthesis/#classiq.synthesize)
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------- | ---------- |
| `model` | `SerializedModel \| BaseQFunc` | The entry point of the Qmod model - a qfunc named 'main' (or alternatively the output of 'create\_model'). | *required* |
| `auto_show` | `bool` | Whether to 'show' the synthesized model (False by default). | False |
| `constraints` | [Constraints](#constraints) \| None | Constraints for the synthesis of the model. See Constraints (Optional). | None |
| `preferences` | [Preferences](#preferences) \| None | Preferences for the synthesis of the model. See Preferences (Optional). | None |
**Returns:**
* **Type:** [QuantumProgram](#quantumprogram)
* Quantum program. (See: QuantumProgram)
### show
show(
quantum\_program: QuantumProgram,
display\_url: bool = True
) -> None
Displays the interactive representation of the quantum program in the Classiq IDE.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | --------------------------------- | ------------------------------------ | ---------- |
| `quantum_program` | [QuantumProgram](#quantumprogram) | The quantum program to be displayed. | *required* |
| `display_url` | `bool` | Whether to print the url | True |
### assign\_parameters
assign\_parameters(
quantum\_program: QuantumProgram,
parameters: ExecutionParams
) -> QuantumProgram
Assign parameters to a parametric quantum program.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | --------------------------------- | -------------------------------------------------------------------------------- | ---------- |
| `quantum_program` | [QuantumProgram](#quantumprogram) | The quantum program to be assigned. This is the result of the synthesize method. | *required* |
| `parameters` | `ExecutionParams` | The parameter assignments. | *required* |
**Returns:**
* **Type:** [QuantumProgram](#quantumprogram)
* The quantum program after assigning parameters.
### export
export(
quantum\_program: QuantumProgram,
target\_language: TargetLanguage | None = TargetLanguage.QASM2,
transpilation\_config: TranspilationConfig | FaultTolerantTranspilationConfig | Literal\[True] | None = None
) -> str
Export a quantum program as a circuit string in the requested target language.
Non-angle runtime parameters (e.g. integers that affect circuit structure such as
repeat counts) must be assigned first using `assign_parameters`.
**Parameters:**
| Name | Type | Description | Default |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------- |
| `quantum_program` | [QuantumProgram](#quantumprogram) | The quantum program to export. This is the result of `synthesize`. | *required* |
| `target_language` | [TargetLanguage](#targetlanguage) \| None | The target language to export to. Defaults to `TargetLanguage.QASM2`. | TargetLanguage.QASM2 |
| `transpilation_config` | [TranspilationConfig](#transpilationconfig) \| [FaultTolerantTranspilationConfig](#faulttoleranttranspilationconfig) \| Literal\[True] \| None | Transpilation configuration. Pass a `TranspilationConfig` or `FaultTolerantTranspilationConfig` to apply transpilation during export. Pass `True` to reuse the transpilation settings from the quantum program. Pass `None` to skip transpilation and export the circuit as synthesized. Defaults to `None`. | None |
**Returns:**
* **Type:** `str`
* The exported circuit code as a string.
### get\_circuit\_metrics
get\_circuit\_metrics(
quantum\_program: QuantumProgram
) -> CircuitMetrics
Get the logical resource estimation (width, depth and gate counts) of a quantum program.
For parametric programs, depth and gate counts may be returned as symbolic
string expressions (e.g. `"n + 1"`) instead of integers.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | --------------------------------- | ----------------------------------------------------------------------------- | ---------- |
| `quantum_program` | [QuantumProgram](#quantumprogram) | The quantum program to estimate. This is the result of the synthesize method. | *required* |
**Returns:**
* **Type:** `CircuitMetrics`
* The logical width, depth and gate counts of the quantum program.
### get\_transpiled\_circuit\_metrics
get\_transpiled\_circuit\_metrics(
quantum\_program: QuantumProgram
) -> CircuitMetrics
Get the hardware resource estimation (width, depth and gate counts) of a transpiled quantum program.
**Parameters:**
| Name | Type | Description | Default |
| ----------------- | --------------------------------- | ----------------------------------------------------------------------------- | ---------- |
| `quantum_program` | [QuantumProgram](#quantumprogram) | The quantum program to estimate. This should be a transpiled quantum program. | *required* |
**Returns:**
* **Type:** `CircuitMetrics`
* The width, depth and gate counts of the transpiled program.
### set\_preferences
set\_preferences(
serialized\_model: SerializedModel,
preferences: Preferences | None = None,
kwargs: Any =
) -> SerializedModel
Overrides the preferences of a (serialized) model and returns the updated model.
**Parameters:**
| Name | Type | Description | Default |
| ------------------ | ----------------------------------- | -------------------------------------------------------------------------------- | ---------- |
| `serialized_model` | `SerializedModel` | The model in serialized form. | *required* |
| `preferences` | [Preferences](#preferences) \| None | The new preferences to be set for the model. Can be passed as keyword arguments. | None |
| `kwargs` | `Any` | | |
**Returns:**
* **Type:** `SerializedModel`
* The updated model with the new preferences applied.
### set\_execution\_preferences
set\_execution\_preferences(
serialized\_model: SerializedModel,
execution\_preferences: ExecutionPreferences | None = None,
kwargs: Any =
) -> SerializedModel
Overrides the execution preferences of a (serialized) model and returns the updated model.
**Parameters:**
| Name | Type | Description | Default |
| ----------------------- | ------------------------------ | ------------------------------------------------------------------------------------------ | ---------- |
| `serialized_model` | `SerializedModel` | A serialization of the defined model. | *required* |
| `execution_preferences` | `ExecutionPreferences \| None` | The new execution preferences to be set for the model. Can be passed as keyword arguments. | None |
| `kwargs` | `Any` | | |
### set\_constraints
set\_constraints(
serialized\_model: SerializedModel,
constraints: Constraints | None = None,
kwargs: Any =
) -> SerializedModel
Overrides the constraints of a (serialized) model and returns the updated model.
**Parameters:**
| Name | Type | Description | Default |
| ------------------ | ----------------------------------- | -------------------------------------------------------------------------------- | ---------- |
| `serialized_model` | `SerializedModel` | The model in serialized form. | *required* |
| `constraints` | [Constraints](#constraints) \| None | The new constraints to be set for the model. Can be passed as keyword arguments. | None |
| `kwargs` | `Any` | | |
**Returns:**
* **Type:** `SerializedModel`
* The updated model with the new constraints applied.
### create\_model
create\_model(
entry\_point: QFunc | GenerativeQFunc,
constraints: Constraints | None = None,
execution\_preferences: ExecutionPreferences | None = None,
preferences: Preferences | None = None,
classical\_execution\_function: CFunc | None = None,
out\_file: str | None = None
) -> SerializedModel
Create a serialized model from a given Qmod entry function and additional parameters.
**Parameters:**
| Name | Type | Description | Default |
| ------------------------------ | ----------------------------------- | -------------------------------------------------------------------------------- | ---------- |
| `entry_point` | `QFunc \| GenerativeQFunc` | The entry point function for the model, which must be a QFunc named 'main'. | *required* |
| `constraints` | [Constraints](#constraints) \| None | Constraints for the synthesis of the model. See Constraints (Optional). | None |
| `execution_preferences` | `ExecutionPreferences \| None` | Preferences for the execution of the model. See ExecutionPreferences (Optional). | None |
| `preferences` | [Preferences](#preferences) \| None | Preferences for the synthesis of the model. See Preferences (Optional). | None |
| `classical_execution_function` | `CFunc \| None` | A function for the classical execution logic, which must be a CFunc (Optional). | None |
| `out_file` | `str \| None` | File path to write the Qmod model in native Qmod representation to (Optional). | None |
**Returns:**
* **Type:** `SerializedModel`
* A serialized model.
### qasm\_to\_qmod
qasm\_to\_qmod(
qasm: str,
qmod\_format: QmodFormat
) -> str
Decompiles QASM to Native/Python Qmod.
Returns Qmod code as a string. Native Qmod can be synthesized in the Classiq IDE,
while Python Qmod can be copy-pasted to a Python file (`.py`) and synthesized by
calling `synthesize(main)`.
**Parameters:**
| Name | Type | Description | Default |
| ------------- | ------------ | --------------------------- | ---------- |
| `qasm` | `str` | QASM 2 or QASM 3 code | *required* |
| `qmod_format` | `QmodFormat` | The requested output format | *required* |
**Returns:**
* **Type:** `str`
* The decompiled Qmod program
# Support
Source: https://docs.classiq.io/support/index
Welcome to the Classiq Support Center. This page is designed to help you quickly resolve common issues and get additional support if needed.
***
## Frequently Asked Questions (FAQs)
### Getting Started
Classiq is quantum-computing software that enables the design, optimization, analysis, and execution of quantum algorithms. Check out how to get started [here](../getting-started/).
* Start with [Registration and Installation](../getting-started/registration_installations/) to get access to the platform.
* [The Onboarding Tutorial](../getting-started/classiq_tutorial/) will help with your first steps in coding.
* When you feel confident, try some of our [real-world applications](../explore/applications/).
Yes! With Classiq, you can run quantum algorithms on the quantum computers you have access to. Check out our list of [quantum providers](../sdk-reference/providers/).
### Technical Questions
This error arises when your authentication credentials are denied. Try overriding your authentication credentials by executing `authenticate(overwrite=True)`.
If you’re experiencing failed attempts to reconnect to the Studio or long loading times, please try closing and reopening your web browser.
Try authenticating again using:
[comment]: DO_NOT_TEST
```python theme={null}
import classiq
classiq.authenticate()
```
To prevent such problems in the future, it is a good practice to begin code files in the Studio with `authenticate()`.
Some example notebooks (e.g., chemistry) require additional packages in the Studio. First, try:
```bash theme={null}
pip install "classiq[chemistry]"
```
If it still doesn’t work, reset the virtual environment by running:
```bash theme={null}
reset-user-env
```
If none of these options work, reach out to us on the [Community Slack](https://short.classiq.io/join-slack).
Use `quantum_program_from_qasm()`.
### Contributing to the Library
You can find contribution guidelines on [this page](https://github.com/Classiq/classiq-library/blob/main/CONTRIBUTING.md).
### Designing Quantum Models
In Classiq, you can define any observable as a linear combination of Pauli strings. To measure a set of observables from a quantum program, see [Execution Session](../user-guide/execution/ExecutionSession/) and the [Execution Tutorial](../explore/tutorials/basic_tutorials/the_classiq_tutorial/execution_tutorial_part2/).
You can synthesize the quantum circuit using `Constraints`. See [Quantum Program Constraints](../user-guide/synthesis/constraints/).
You can synthesize the quantum program using hardware-aware synthesis. See [Hardware-Aware Synthesis](../user-guide/synthesis/hardware-aware-synthesis/).
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](/qmod-reference/language-reference/statements/classical-control-flow/).
There are two ways to work around this: either bind the qubits you want to a QArray (see [bind](/qmod-reference/language-reference/statements/bind/)) or slice the QArrays (see [Path Operators](/qmod-reference/language-reference/expressions/#relational-operators)).
Use the `apply_to_all` function. See [Utility functions](/sdk-reference/qmod/functions/open_library/utility_functions).
You can use the `free()` function. For more information, see [Uncomputation](/qmod-reference/language-reference/uncomputation/).
Use `qprog.data.width` and `qprog.transpiled_circuit.depth`.
### Execution
Use `ExecutionPreferences` and set the backend appropriately. The [Execution Tutorial](../explore/tutorials/basic_tutorials/the_classiq_tutorial/execution_tutorial/) shows this step by step.
In Qmod, it is possible to use Pyomo to formulate the optimization problem. See [Problem Formulation](/user-guide/applications/optimization/problem-formulation/).
Use `ExecutionPreferences` and set the number of shots. See the [Execution Tutorial](../explore/tutorials/basic_tutorials/the_classiq_tutorial/execution_tutorial/).
After defining the quantum program, use `ExecutionSession.minimize()` or `ExecutionSession.estimate()` for VQAs. See [Execution Tutorial 2: Expectation Values and Parameterized Quantum Programs](../explore/tutorials/basic_tutorials/the_classiq_tutorial/execution_tutorial_part2/).
***
## Need More Help?
If your question is not answered here, please:
* Reach out in the `#support-and-questions` channel on [our community Slack](https://short.classiq.io/join-slack).
* For additional assistance, to report a bug, or to request a feature, submit a ticket via our [Support Center](https://classiq-community.freshdesk.com/support/home).
# Classiq Assistant: Getting Started
Source: https://docs.classiq.io/user-guide/ai/classiq-assistant
**Beta:** The Classiq Assistant is currently in beta.
## Overview
The Classiq Assistant is an AI assistant built into the [Classiq Platform](https://platform.classiq.io/). It lets you generate a quantum program from a natural language description or an image — without learning a new programming language. Describe the quantum problem you want to solve, and the assistant generates a qmod-native model, synthesizes it into a quantum program, and opens it in the Quantum Program page. You can also ask the assistant questions about quantum computing concepts and have it explain the programs it generates.
## Accessing the Assistant
The Classiq Assistant is available only to users with an active Classiq subscription.
The assistant is available in two places:
* **Home page:** Type your request directly in the input box at the center of the home page.
* **Quantum Program page:** Open the assistant panel from any circuit page to keep refining your program or start a new request. The panel travels with you, so you can move between generating, refining, and asking questions without losing your place.
### Conversation context
The assistant keeps the context of your current work so its answers stay relevant:
* **Referenced circuit:** When you have a circuit open, it is attached to the conversation as a chip, so the assistant knows which program you are asking about. Remove the chip to drop that context, or start a new conversation to ask about something else.
* **Generated model:** Each program the assistant generates is available on the Model page as a new model. This model belongs to the current conversation context only — it is not saved permanently and disappears once you move on, so save it if you want to keep it.
* **Starting a new conversation:** Use the **New chat** button in the assistant panel to start fresh, or return to the home page and enter a new request there.
## Generating a Quantum Program
1. Type a description of the quantum program you want to build, or click the **+** icon to upload an image of a circuit or diagram.
2. Click **Send**. The assistant generates a qmod-native model and synthesizes it into a quantum program.
3. The Quantum Program page opens automatically with the result. From here you can keep chatting with the assistant — ask it to explain the circuit, predict the expected results, or refine the model.
Synthesis occasionally fails on the first attempt, and an error message may appear. When this happens, the assistant automatically retries, so the quantum program can take a little longer to load. Wait for it to finish before starting over.
4. To run the program, click **Execute**. This takes you to the Execution page, where you select a backend and run the program.
The assistant runs one request at a time and cannot process multiple chats concurrently. Wait for the current generation to finish before sending a new request or starting another chat.
**Example prompts:**
* "Implement a Grover search to find all pairs where x times y equals 6, with x and y as integers in \[0, 7]" — generates a Grover search circuit over a 6-qubit search space.
* "Teleport a qubit using quantum entanglement and classical corrections" — generates a quantum teleportation circuit.
* "Show me a small Monte Carlo example" — generates a compact amplitude-estimation-style circuit.
You can also ask conceptual and follow-up questions instead of only requesting circuits:
* "Explain what entanglement is"
* "Explain what this circuit does"
* "What results should I expect from this program?"
## What You Can Do
* Generate quantum programs from natural language descriptions or from circuit images and diagrams
* Refine the output through follow-up messages in the same conversation
* Ask the assistant to explain what it generated or walk you through the logic
* Ask the assistant to predict what the results of the program should be
* Ask questions about quantum computing concepts and get explanations in context
## Prompts Best Practice
| Do | Don't |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Use clear, direct descriptions of what you want to build | Over-specify technical parameters in your initial prompt — it over-constrains the assistant and makes generation more likely to fail |
| Start simple and add detail through follow-up messages | Pack multiple complex requirements into a single prompt — the assistant handles focused requests more reliably |
| Rephrase or simplify if the first attempt isn't right | Assume a failed prompt means the use case is not supported — try a simpler version first |
| Ask the assistant to explain the output or predict results | Expect the assistant to configure backends, run circuits, or interpret execution output — those are handled on the Execution page |
## Limitations
* **Not all prompts will succeed.** Problems requiring parameterized circuits, complex Hamiltonian simulation, or niche library functions may produce incomplete or incorrect output.
* **Generated programs are not guaranteed to be correct.** Always review the output before executing.
* **Execution is a separate step.** The assistant generates and synthesizes quantum programs but does not run them. Click **Execute** and run the program on the Execution page.
* **Model configuration is done in the Classiq Platform.** Setting optimization parameters, backend constraints, and preferences is handled directly in the platform, not through the assistant.
# AI with Classiq
Source: https://docs.classiq.io/user-guide/ai/index
Classiq supports AI-powered quantum development across IDEs and environments. AI agents can model, synthesize, execute, and analyze quantum programs — all in natural language.
## Features
Enterprise plugin for Claude Code and Cursor. Includes skills for every development phase — modeling, synthesis, execution, analysis — plus live reference lookup.
Built-in AI assistant in the Classiq Studio. No additional setup — configure your LLM API key and start coding.
## Local Development Setup
For AI-assisted development outside the Studio, set up the Classiq Library locally so agents have access to examples and documentation.
### Prerequisites
* Python >=3.9, \<3.13
* Git
* An IDE with an AI assistant (VS Code + Claude Code, Cursor, etc.)
### Setup
1. **Clone the library**
```bash theme={null}
git clone https://github.com/Classiq/classiq-library.git
cd classiq-library
```
2. **Install the SDK**
```bash theme={null}
pip install classiq
```
3. **Open in your IDE** and point it at the `classiq-library` directory.
For the full AI-in-IDE experience — skills, live doc lookup, and Classiq conventions baked in — see the [Quantum Engineer Plugin](/user-guide/ai/quantum-engineer-plugin).
# Quantum Engineer Plugin
Source: https://docs.classiq.io/user-guide/ai/quantum-engineer-plugin
## Overview
This is an enterprise-grade feature available exclusively to Classiq's enterprise customers.
The **Quantum Engineer** plugin brings Classiq expertise directly into your AI-powered IDE. It teaches coding agents like Claude Code, Cursor, and Codex how to model, synthesize, execute, analyze, and post-process quantum programs with Classiq.
Build, run, and analyze quantum programs in natural language — describe what you want and the agent handles every step, from writing the model to reading back results.
Programs are expressed in **Qmod**, and draw on the open library of reusable quantum functions. Synthesis delegates to Classiq's backend engine, which compiles high-level models into hardware-optimized circuits automatically.
The plugin includes skills for each phase of quantum development:
* **Modeling** — write quantum algorithms in Python using Classiq.
* **Synthesis** — compile a model into a quantum program with `synthesize()`, constraints, and hardware targets.
* **Execution** — run circuits: `sample`, `observe`, `calculate_state_vector`, and variational loops.
* **Post-processing** — interpret results: histograms, energy curves, and most-probable states.
* **Analyzer** — inspect synthesized programs for gate counts, depth, and hardware fit.
* **Qiskit migration** — translate existing Qiskit code into Classiq models.
A built-in reference layer keeps the agent's knowledge current as it works.
## Installation
The marketplace is access-controlled: reach out to Classiq to get onboarded, and you'll receive a personal GitHub invitation to the repository. Accept it first — the steps below assume you already have access.
Add the marketplace once per machine, using the repository from your invitation:
```
/plugin marketplace add /
```
Then install the plugin:
```
/plugin install classiq-quantum-engineer@classiq
```
Restart Claude Code after the first install so the bundled MCP server comes up. You'll be prompted to approve the `classiq-mcp` server on first use.
**Keeping it up to date:**
```
/plugin marketplace update classiq # pull the latest catalog
/plugin update classiq-quantum-engineer@classiq # update the plugin
/plugin list # see what you have installed
```
* Open Cursor Settings (Cmd+Shift+J) → Plugins.
* Choose Add/import plugin.
* Paste the GitHub URL from your Classiq invitation.
* Select classiq-quantum-engineer and install it.
* Confirm the plugin status shows Imported.
* Reload the window — open the Command Palette and run Developer: Reload Window.
* Enable the MCP server — go to Settings → Features → Model Context Protocol and turn on Classiq Docs.
* Confirm skills loaded — go to Settings → Rules → Agent Decides. You should see skills such as classiq, classiq-modeling, classiq-synthesis, and classiq-execution.
**Keeping it up to date:**
To pick up the latest plugin version, remove and re-import the plugin from the GitHub URL in your invitation, then reload the window.
After updating, verify that:
* Settings → Plugins shows classiq-quantum-engineer with status Imported.
* Settings → Features → Model Context Protocol shows Classiq Docs enabled.
* Settings → Rules → Agent Decides includes the Classiq skills.
The plugin requires the `classiq` Python package in your project's environment. If you don't have it yet, ask the agent to install it — see the **Install Classiq** example in the [Examples](#examples) section below, or [Use Python and Classiq](/getting-started/sdk_installation) for manual SDK setup.
## Usage
Once installed, just describe what you want in natural language — no special syntax required. The agent picks the right skill for each phase of the work:
| You ask for | Skill that responds |
| ------------------------------------------------------------------------------------------------- | ------------------- |
| Writing, editing, or debugging a quantum algorithm in Python (`@qfunc`, `QBit`, `QNum`, `QArray`) | Modeling |
| Writing or debugging native Qmod (`.qmod` files) | Native Qmod |
| Compiling a model — `synthesize()`, constraints, hardware targets | Synthesis |
| Running a circuit — `sample`, `observe`, `calculate_state_vector`, variational loops | Execution |
| Interpreting results — histograms, energy curves, most-probable states | Post-processing |
| Inspecting a synthesized program — gate counts, depth, hardware fit | Analyzer |
| Translating Qiskit code into Classiq models | Qiskit migration |
For requests that span multiple phases — "model this and run it" — the agent organizes the full pipeline end-to-end.
## Examples
**Prompt:**
```
Create a Bell state, synthesize it, run it on the simulator, and show the measurement counts.
```
**Generated code:**
```python theme={null}
from classiq import *
@qfunc
def main(res: Output[QArray[QBit, 2]]):
allocate(2, res)
H(res[0])
CX(res[0], res[1])
qprog = synthesize(main)
result = sample(qprog)
print(result)
```
**Output:**
```
res counts probability bitstring
0 [1, 1] 1036 0.505859 11
1 [0, 0] 1012 0.494141 00
```
**Prompt:**
```
Write a quantum program that puts a 1-qubit integer in superposition, assigns 2 to a second integer, computes their sum, and runs it.
```
**Generated code:**
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QNum], y: Output[QNum], z: Output[QNum]):
allocate(1, x)
H(x)
y |= 2
z |= x + y
qprog = synthesize(main)
res = sample(qprog)
print(res)
```
**Output:**
| x | y | z | counts | probability |
| - | - | - | ------ | ----------- |
| 0 | 2 | 2 | 1049 | 0.512 |
| 1 | 2 | 3 | 999 | 0.488 |
**Prompt:**
```
Use Grover's algorithm to find all pairs (x, y) of 2-bit integers where x + y < 4 and (x * y) % 4 == 2. Run it and show which states get amplified.
```
**Generated code:**
```python theme={null}
from classiq import *
VAR_SIZE = 2
class GroverVars(QStruct):
x: QNum[VAR_SIZE]
y: QNum[VAR_SIZE]
@qperm
def my_predicate(vars: Const[GroverVars], res: QBit) -> None:
res ^= (vars.x + vars.y < 4) & ((vars.x * vars.y) % 4 == 2)
@qfunc
def main(vars: Output[GroverVars]):
allocate(vars)
hadamard_transform(vars)
power(
2,
lambda: grover_operator(
lambda vars: phase_oracle(predicate=my_predicate, target=vars),
hadamard_transform,
vars,
),
)
qprog = synthesize(main)
result = sample(qprog)
result
```
**Output:**
| vars.x | vars.y | probability |
| ------ | ------ | ----------- |
| 1 | 2 | 0.481 |
| 2 | 1 | 0.463 |
| 2 | 2 | 0.006 |
**Prompt:**
```
Install classiq and set it up for me.
```
The agent invokes the **Setup** skill, which walks through the full installation in your environment: it runs an environment diagnostic, installs the `classiq` package via pip, opens a browser window for authentication, and confirms everything is ready with a final status summary.
## Per-project best practices
A small amount of one-time setup per project pays off quickly: a project memory file gives the agent persistent context about your environment, sanity checks let you verify everything is wired up before you start, and a troubleshooting reference saves time when something unexpected happens.
### Memory file
Both IDEs support a project-level file that the agent reads at the start of every conversation. Use it to record your Python environment and any project-specific conventions — so the agent never has to ask and never guesses wrong.
Create `CLAUDE.md` at the root of your project and fill in the bracketed fields:
```markdown theme={null}
# [Project Name]
## Environment
- Python: [path/to/venv/bin/python]
- Classiq SDK: installed in the environment above
## Backend
Default: Classiq cloud simulator.
[Optional: list hardware targets or execution preferences for this project.]
## Project overview
[One or two sentences describing the quantum algorithms or application this project implements.]
## Conventions
[Any project-specific patterns — naming, file layout, preferred synthesis constraints, etc.]
```
Claude Code picks up `CLAUDE.md` automatically — no additional configuration required.
Create `.cursor/rules/classiq.mdc` at the root of your project. This file gives Cursor persistent Classiq-specific context for the project.
```markdown theme={null}
---
description: Classiq project context
alwaysApply: true
---
# [Project Name]
## Environment
- Python: [path/to/venv/bin/python]
- Classiq SDK: installed in the environment above
## Backend
Default: Classiq cloud simulator.
[Optional: list hardware targets or execution preferences for this project.]
## Project overview
[One or two sentences describing the quantum algorithms or application this project implements.]
## Conventions
[Any project-specific patterns — naming, file layout, preferred synthesis constraints, etc.]
```
The `alwaysApply: true` frontmatter tells Cursor to load this rule for every conversation in the project.
To verify the rule is active, open Settings → Rules and confirm the project rule appears. You can also ask the agent: "What Classiq project context do you see?" The response should reflect the environment and conventions from .cursor/rules/classiq.mdc.
### Sanity checks
Run these checks after installation to confirm the plugin is wired up correctly.
**Verify the plugin is installed:**
```
/plugin list
```
Look for `classiq-quantum-engineer@classiq` in the output. If it is missing, reinstall:
```
/plugin install classiq-quantum-engineer@classiq
```
**Confirm skills are active:**
Run `/status` or ask the agent directly: `"Which Classiq skills do you have loaded?"` The response should name skills such as `classiq-modeling`, `classiq-synthesis`, and `classiq-execution`.
**Confirm the MCP server is running:**
Ask the agent:
```
"Can you look up the Classiq docs for synthesize?"
```
A successful lookup means the `classiq-mcp` server is up. A timeout or "no tools available" reply means the server did not start — see [Troubleshooting](#troubleshooting) below.
**Verify the plugin is installed:**
* Open Cursor Settings → Plugins.
The classiq-quantum-engineer plugin should appear with status Imported. If it is missing, re-import it from the GitHub URL in your invitation.
If import fails, confirm that you accepted the GitHub invitation and are signed into Cursor with an account that can access the repository.
**Confirm skills are active:**
* Go to Settings → Rules → Agent Decides.
You should see skills such as classiq, classiq-modeling, classiq-synthesis, and classiq-execution.
You can also ask the agent:
```
Which Classiq skills do you have loaded?
```
A successful response should name the Classiq skills available to the agent.
**Confirm the MCP server is running:**
* Go to Settings → Features → Model Context Protocol and confirm Classiq Docs is enabled.
Then ask the agent:
```
Can you look up the Classiq docs for synthesize?
```
A successful lookup confirms the MCP server is running. A timeout, missing-tool message, or generic answer without a docs lookup usually means the MCP server did not start correctly.
**Confirm the SDK is available in the project environment:**
Ask the agent:
```
Check whether the classiq Python package is installed in this project environment.
```
If the package is missing, you can ask the agent to install it.
### Troubleshooting
#### MCP server does not start
The `classiq-mcp` server starts automatically on launch, but requires a one-time approval prompt on first use.
1. Run `/plugin list` — confirm `classiq-quantum-engineer@classiq` appears.
2. Go to **Settings → MCP Servers**. If `classiq-mcp` shows as disabled, enable it.
3. Restart Claude Code. The server starts fresh on each launch.
If the server still does not appear after a restart, try reinstalling:
```
/plugin update classiq-quantum-engineer@classiq
```
1. Go to **Settings → Features → Model Context Protocol**.
2. Confirm **Classiq Docs** is toggled on.
3. Reload the window — Command Palette → *Developer: Reload Window*.
If the server still does not appear, remove and re-import the plugin from the GitHub URL in your invitation, then reload.
#### Skills do not load
Skills appear in **Settings → Rules**. If they are absent after installation:
* Quit and relaunch Claude Code.
* Confirm the plugin installed cleanly: `/plugin list` should show `classiq-quantum-engineer@classiq` without an error flag.
Skills appear in **Settings → Rules → Agent Decides**. If they are absent after installation:
* Reload the window — Command Palette → *Developer: Reload Window*.
* Confirm the plugin status in **Settings → Plugins** shows **Imported** without an error.
#### Plugin is installed but not updating
If `synthesize` behavior or skill instructions seem outdated:
```
/plugin marketplace update classiq # pull the latest catalog
/plugin update classiq-quantum-engineer@classiq
```
Restart Claude Code after updating.
If skill instructions seem outdated, remove and re-import the plugin from the GitHub URL in your invitation to pick up the latest version, then reload the window.
## See also
[Use AI with Classiq](/user-guide/ai/index)
# AI Agent in Studio
Source: https://docs.classiq.io/user-guide/ai/studio-agent
The Classiq Studio has a built-in AI agent that assists with quantum algorithm development — no local installation or plugin required.
## Getting Started
1. Open [Classiq Studio](https://platform.classiq.io/studio/).
2. Set your API key for your preferred LLM provider under **Settings**.
3. Describe what you want to build. The agent writes, runs, and explains Classiq code directly in the editor.
## What the Agent Can Do
* Write and edit quantum algorithms using the Classiq Python SDK
* Synthesize models and inspect the resulting circuit
* Execute programs on the simulator and read back results
* Explain code and suggest improvements
## Supported LLM Providers
The Studio agent works with any of the LLM providers configured in your account settings. Set your API key once and the agent will use it for all sessions.
# Data Analysis and Graphs
Source: https://docs.classiq.io/user-guide/analysis/data-analysis-and-graphs
The input to the analyzer tool is a quantum program in OpenQasm or Cirq format.
The analysis data and graphs can be accessed using Classiq's Python
SDK.
After synthesizing a quantum program, initialize the `Analyzer` class using the quantum program
returned from the synthesis process.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
qfunc,
Analyzer,
Output,
QBit,
allocate,
synthesize,
QuantumProgram,
allocate,
)
@qfunc
def main(res: Output[QBit]) -> None:
allocate(1, res)
qprog = synthesize(main)
analyzer = Analyzer(circuit=qprog)
```
## Graphs and Data
Quantum programs are more than just a beautiful image; they are meant to run on
real quantum hardware to solve and supply interesting and new answers.
The hardware analysis supplies two main insights.
### Available Devices
To perform hardware-aware analysis, you may want to know which devices are
available using the
platform. You can get a list of the devices that are both available and
suit the quantum program (i.e., have a sufficient number of qubits).
[comment]: DO_NOT_TEST
```python theme={null}
analyzer.get_available_devices()
```
This command returns the available devices of all the providers, in dictionary
format, where providers are
the keys, and lists of available devices are the values:
[comment]: DO_NOT_TEST
```python theme={null}
{
"IBM Quantum": [
"almaden",
"boeblingen",
"brooklyn",
"cairo",
"cambridge",
"guadalupe",
"hanoi",
"johannesburg",
"kolkata",
"manhattan",
"melbourne",
"montreal",
"mumbai",
"paris",
"poughkeepsie",
"rochester",
"rueschlikon",
"singapore",
"sydney",
"tokyo",
"toronto",
"washington",
],
"Azure Quantum": ["ionq", "quantinuum"],
}
```
You can also request the devices of a specific provider:
[comment]: DO_NOT_TEST
```python theme={null}
analyzer.get_available_devices(["IBM Quantum"])
```
### Hardware-Circuit Connection
The Hardware-Circuit Connection graph is a representation of a quantum program as
implemented on a specific (physical) quantum device. You
can interactively select hardware from hardware providers such as IBM Quantum,
Amazon Braket, and Microsoft Azure.
The analyzer compiles the quantum program for the selected hardware, allowing easy
inspection of which physical qubits will be used for execution on the device
and, in turn, modifying the quantum program if needed.
This information is important if you want to execute the quantum program on real quantum
hardware, so you can make modifications to the quantum program.
This graph is accessible from the SDK only if you install the `analyzer_sdk`
extension with the
`pip install classiq[analyzer_sdk]` command and use Jupyter as your coding
platform. Once the extension is installed, run this command:
[comment]: DO_NOT_TEST
```python theme={null}
# Run inside jupyter
analyzer.plot_hardware_connectivity()
```
Alternatively, you can open the graph directly with a specific provider and
device:
[comment]: DO_NOT_TEST
```python theme={null}
analyzer.plot_hardware_connectivity(provider="IBM Quantum", device="washington")
```
### Hardware Comparison Table
The hardware comparison table compares the transpiled quantum program on different
hardware backends. The table includes information about the quantum program's depth, number of
multi-qubit gates, and total number of gates.
[comment]: DO_NOT_TEST
```python theme={null}
providers = ["IBM Quantum", "Azure Quantum", "Amazon Braket"]
analyzer = Analyzer(circuit=qprog)
analyzer.get_hardware_comparison_table(providers=providers)
analyzer.plot_hardware_comparison_table()
```
The `providers` variable is a list of providers ("IBM Quantum", "Azure Quantum",
and "Amazon Braket"), where the table includes only the backends of providers that
appear in the list, and the default is to use all the providers.
The table has the following form:
Sort the table according to the table properties using the dropdown button on
the upper left of the table. \`\`\`
Using the default device/providers option (all) or comparing a large
number of devices might take a long time, especially when analyzing large quantum programs.
It is advised to compare a small number of devices when you are interested in analyzing large quantum programs.
The difference between the transpilation in the synthesis process and the comparison table data originates from the fact that the comparison table data is aware of the specific hardware and considers information such as the basis gates and connectivity.
\[1] M. Van den Nest, W. Dur, G. Vidal, H. J. Briegel,
"Classical simulation versus universality in measurement-based quantum
computation",
Phys. Rev. A 75, 012337 (2007).
\[2] S. Oum,
"Rank-width: Algorithmic and structural results", Lect. Notes Comput. Sci. 3787,
49 (2005).
\[3] S. Oum,
"Rank-width is less than or equal to branch-width", J. Graph Theory, 57 (3),
239-244 (2008).
\[4] Hans L. Bodlaender, "Discovering treewidth".
Institute of
Information and Computing Sciences, Utrecht University, Technical Report.
UU-CS-2005-018.
[http://www.cs.uu.nl](http://www.cs.uu.nl)
# Analysis
Source: https://docs.classiq.io/user-guide/analysis/index
The Classiq product requires information from the synthesis so it can automatically generate a quantum program. This fact is even more important for large quantum programs, where simulation may not even be an option.
The Classiq analyzer comprises a web application plus analysis data and graphs that provide information about a quantum program, primarily so there is no need to simulate it.
These sections describe how to use the web application, data, and graphs, and give a comprehensive walkthrough of the components:
* [Quantum Program Visualization Tool](/user-guide/analysis/visualization-of-quantum-programs)
* [Data Analysis and Graphs](/user-guide/analysis/data-analysis-and-graphs)
# Visualization of Quantum Programs
Source: https://docs.classiq.io/user-guide/analysis/visualization-of-quantum-programs
The Classiq analyzer application helps you visualize and analyze quantum programs.
The input to the application is a quantum program synthesized by the Classiq [synthesis engine](/user-guide/synthesis/getting-started), or an OpenQASM quantum program.
## Accessing the Quantum Program Visualization Tool
There are 3 ways to view a quantum program using the visualization tool:
* Through the Classiq Python SDK
* Direct access via the Classiq IDE
* Direct access via the Studio
### Classiq Python SDK
* Synthesize your model using `synthesize()` to obtain a quantum program, and pass it as a parameter to the function `show()`. Here is an example with a trivial model:
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import qfunc, Output, QBit, synthesize, show, allocate
@qfunc
def main(res: Output[QBit]) -> None:
allocate(1, res)
qprog = synthesize(main)
show(qprog)
```
### Direct Access
* Synthesizing a quantum program using the IDE [https://platform.classiq.io/synthesis](https://platform.classiq.io/synthesis) automatically redirects you to the visualization tool.
* Upload (drag and drop) a file that contains a quantum program synthesized using the Classiq engine (either synthesized and downloaded from the IDE or obtained from the python SDK using `qprog.save_result("file-name")`) into [https://platform.classiq.io/circuit/](https://platform.classiq.io/circuit/).
### Visualization in the Studio
* Follow the same steps as in Classiq Python SDK. The visualization tool can be directly rendered in the notebook:
## Using Visualization Tool
The Quantum Program visualization bridges the high-level algorithm descriptions (as it is captured in Qmod) with their quantum implementations (as synthesized by the Classiq engine). The tool offers two key innovations: **functional block hierarchies** and **quantum data flow** representations.
The **quantum data flow** view lets users track quantum variables, including higher-level types like numbers, arrays, and structs, along with their qubit allocations. This aids in understanding data flow and memory allocation within quantum algorithms.
**Functional block hierarchies** enable navigation between different levels of abstraction, from high-level functional blocks to individual quantum gates, offering a more thorough exploration of the algorithm's structure.
The QP visualization tool provides an interactive way to analyze quantum programs by focusing on the quantum data-flow between functional blocks. Here’s a breakdown of its key features and functionality:
#### Purpose
* Analyze the implementation of the quantum model (Qmod) as synthesized by the Classiq engine.
* Verify the data flow within the quantum program, enabling debugging and deeper analysis
#### Hierarchical Structure
* Allows users to traverse different levels of the quantum model implementation, from high-level Qmod functions down to atomic functions.
Double clicking a function block opens and collapses the internal hierarchies:
#### Color Coding
The visualization uses colors to help distinguish different block categories:
* **Yellow**: Represents Qmod function blocks (either written by the user or taken from the Classiq library).
* **Turquoise**: Represents Qmod statement blocks (such as: control, invert, power, within-apply, assignment).
* **Grey**: Represents built-in functional blocks (generated by the Classiq engine during synthesis).
#### Data Flow Analysis
Data flow between functional blocks is presented in terms of the Qmod variables:
* **Purple lines** represent the flow of quantum variables throughout the program.
* The **purple dot** marks where a variable is initialized.
* When variables split or merge (via slicing or the bind operation), the purple lines update to show the changes.
* The variable’s name and size are also displayed along the purple lines, making it easier to track their initialization, usage and transformations.
This structured approach allows for a clear understanding of the program’s execution, providing users with a tool to validate the accuracy and efficiency of their quantum programs.
#### Task Bar
On the top right is the analyzer task bar:
The taskbar contain several groups of buttons, arranged from left to right:
1. **Search tool**: Allows you to search through the building blocks of a quantum program to quickly locate specific elements.
2. **Hierarchical View**: Provides options to expand all functions and gates, revealing the most detailed level of analysis for the quantum gates used in your algorithm. You can also collapse everything to return to the original, simplified view displayed when the quantum program was first loaded, where a single bar represents the entire algorithm.
3. **Navigation and Zoom**: This group includes map controls for navigating across different parts of the quantum program chart, enabling you to focus on gates and functions that are currently outside the visible area. It also includes zoom controls to:
* Reset the chart to its default scale (currently 90%),
* Zoom out,
* Adjust the zoom level manually,
* Or zoom in for a closer view.
### Variables View
Within the Quantum Program page you can also toggle the **Variables View** option:
Variables View provides a simplified, high-level visualization of how quantum data flows through a program. Instead of showing individual qubits, it highlights logical quantum variables and their transformations, making it easier to understand complex algorithms and trace data flow across different parts of the program. As quantum algorithms increase in scale and sophistication,
traditional visualization techniques become cluttered and difficult to interpret, making it difficult to see the bigger picture. Classiq Qmod language addresses this by allowing users to design algorithms using high-level elements organized into modular functional blocks. Building on this, Variables View focuses on the logical units, making complex workflows far easier to follow.
In the example below, the Variables View shows a simplified implementation of the discrete logarithm algorithm [\[1\]](#nielsen). Notice how purple lines trace the flow of logical variables, with dots indicating initialization points. As the algorithm progresses, variables are split and merged, providing an intuitive understanding of the quantum algorithm.
### Sharing your Quantum Program Visualization
You can easily share your Quantum Program visualization with anyone, even those who haven’t signed up for the platform. It’s simple:
* Copy the Quantum Program URL directly from your browser and share it.
* Alternatively, click the "Share" button on the Quantum Program page, choose a social media to share in or copy the generated link, and share it with anyone.
\[1]: [Michael A. Nielsen and Isaac L. Chuang. 2011. Quantum Computation and Quantum Information: 10th Anniversary Edition, Cambridge University Press, New York, NY, USA.
](https://www.amazon.com/Quantum-Computation-Information-Michael-Nielsen/dp/1107002176)
# Combinatorial Optimization
Source: https://docs.classiq.io/user-guide/applications/optimization/index
The Classiq combinatorial optimization platform is a quantum software engine for optimization problems that you define.
The engine tackles your formulated real-world optimization challenges and generates customized quantum programs.
You choose whether to run the programs on a quantum backend or a classical simulation, and receive the optimized solution.
To gain further insights regarding the synthesis process, you can examine the synthesized program with the
Classiq [analyzer](/user-guide/analysis/index) module.
## Formulating Problems
You describe new optimization problems using the Python SDK package.
The problem is formulated using [PYOMO](http://www.pyomo.org/), a Python-based, open-source optimization
modeling language. The language supports a wide variety of problem types, such as integer linear
programming, quadratic programming, graph theory problems, and SAT problems.
Read in-depth reviews of the language’s capabilities in
\[ \[1] ]\(#pyomo documentation) and \[ \[2] ]\(#pyomo cookbook) \[ \[3] ]\(#pyomo intro).
The basics of problem modelling in PYOMO and
a complete example are in the [problem formulation](/user-guide/applications/optimization/problem-formulation) section.
The platform supports an extensive set of modeling configurations for your use ([supported modeling](/user-guide/applications/optimization/supported-modeling)).
## Solving Optimization Problems
The core Classiq capabilities are generation of a designated quantum solution,
and execution of the generated algorithm on a quantum backend.
The platform relies on the QAOA penalty algorithm to solve optimization problems.
## References
\[1] Pyomo Documentation 6.0.1, [https://pyomo.readthedocs.io/en/stable/](https://pyomo.readthedocs.io/en/stable/).
\[2] Prof. Jeffrey Kantor’s Pyomo Cookbook
[https://jckantor.github.io/ND-Pyomo-Cookbook/](https://jckantor.github.io/ND-Pyomo-Cookbook/).
\[3] J. D. Siirola, Introduction to Pyomo: The optimization foundation for IDAES,
[https://www.osti.gov/servlets/purl/1524963](https://www.osti.gov/servlets/purl/1524963) (2018).
# Problem Formulation
Source: https://docs.classiq.io/user-guide/applications/optimization/problem-formulation
[comment]: SINGLE_FILE
In the PYOMO language, like any other algebraic modeling languages (AMLs),
the optimization problem consists of three main components:
decision variables, constraints, and an objective function.
This section briefly introduces these components and explains the modalities supported by the platform.
### Model
As an object-oriented language, PYOMO organizes the optimization problem into a single object of type
ConcreteModel. It contains all the other components as Python attributes.
The model is declared in the following way:
```python theme={null}
import pyomo.environ as pyo
model = pyo.ConcreteModel()
```
### Decision Variables
The variables component is the “unknown part” of the model.
The solver aims to assign values that constitute the best possible solution.
Following is a description of the possible arguments for variable declaration in PYOMO.
In many optimization problems, the variables are indexed.
The index set is provided as the first argument to the PYOMO var object.
```python theme={null}
index_set = [0, 1, 2, 3]
```
[comment]: DO_NOT_TEST
```python theme={null}
model.x = pyo.Var(index_set)
```
Next, state the variable domain.
It may be a binary variable, an integer variable,
a real variable, etc. The platform currently supports the binary and integer domains:
• Binary:
[comment]: DO_NOT_TEST
```python theme={null}
model.x = pyo.Var(index_set, domain=pyo.Binary)
```
• Integer:
[comment]: DO_NOT_TEST
```python theme={null}
model.x = pyo.Var(index_set, domain=pyo.NonNegativeIntegers, bounds=(0, 7))
```
If you know the variable value, fix it now to save qubits:
[comment]: DO_NOT_TEST
```python theme={null}
model.x[0].fix(3)
```
See [PYOMO variables](https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Variables.html).
### Constraints
Constraints enrich the descriptive power of optimization problems.
Different scenarios, rules, regulations, and variable relations may be phrased as conditions on decision variables that must be satisfied.
In PYOMO, specify the constraints using equality or inequality expressions. There are several ways to integrate them inside the existing PYOMO model:
* Using the `expr` argument:
```python theme={null}
model = pyo.ConcreteModel()
model.x = pyo.Var(index_set, domain=pyo.Binary)
model.amount_constraint = pyo.Constraint(expr=sum(model.x[i] for i in model.x) == 3)
```
* Using a rule argument and a separate Python function:
```python theme={null}
def amount_rule(model):
return sum(model.x[i] for i in model.x) == 3
model.amount = pyo.Constraint(rule=amount_rule)
```
* Using a Python constraint decorator:
```python theme={null}
@model.Constraint()
def amount_rule(model):
return sum(model.x[i] for i in model.x) == 3
```
Index the constraints similarly to the variables.
```python theme={null}
def size_rule(model, i):
return model.x[i] <= model.x[i + 1]
model.size_rule = pyo.Constraint(index_set[:-1], rule=size_rule)
```
See [PYOMO constraints](https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Constraints.html).
### Objective Function
The objective function encodes the essence of the best solution.
It is a function of the decision variables, which return a real value that the optimization solver tries to minimize or maximize.
It is incorporated into the PYOMO model similarly to the constraints: with an `expr` argument, with a rule argument, or with a decorator.
An additional declaration argument is `sense`, which is set to `minimize` or `maximize`.
```python theme={null}
model.cost = pyo.Objective(expr=sum(model.x[i] for i in index_set), sense=pyo.maximize)
```
See [PYOMO objective functions](https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Objectives.html).
### Importing
You can import all PYOMO components from the `pyomo.environ` sub-package:
[comment]: DO_NOT_TEST
```python theme={null}
import pyomo.environ as pyo
Model = pyo.ConcreteModel()
model.variable = pyo.Var()
model.constraint = pyo.Constraint()
```
### Complete Example
```python theme={null}
from typing import Union, List
import numpy as np
import pyomo.core as pyo
import networkx as nx
def mis(graph: Union[nx.Graph, List[List[int]]]) -> pyo.ConcreteModel:
if isinstance(graph, list):
graph = nx.convert_matrix.from_numpy_matrix(np.array(graph))
model = pyo.ConcreteModel()
model.Nodes = pyo.Set(initialize=list(graph.nodes))
model.Arcs = pyo.Set(initialize=list(graph.edges))
model.x = pyo.Var(model.Nodes, domain=pyo.Binary)
@model.Constraint(model.Arcs)
def independent_rule(model, node1, node2):
return model.x[node1] + model.x[node2] <= 1
model.cost = pyo.Objective(expr=sum(list(model.x.values())), sense=pyo.maximize)
return model
```
This example combines all components under a single Python function.
It accepts user-defined inputs, and returns a complete PYOMO model with the assigned parameters.
The function is saved in a file of the same name.
The `graph` may be either an instance of the
`networkx.Graph` class or the adjacency matrix in the form of `List[List[int]]`.
# Supported Modeling
Source: https://docs.classiq.io/user-guide/applications/optimization/supported-modeling
Classiq supports a limited set of modeling configurations. The following tables describe them.
## Variables
| Index Set |
List or set |
| Domain |
Binary(equivalent to \[0, 1] list) |
Bounded NonNegativeIntegers (equivalent to \[0:bound] list) |
## Constraints
| Constraint type |
Equality constraints |
Inequality constraints |
| Constraint amount |
Multiple, non overlapping |
Multiple |
| Expression type |
Linear sum |
| Variable coefficient |
Positive integer |
| Constant term |
Positive integer |
## Objective Functions
| Objective amount |
Single |
| Variable type |
Binary |
Integer |
| Expression type |
Polynomial |
| Variable coefficient |
Integer or float |
# Quantum Machine Learning
Source: https://docs.classiq.io/user-guide/applications/qml/index
Quantum machine learning (QML) is a field that seeks to combine the principles of
quantum mechanics and machine learning to develop new algorithms and techniques that
can process and analyze data more efficiently.
The platform has a few QML built-in algorithms:
* With [Quantum Neural Network (QNN)](/user-guide/applications/qml/qnn/index), you can combine classical and quantum neural network layers.
# A Full Example
Source: https://docs.classiq.io/user-guide/applications/qml/qnn/a-full-example
[comment]: SINGLE_FILE_SLOW
## Intro
In this example, we will show a simple example of parametric quantum program (PQC).
We will take 1 input from the user, and consider 1 weight, while utilizing 1 qubit in the PQC.
During this example, the goal of the learning process is to assess the right angle for a `Rx` gate for performing a "NOT" operation (spoiler, the correct answer is $\pi$).
## General flow
In [section 1](#step-1-create-our-torchnnmodule) we will see the code required for defining a quantum layer.
This will include:
* section 1.1: defining the quantum model and synthesizing it to a quantum program
* section 1.2: defining the post-process callable
* section 1.3: defining a `torch.nn.Module` network
In section 2 we will choose our dataset, loss function, and optimizer.
Section 3 will demostrate how to handle the learning process, and section 4 will test our network's performance.
If you're not familiar with PyTorch, it is highly recommended that you'll check out the following pages from their documentation:
* [Creating Models](https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html#creating-models)
* [Build the Neural Network](https://pytorch.org/tutorials/beginner/basics/buildmodel_tutorial.html)
* [Optimizing the Model Parameters](https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html#optimizing-the-model-parameters)
* [Tensors](https://pytorch.org/tutorials/beginner/basics/tensorqs_tutorial.html)
* [Datasets & DataLoaders](https://pytorch.org/tutorials/beginner/basics/data_tutorial.html)
## Step 1 - Create our `torch.nn.Module`
### Step 1.1 - Create our parametric quantum program
Our quantum model will be defined and synthesized as follows:
```python theme={null}
from classiq import (
synthesize,
qfunc,
QArray,
QBit,
RX,
Output,
CReal,
allocate,
)
@qfunc
def encoding(theta: CReal, q: QArray[QBit]) -> None:
RX(theta=theta, target=q[0])
@qfunc
def mixing(theta: CReal, q: QArray[QBit]) -> None:
RX(theta=theta, target=q[0])
@qfunc
def main(input_0: CReal, weight_0: CReal, res: Output[QArray[QBit]]) -> None:
allocate(1, res)
encoding(theta=input_0, q=res)
mixing(theta=weight_0, q=res)
quantum_program = synthesize(main)
```
The input (`input_0`), logically indicating the state `|0>` or `|1>`, is transformed into an angle, either `0` or `pi`.
### Step 1.2 - Create the Post-processing
Post-process the result of executing the quantum program to obtain a single number (`float`) and a single dimension `Tensor`.
```python theme={null}
import torch
from classiq.applications.qnn.types import SavedResult
# Post-process the result, returning a dict:
# Note: this function assumes that we only care about
# differentiating a single state (|0>)
# from all the rest of the states.
# In case of a different differentiation, this function should change.
def post_process(result: SavedResult) -> torch.Tensor:
"""
Take in a `SavedResult` with `ExecutionDetails` value type, and return the
probability of measuring |0> which equals the amount of `|0>` measurements
divided by the total amount of measurements.
"""
counts: dict = result.value.counts
# The probability of measuring |0>
p_zero: float = counts.get("0", 0.0) / sum(counts.values())
return torch.tensor(p_zero)
```
### Step 1.3 - Create a network
Now we're going to define a network, just like any other PyTorch network, only that this time, we will have only 1 layer, and it will be a quantum layer.
```python theme={null}
import torch
from classiq.applications.qnn import QLayer
class Net(torch.nn.Module):
def __init__(self, *args, **kwargs) -> None:
super().__init__()
self.qlayer = QLayer(
quantum_program, # the quantum program, the result of `synthesize()`
post_process, # a callable that takes a single `SavedResult`, returning a `torch.Tensor`
*args,
**kwargs
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
x = self.qlayer(x)
return x
model = Net()
```
### Step 2 - Choose a dataset, loss function, and optimizer
We will use the `DATALOADER_NOT` dataset, defined [here](/user-guide/applications/qml/qnn/datasets), as well as [`L1Loss`](https://pytorch.org/docs/stable/generated/torch.nn.L1Loss.html) and [SGD](https://pytorch.org/docs/stable/generated/torch.optim.SGD.html)
```python theme={null}
from classiq.applications.qnn.datasets import DATALOADER_NOT
import torch.nn as nn
import torch.optim as optim
_LEARNING_RATE = 1.0
# choosing our data
data_loader = DATALOADER_NOT
# choosing our loss function
loss_func = nn.L1Loss()
# choosing our optimizer
optimizer = optim.SGD(model.parameters(), lr=_LEARNING_RATE)
```
### Step 3 - Train
For the training process, we will use a loop similar to [the one recommended by PyTorch](https://pytorch.org/tutorials/beginner/blitz/neural_networks_tutorial.html#update-the-weights)
```python theme={null}
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
def train(
model: nn.Module,
data_loader: DataLoader,
loss_func: nn.modules.loss._Loss,
optimizer: optim.Optimizer,
epoch: int = 20,
) -> None:
for index in range(epoch):
print(index, model.qlayer.weight)
for data, label in data_loader:
optimizer.zero_grad()
output = model(data)
loss = loss_func(output, label)
loss.backward()
optimizer.step()
train(model, data_loader, loss_func, optimizer)
```
### Step 4 - Test
Lastly, we will test our network accuracy, using [the following answer](https://stackoverflow.com/questions/52176178/pytorch-model-accuracy-test#answer-64838681)
```python theme={null}
def check_accuracy(model: nn.Module, data_loader: DataLoader, atol=1e-4) -> float:
num_correct = 0
total = 0
model.eval()
with torch.no_grad():
for data, labels in data_loader:
# Let the model predict
predictions = model(data)
# Get a tensor of booleans, indicating if each label is close to the real label
is_prediction_correct = predictions.isclose(labels, atol=atol)
# Count the amount of `True` predictions
num_correct += is_prediction_correct.sum().item()
# Count the total evaluations
# the first dimension of `labels` is `batch_size`
total += labels.size(0)
accuracy = float(num_correct) / float(total)
print(f"Test Accuracy of the model: {accuracy*100:.2f}")
return accuracy
check_accuracy(model, data_loader)
```
The results show that the accuracy is $1$, meaning a 100% success rate at performing the required transformation (i.e. the network learned to perform a X-gate).
We may further test it by printing the value of `model.qlayer.weight`, which is a tensor of shape `(1,1)`, which should, after training, be close to $\pi$.
Finally, we safely teardown the `QLayer` instance.
```python theme={null}
model.qlayer.teardown()
```
## Summary
In this example, we wrote a fully working Quantum Neural Network from scratch, trained it, and saw its success at learning the requested transformation.
In section 1 we defined our parametric quantum program, as well as our post-processing function. Together, these two are sent as arguments to [the `QLayer` object](/user-guide/applications/qml/qnn/qlayer).
In section 2 we set some hyperparameters, and in section 3 we trained our model.
Section 4 helped us verify that our network is working as intended.
# Datasets
Source: https://docs.classiq.io/user-guide/applications/qml/qnn/datasets
Pytorch provides two classes: `DataSet` and `DataLoader`.
If you're not familiar with them, please review them [here](https://pytorch.org/tutorials/beginner/basics/data_tutorial.html)
Classiq provides two simple datasets, which are mainly used in our examples.
They can be found in `classiq/applications/qnn/data_sets.py`.
## DatasetNot
This dataset is used for training a network to learn the "NOT" operation.
More specifically, learning the angle to a parametrized `Rx` gate (spoiler - the correct answer is `pi`).
This dataset has 2 items:
0. the data is `|00...0>`, the label is `|11...1>`.
1. the data is `|11...1>`, the label is `|00...0>`.
The amount of qubits is specified in the constructor (`def DatasetNot.__init__(self, n: int, ...)`).
### Transformers
Additionally, we provide 2 `Transform`s for this class. (Their PyTorch documentation can be found [here](https://pytorch.org/tutorials/beginner/basics/transforms_tutorial.html)), which serve our example.
Note that these transformers are automatically used.
Feel free to keep reading about them, though this is not mandatory.
In our example, we wish to
A) encode the input state onto the quantum circle
B) execute the PQC
C) measure the PQC
D) post-process the measurement results
Our transformers help steps `A` and `D`.
First, `state_to_weights` transforms the state, into parameters for the encoding `Rx` gates. This is used for step `A`
In other words, the state `|0>` is transformed into the angle `0`, and the state `|1>` is transformed into the angle `pi`.
Second, `state_to_label` transforms the expected output state into a single float number.
More specifically, since we generate this data, we set the expected output state to be a pure state (in the `Z` basis).
Additionally, we define the post-processing to return the probability of measuring `|00...0>` in the output state.
Thus, for the output `|00...0>`, the post processed output is `1`, corresponding to `100%`, and for the output `|11...1>`, the post processed output is `0`.
### DatasetXor
This dataset is used for training a network to learn the "XOR" operation.
This may take, similar to `DatasetNot`, the amount of qubits in the constructor.
The "XOR" operation on more than 2 inputs is defined as "a quantum program that outputs a 1 when the number of 1s at its inputs is odd, and a 0 when the number of incoming 1s is even" (credit: [wikipedia](https://en.wikipedia.org/wiki/XOR_gate#More_than_two_inputs))
## Usage examples
### Using pre-configured `DataLoader`s
```python theme={null}
from classiq.applications.qnn.datasets import DATALOADER_NOT
for data, label in DATALOADER_NOT:
print(f"Training the following data: {data}")
print(f"with the following labels: {label}")
```
### Using pre-configures `Dataset`s
```python theme={null}
from classiq.applications.qnn.datasets import DATASET_NOT
from torch.utils.data import DataLoader
DATALOADER_NOT = DataLoader(DATASET_NOT, batch_size=2, shuffle=True)
for data, label in DATALOADER_NOT:
print(f"Training the following data: {data}")
print(f"with the following labels: {label}")
```
### Using the `DatasetNot` class
#### without using our pre-defined transformers
```python theme={null}
from classiq.applications.qnn.datasets import DatasetNot
from torch.utils.data import DataLoader
NUM_QUBITS = 1
DATASET_NOT = DatasetNot(NUM_QUBITS)
DATALOADER_NOT = DataLoader(DATASET_NOT, batch_size=2, shuffle=True)
for data, label in DATALOADER_NOT:
print(f"Training the following data: {data}")
print(f"with the following labels: {label}")
```
#### with our pre-defined transformers
```python theme={null}
from classiq.applications.qnn.datasets import (
DatasetNot,
state_to_weights,
state_to_label,
)
from torch.utils.data import DataLoader
from torchvision.transforms import Lambda
NUM_QUBITS = 1
DATASET_NOT = DatasetNot(
1, transform=Lambda(state_to_weights), target_transform=Lambda(state_to_label)
)
DATALOADER_NOT = DataLoader(DATASET_NOT, batch_size=2, shuffle=True)
for data, label in DATALOADER_NOT:
print(f"Training the following data: {data}")
print(f"with the following labels: {label}")
```
# Quantum Neural Networks
Source: https://docs.classiq.io/user-guide/applications/qml/qnn/index
* [QNN](/user-guide/applications/qml/qnn/qnn)
* [A full example](/user-guide/applications/qml/qnn/a-full-example)
* [The `QLayer` object](/user-guide/applications/qml/qnn/qlayer)
* [Simplified quantum layer (`QLayerV2`)](/user-guide/applications/qml/qnn/qlayerv2)
* [Available datasets](/user-guide/applications/qml/qnn/datasets)
# Quantum Layer
Source: https://docs.classiq.io/user-guide/applications/qml/qnn/qlayer
The Classiq engine exports the `QLayer` object, which inherits from `torch.nn.Module` (like most objects in the `torch.nn` namespace), and it acts like one.
The `QLayer` object is defined like this:
[comment]: DO_NOT_TEST
```python theme={null}
class QLayer(nn.Module):
def __init__(
self,
quantum_program: QuantumProgram,
execute: ExecuteFunction,
post_process: PostProcessFunction,
) -> None: ...
```
Or,
[comment]: DO_NOT_TEST
```python theme={null}
class QLayer(nn.Module):
def __init__(
self,
quantum_program: QuantumProgram,
post_process: PostProcessFunction,
) -> None: ...
```
The first parameter, `quantum_program`, is the result of [synthesizing a quantum model](/user-guide/synthesis/index).
Note that the parameters are assumed to follow the API stated in [qnn](/user-guide/applications/qml/qnn/qnn).
The second parameter is a callable which is responsible for executing the quantum program, usually with [`execute_qnn`](#execution).
It takes a `QuantumProgram` and `MultipleArguments` (a list of arguments sets to assign to the quantum program parameters) as inputs, and returns a `ResultsCollection`.
Note that this argument can be left out, as demonstrated in the second code block.
If it is not supplied, the layer will create an `ExecutionSession` and sample the quantum program automagically.
In order to properly close the `ExecutionSession`, if it was created, call the `teardown` method of `QLayer`.
The third parameter is a callable which is responsible for post-processing each execution result. It takes a `SavedResult` as input, process it and returns a `Tensor`.
## Saving and loading models (checkpointing)
For hybrid QNN models that include a `QLayer`, prefer saving and loading only the weights:
[comment]: DO_NOT_TEST
```python theme={null}
# Save
torch.save(model.state_dict(), path)
# Load (recreate model structure first, then load weights)
model = Net(...) # same structure as when saved
model.load_state_dict(torch.load(path))
```
Whole-model pickle (`torch.save(model, path)`) is supported, but `post_process` and the execution path cannot be pickled when they are local functions, lambdas, or closures (e.g. defined inside `__init__`). In that case they are omitted from the checkpoint. After loading:
1. Call `layer.register_post_process(your_post_process)` on each `QLayer` that had a non-serializable `post_process` before calling `forward()`.
2. If you know `post_process` is not serializable, you can pass `serializable_post_process=False` when constructing the `QLayer` to skip pickling it and avoid a warning on save.
## Example callables
An example of such callables:
[comment]: DO_NOT_TEST
```python theme={null}
import torch
from classiq.applications.qnn.types import (
MultipleArguments,
SavedResult,
ResultsCollection,
)
from classiq import execute_qnn
from classiq.synthesis import QuantumProgram
def execute(
quantum_program: QuantumProgram, arguments: MultipleArguments
) -> ResultsCollection:
return execute_qnn(quantum_program, arguments)
def post_process(result: SavedResult) -> torch.Tensor:
# for example, post-processing can take some value out of `result.value.counts`, which is a `dict`
value = _post_process_result(result)
return torch.tensor(value)
```
## Execution
To facilitate the execution of your quantum layer, we supply the utility function `execute_qnn`.
It enables you to easily execute a batch of input arguments, and instruct whether you want the sample results or the estimation results according to a specific observable.
The inputs for `execute_qnn` are:
* `quantum_program` of type `QuantumProgram`
* `arguments` of type `MultipleArguments`
* (optionally) `observable` of type `PauliOperator`.
The function returns a `ResultsCollection`, which is a list of `SavedResult` objects (see [Execution Results](/user-guide/execution/index#results) for more information).
The type of each `SavedResult` depends on the `observable` input:
* If no `observable` were given, the type would be `ExecutionDetails`.
* Otherwise, the type would be `EstimationResult`.
If only one observable was given, `execute_qnn` will estimate the execution of all batched arguments with this observable.
If more than one observable was given, their number should match the number of batched arguments, and each execution with a set of arguments will be estimated with the matching observable.
### Examples
[comment]: DO_NOT_TEST
```python theme={null}
# Execute and return the sample results
def execute(
quantum_program: QuantumProgram, arguments: MultipleArguments
) -> ResultsCollection:
return execute_qnn(quantum_program, arguments)
# Execute and return the estimation results according to a specific observable
def execute(
quantum_program: QuantumProgram, arguments: MultipleArguments
) -> ResultsCollection:
return execute_qnn(
quantum_program,
arguments,
observable=PauliOperator(
pauli_list=[("II", 1 / 2), ("IZ", -1 / 2), ("ZI", -1 / 2)]
),
)
```
## Behind the Scenes
Behind the scenes, the `QLayer` handles the following actions:
* Processing of the PQC
* Initializing and tracking of parameters
* Passing the inputs and weights (as multi-dimensional tensors) to the execution function
* Passing the results from the execution function to the post-processing function
* Gradient calculation on the PQC
# Simplified Quantum Layer (QLayerV2)
Source: https://docs.classiq.io/user-guide/applications/qml/qnn/qlayerv2
`QLayerV2` is a new, simplified quantum layer for hybrid QNNs. It is constructed from a synthesized quantum program and an optional set of observables, and produces a trainable `torch.nn.Module` whose outputs are the expectation values of those observables.
The new interface is designed to be more intuitive than the classic `QLayer` and - just as importantly - it is **much faster** behind the scenes, so training loops run considerably quicker.
Use it when your quantum layer's output is naturally a set of expectation values. For layers that need sampling, counts, or custom classical post-processing, keep using the classic [`QLayer`](/user-guide/applications/qml/qnn/qlayer) (see [Choosing between the two layers](#choosing-between-the-two-layers)).
`QLayerV2` currently runs only inside **Classiq Studio** and is limited to circuits of **up to 26 qubits**. Constructing it in any other environment, or with a larger circuit, raises an error. Extending its scale and reach is planned.
**`QLayerV2` is a temporary name.** It ships alongside the existing `QLayer` (also available under the alias `QLayerV1`), which is unchanged for now so existing code keeps working. `QLayerV2` is the interface we are moving toward: once it covers the full feature set, the classic interface will go through the standard deprecation process and `QLayerV2` will become the single, canonical `QLayer`. That deprecation has **not** started yet.
## Interface
`QLayerV2` is imported from the same package as `QLayer`:
[comment]: DO_NOT_TEST
```python theme={null}
from classiq.applications.qnn import QLayerV2
QLayerV2(
qprog, # a synthesized QuantumProgram
observables=None, # optional; defaults to one per qubit
)
```
* `qprog` - a synthesized [`QuantumProgram`](/user-guide/synthesis/index). Its parameters are classified by name: the `input`/`i_` prefixes mark **inputs** (the encoded classical data) and the `weight`/`w_` prefixes mark **trainable weights** (for example `input_0`, `i_x`, `weight_0`, `w_theta`). See [Parameters: Inputs Versus Weights](/user-guide/applications/qml/qnn/qnn#parameters-inputs-versus-weights).
* `observables` - one output feature per Pauli observable. Defaults to one `` per qubit, so the default output width equals the circuit width. Accepts a single `SparsePauliOp` or a sequence of them. An observable narrower than the program is padded with identities to the program's width.
The layer trains like any other `torch` module. Its `forward` is rank-preserving: an input of shape `(batch, in_features)` produces `(batch, out_features)`, and an unbatched input of shape `(in_features,)` produces `(out_features,)`.
## Examples
### Minimal example
With only a `qprog`, the layer measures one `` per qubit using the default observables:
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import *
from classiq.applications.qnn import QLayerV2
@qfunc
def main(input_0: CReal, weight_0: CReal, res: Output[QArray]) -> None:
allocate(2, res)
RY(input_0, res[0]) # driven by the input feature
RY(weight_0, res[1]) # trainable weight
CX(res[0], res[1])
qprog = synthesize(main)
# Defaults: one per qubit.
layer = QLayerV2(qprog)
```
The result is a trainable `torch` layer that plugs into an ordinary network:
[comment]: DO_NOT_TEST
```python theme={null}
import torch.nn as nn
class MyNet(nn.Module):
def __init__(self) -> None:
super().__init__()
self.pre = nn.Linear(4, 1)
self.quantum = QLayerV2(qprog)
def forward(self, x):
x = self.pre(x)
return self.quantum(x)
```
### Custom observables
Pass one `SparsePauliOp` per output feature to control what the layer measures. Here the single output feature is ``:
[comment]: DO_NOT_TEST
```python theme={null}
from classiq.qmod.builtins.enums import Pauli
# : Pauli-Z on qubit 0. Narrower observables are padded to the circuit width.
z0 = Pauli.Z(0)
layer = QLayerV2(qprog, observables=[z0])
```
## Choosing between the two layers
The classic [`QLayer`](/user-guide/applications/qml/qnn/qlayer) is also available under the alias `QLayerV1`, so the two interfaces can be named side by side during the transition.
| | [`QLayerV1`](/user-guide/applications/qml/qnn/qlayer) (alias of the classic `QLayer`) | `QLayerV2` (new) |
| ----------- | ------------------------------------------------------------------------------------- | ----------------------------------------- |
| Output | Any tensor from a custom `post_process` | Expectation values of Pauli observables |
| You provide | `execute` and `post_process` callables | Just `qprog` (and optional `observables`) |
| Measurement | Sampling derived values | Expectation values only |
| Speed | Standard | Much faster |
| Runs | Anywhere execution is available | Classiq Studio only, up to 26 qubits |
`QLayerV1` remains available today for sampling, counts, and custom post-processing. `QLayerV2` is the interface we are building toward and will eventually become the single, canonical `QLayer`. Reach for `QLayerV2` when you want the simplest, fastest path to an expectation-value layer.
# Quantum Neural Networks (QNN)
Source: https://docs.classiq.io/user-guide/applications/qml/qnn/qnn
The Classiq QNN package is integrated with PyTorch so you can define `torch` networks with the addition of quantum layers (which are quantum programs).
This topic assumes basic knowledge of classical neural networks.
A neural network can be described as a list of layers, where each layer takes in a vector and outputs a different vector.
The vectors are treated as one-dimensional, and other dimensions are identical up to `reshape`.
The input and output of each layer is a vector of classical data; for convenience, called a `list` of `float`s.
This implies that any quantum layer, assuming the structure of the data transfer between the layers does not change, must take in classical data and return classical data.
This is done by renaming the incoming data as `parameters` for the quantum program, measuring the quantum layer, and applying classical post-processing calculations.
## Examples
One example for post-processing outputs of a quantum layer is returning a single number between `0` and `1`, indicating the confidence of a single choice.
This is common in cases of binary classification where a single qubit is measured and the output of the quantum layer is `the amount of |0> measured` divided by `the total number of measurements`.
Another example for post-processing is returning the probability (or amplitude) of each result.
If the measurement result is this:
```
{
"00": 10,
"01": 20,
"10": 30,
"11": 40,
}
```
Then the output of the quantum layer can be this:
```
[0.1 , 0.2 , 0.3 , 0.4]
```
which is normalized by the number of measurements, and the result is an ordered list of the probabilities of each result.
See a [full working example](/user-guide/applications/qml/qnn/a-full-example).
## Parameters: Inputs Versus Weights
A complete quantum layer takes two types of parameters: "inputs" and "weights".
The "input" parameters handle the encoding of the data (the classical `list` of `float`s), whereas the "weight" parameters undergo gradient descent in the usual NN way.
The "input" parameters are usually handled by the first sub-layer, while the "weight" parameters are usually handled by the rest of the sub-layers.
The Classiq engine distinguishes between the two types of parameters by their initial name:
* `input_something` or `i_something` for inputs
* `weight_something` or `w_something` for weights
## Classiq Engine API
### `QLayer`
Classiq exports the `QLayer` object, which inherits from `torch.nn.Module` (like most objects in the `torch.nn` namespace), and it acts accordingly.
For example:
[comment]: DO_NOT_TEST
```python theme={null}
class MyNet(nn.Module):
def __init__(self) -> None:
self.linear_layer = nn.Linear(...)
self.quantum_layer = classiq.QLayer(...)
def forward(self, x: Tensor):
x = self.linear_layer(x)
x = self.quantum_layer(x)
return x
```
The full declaration of the `QLayer` object, with explanations about the parameter it gets, are described [here](/user-guide/applications/qml/qnn/qlayer).
There are two quantum-layer interfaces, both fully supported. Use the classic `QLayer` (this page) when your layer needs sampling, counts, or custom classical post-processing. Use the simpler [`QLayerV2`](/user-guide/applications/qml/qnn/qlayerv2) when the layer's outputs are expectation values of Pauli observables.
### Datasets
Classiq provides two [datasets](/user-guide/applications/qml/qnn/datasets) for play-testing examples.
1. "NOT" takes in a single-qubit state (either |0> or |1>) and returns an $n$-qubit state of all-ones or all-zeros, respectively. For example, for $n=2$: `0 -> |11>`, `1 -> |00>`.
2. "XOR" takes in an $n$-qubit state and returns a single classical bit, equal to the bitwise-xor of all the bits from the input state. For example, `101 -> 0`, `10101 -> 1`, `10 -> 1`, `11 -> 0`.
### Gradients
The Classiq engine automatically calculates the gradient of a PQC.
And there are many more calculations on their way.
Stay tuned!
# Client Credentials (M2M) Authentication
Source: https://docs.classiq.io/user-guide/authentication/m2m-authentication
The Classiq SDK supports a non-interactive, machine-to-machine (M2M) authentication flow built on the OAuth 2.0 client credentials grant. Use this flow when a backend service needs to call the Classiq platform without a person signing in.
## Obtaining credentials
M2M clients are provisioned by Classiq rather than created self-service. To obtain credentials, contact your Classiq account manager or sales representative and request an M2M client for your account.
Once the client is created, Classiq delivers the credentials over a secured channel to avoid exposing the secret in transit:
* You receive an encrypted link to the credential details.
* Access is protected by a **one-time verification code** sent to your recipient email address when you open the link.
Treat `CLASSIQ_CLIENT_SECRET` like any other production secret. Do not commit it to source control, embed it in code, or print it in logs.
## Configuring the environment
First, make sure you have the latest Classiq SDK installed:
```bash theme={null}
pip install -U classiq
```
If you have not yet installed the SDK, follow the [Python SDK installation guide](/getting-started/sdk_installation) first.
The SDK reads the credentials from the process environment at authentication time. When both `CLASSIQ_CLIENT_ID` and `CLASSIQ_CLIENT_SECRET` are present, it authenticates silently and skips the interactive browser login entirely.
| Variable | Required | Purpose |
| ----------------------- | -------- | -------------------------------------------------------------- |
| `CLASSIQ_CLIENT_ID` | Yes | The M2M client identifier. |
| `CLASSIQ_CLIENT_SECRET` | Yes | The client secret paired with the ID. |
| `CLASSIQ_ORG_ID` | No | Selects an organization when the client has access to several. |
Set these values as environment variables wherever your code runs. On Linux and macOS, export them in your shell session:
```bash theme={null}
export CLASSIQ_CLIENT_ID="m2m_client_id"
export CLASSIQ_CLIENT_SECRET="your_high_entropy_secret"
```
On Windows, set them with PowerShell for the current session:
```powershell theme={null}
$env:CLASSIQ_CLIENT_ID = "m2m_client_id"
$env:CLASSIQ_CLIENT_SECRET = "your_high_entropy_secret"
```
Replace the placeholder values with the client ID and secret you received.
Because the SDK reads these from the environment, any mechanism that sets them for the process works. In a CI/CD pipeline, keep the secret in the platform's encrypted secrets store and inject both variables into the job. In GitHub Actions:
```yaml theme={null}
env:
CLASSIQ_CLIENT_ID: ${{ secrets.CLASSIQ_CLIENT_ID }}
CLASSIQ_CLIENT_SECRET: ${{ secrets.CLASSIQ_CLIENT_SECRET }}
```
When running in a container, pass the variables through from the host environment:
```bash theme={null}
docker run \
-e CLASSIQ_CLIENT_ID \
-e CLASSIQ_CLIENT_SECRET \
your-image
```
## Authenticating with M2M credentials
You call `classiq.authenticate()` exactly as in the interactive flow. With the variables set, it detects the M2M credentials and uses them instead of opening a browser, so the same code runs unattended.
The M2M flow takes priority over any credentials cached from a previous interactive login on the same machine. M2M tokens are held in memory for the lifetime of the process and are not written to disk, so each new process authenticates fresh.
## Troubleshooting
If authentication fails, the SDK raises:
```text theme={null}
classiq.interface.exceptions.ClassiqAuthenticationError: Request to Auth0 failed with error code 401: access_denied
```
A `401 access_denied` response means the credentials were rejected or the SDK version does not support the M2M flow. Work through these checks:
1. **Verify the version.** Confirm you are running an up-to-date Classiq SDK:
```bash theme={null}
pip show classiq
```
2. **Verify the variables.** Confirm the client ID is exported in the environment running your code:
```bash theme={null}
echo $CLASSIQ_CLIENT_ID
```
On Windows PowerShell, use `echo $env:CLASSIQ_CLIENT_ID` instead.
If it prints nothing, the variables are not set in the current session. Re-export them, and make sure your CI/CD job or scheduler passes them through to the process.
If the problem persists, ask in the [community Slack](https://short.classiq.io/join-slack).
# SDK Authentication
Source: https://docs.classiq.io/user-guide/authentication/sdk-authentication
The Classiq Python SDK authenticates your device with your Classiq account through an interactive, browser-based confirmation. For unattended, server-to-server contexts where no person can sign in, use the [Client Credentials (M2M) flow](/user-guide/authentication/m2m-authentication) instead.
## Authenticating your device
Make sure the SDK is installed before authenticating; see the [Python SDK installation guide](/getting-started/sdk_installation).
In Python, run:
[comment]: DO_NOT_TEST
```python theme={null}
import classiq
classiq.authenticate()
```
A confirmation window opens in your web browser. Confirm the authentication:
Once confirmed, you are ready to use Classiq. The credentials are cached locally and refreshed automatically, so you only need to re-authenticate if they are missing, expired, or revoked.
## Re-authenticating
To replace cached credentials, for example after they expire or when switching accounts, overwrite them:
[comment]: DO_NOT_TEST
```python theme={null}
import classiq
classiq.authenticate(overwrite=True)
```
## Troubleshooting
Overwrite the cached credentials and authenticate again, as described in [Re-authenticating](#re-authenticating).
This error means your authentication credentials were denied. Overwrite them as described in [Re-authenticating](#re-authenticating).
The authentication procedure on headless Linux systems stores the tokens locally in a credentials file. You must still run the authentication once, but it can be done on another system that has a browser, then the credentials file copied over.
On some Apple computers, a system pop-up may appear during authentication:
Type your device password and click **Always Allow** twice.
If the problem persists, ask in the [community Slack](https://short.classiq.io/join-slack).
# Execution Session
Source: https://docs.classiq.io/user-guide/execution/ExecutionSession
This section explains how to execute a quantum program using the `ExecutionSession` class.
The class enables executing a quantum program with parameters and operations, eliminating the need to resynthesize the model.
## Initializing
Initialize `ExecutionSession` with either:
* A **quantum program** (the output of `synthesize`), or
* **OpenQASM 2.0 or 3.0** source as a **string** (same semantics as the first argument to [`sample`](/user-guide/execution/index#sampling-openqasm)).
It is recommended to use `ExecutionSession` as a context manager in order to ensure resources are cleaned up. Alternatively, you can call the `close` method directly.
### Quantum program
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import qfunc, synthesize, ExecutionSession
@qfunc
def main():
pass
qprog = synthesize(main)
with ExecutionSession(qprog) as es:
...
```
### OpenQASM string
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import ExecutionSession
openqasm = """
OPENQASM 2.0;
include "qelib1.inc";
qreg q[1];
h q[0];
"""
with ExecutionSession(openqasm) as es:
details = es.sample()
```
When the first argument is OpenQASM text, do not use `parameters` on `sample` / `submit_sample` for Qmod-style `main` arguments; use a synthesized `QuantumProgram` instead.
## Operations
`ExecutionSession` supports three types of operations:
* `sample`: Executes the quantum program with the specified parameters.
* `estimate`: Computes the expectation value of the specified Hamiltonian using the quantum program.
* `minimize`: Runs a variational minimization loop, iteratively sampling the circuit to minimize a cost function using the COBYLA optimizer.
When estimating using a simulator, the `ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR` backend
calculates the expectation value directly from the computed state vector, as opposed to computing it from shots.
Each invocation mode can use one of these options:
* `single`
* `submit`: When using submit as a prefix, the job object returns immediately, and the results should be polled. See `ExecutionJob` in the [sdk reference](/sdk-reference/index).
For the `sample` method, pass a single parameter dict or a list for batch execution:
* `es.sample(parameters: Optional[ExecutionParams | List[ExecutionParams]])`
* `es.submit_sample(parameters: Optional[ExecutionParams | List[ExecutionParams]])`
The `estimate` method works the same way:
* `es.estimate(hamiltonian: SparsePauliOp, parameters: Optional[ExecutionParams | List[ExecutionParams]])`
* `es.submit_estimate(hamiltonian: SparsePauliOp, parameters: Optional[ExecutionParams | List[ExecutionParams]])`
The `minimize` method accepts a `max_iteration` parameter:
* `es.minimize(cost_function, initial_params, max_iteration)`
`max_iteration` does not directly control the number of quantum jobs. It sets an upper bound on the number of classical optimizer (COBYLA) iterations; the optimizer may converge before reaching this limit. See the [scipy COBYLA documentation](https://docs.scipy.org/doc/scipy/reference/optimize.minimize-cobyla.html) for details on iteration and convergence behavior.
## Examples
### sample()
A simple example of how to use `sample` and its variations:
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
qfunc,
Output,
QBit,
CReal,
synthesize,
RX,
allocate,
ExecutionSession,
)
@qfunc
def main(x: Output[QBit], t: CReal):
allocate(1, x)
RX(t, x)
qprog = synthesize(main)
with ExecutionSession(qprog) as execution_session:
sample_result = execution_session.sample({"t": 0.5})
print(sample_result.dataframe)
batch_sample_result = execution_session.sample([{"t": 0.5}, {"t": 0.6}])
sample_job = execution_session.submit_sample({"t": 0.5})
batch_sample_job = execution_session.submit_sample([{"t": 0.5}, {"t": 0.6}])
```
### estimate()
An example that shows how to use `estimate` and its variations:
```python theme={null}
from classiq import (
qfunc,
Output,
QBit,
CReal,
synthesize,
Pauli,
RX,
allocate,
ExecutionSession,
)
@qfunc
def main(x: Output[QBit], t: CReal):
allocate(1, x)
RX(t, x)
qprog = synthesize(main)
with ExecutionSession(qprog) as execution_session:
hamiltonian = Pauli.I(0) + 2 * Pauli.Z(0)
estimate_result = execution_session.estimate(hamiltonian, {"t": 0.5})
batch_estimate_result = execution_session.estimate(
hamiltonian, [{"t": 0.5}, {"t": 0.6}]
)
estimate_job = execution_session.submit_estimate(hamiltonian, {"t": 0.5})
batch_estimate_job = execution_session.submit_estimate(
hamiltonian, [{"t": 0.5}, {"t": 0.6}]
)
```
## Handling Long Jobs
When handling long-running jobs (jobs that are submitted to HW providers with potentially very long queues) it is advisable to retrieve and save the job ID for future reference:
[comment]: DO_NOT_TEST
```python theme={null}
...
with ExecutionSession(qprog) as session:
job = session.submit_sample()
job_ID = job.id
restored_job = ExecutionJob.from_id(job_ID)
results = restored_job.get_sample_result()
```
Alternatively, for scenarios requiring result polling, e.g., iterative hybrid algorithms, consider the following partial code example.
This example runs a series of quantum estimation jobs, step by step.
It automatically submits each job, collects the results, checks they meet certain criteria (for example, does the cost exceed a certain threshold), and adjusts the parameters for the next job based on those results.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import ExecutionSession, ExecutionJob
def get_data_from_file():
# read data from file
return data
def store_data_in_file(data):
# save data in file
return
with ExecutionSession(qprog) as session:
iterations_data = get_data_from_file() or []
for _ in range(max_iterations - len(iterations_data)):
if iterations_data and "result" not in iterations_data[-1]:
# continue the loop from the last iteration
last_job = ExecutionJob.from_id(iterations_data[-1]["job_id"])
else:
last_job = session.submit_estimate(hamiltonian, params)
iterations_data.append({"job_id": last_job.id, "params": params})
store_data_in_file(iterations_data)
result = last_job.get_estimate_result()
iterations_data[-1]["result"] = result
store_data_in_file(iterations_data)
if result_is_good_enough(result):
break
params = compute_the_next_parameters(result)
```
## `@cfunc`
Note that Classiq does not support algorithms utilizing `@cfunc` (or `cscope` in Qmod native) for long job execution.
# Hardware Benchmarking
Source: https://docs.classiq.io/user-guide/execution/benchmarking/index
Benchmarking quantum hardware is essential on the path toward practical quantum
computing. As hardware advances, benchmarking must go beyond standard device-level
tests such as randomized benchmarking or Quantum Volume to include **algorithmic- and
application-level** evaluation, which measures what ultimately matters: the
correctness and usefulness of the final computational outcome.
## Functional-level benchmarks
Classiq provides a functional-level benchmarking suite for this purpose. Each
benchmark is defined by a quantum model, a **score**, and a problem-size parameter,
so you can study how performance scales with the task. Hardware constraints such as
circuit width are handled at the synthesis stage rather than hard-coded into the
benchmark, keeping the functional definition of a task separate from the capabilities
of the target device.
## Running across backends
Classiq exposes a wide variety of backends — QPUs, hardware emulators, and simulators
across many providers — and lets you switch smoothly between them. The platform also
handles the operational side of a run — managing execution
budget (including running jobs against your Classiq-allocated budget, or emulating a
device's noise model without consuming QPU time or credits) and tracking the time
each job takes to complete, so backends are directly comparable on both accuracy and
turnaround.
## Next steps
Run a set of predefined benchmarks covering canonical algorithmic and
application-level tasks, or define your own. See
[Predefined Benchmarks](./predefined-benchmarks) to get started.
# Predefined Benchmarks
Source: https://docs.classiq.io/user-guide/execution/benchmarking/predefined-benchmarks
The predefined benchmarks let you measure and compare how well quantum backends run a set of
well-established quantum circuits. You pick a benchmark, a range of problem sizes,
and a set of backends; Classiq runs every combination, scores each result, and
returns a table and a scalability chart you can use to decide which hardware fits
your workload.
You run benchmarks from the **Classiq IDE**, a no-code interface on the Execution
page. It's ideal for interactive hardware evaluation and for comparing devices
without writing any code. The same benchmarks can also be run from the Classiq
SDK via [`run_benchmark`](../../../sdk-reference/execution#run_benchmark).
## Supported benchmarks
Each benchmark targets a different circuit family and scales with a single
**problem size** parameter. Every benchmark returns a **score** between 0 and 1,
where higher is better and lower values reflect hardware noise and errors. For most
benchmarks 1 corresponds to ideal, noiseless behavior; for some (such as Dynamical
Localization) the ideal noiseless value can itself be lower than 1. The score is
defined per benchmark:
| Benchmark | What it measures | Problem size | Score |
| -------------------------- | -------------------------------------------------------------- | -------------------- | -------------------------------------------------------------- |
| **GHZ** | Ability to create and preserve a maximally entangled GHZ state | Number of qubits | Fidelity of the prepared GHZ state |
| **Adder** | Correctness of in-circuit modular addition | Register size (bits) | Probability of measuring the correct sum |
| **QFT** | Accuracy of the Quantum Fourier Transform output distribution | Number of qubits | 1 − total-variation distance from the ideal distribution |
| **State Preparation** | Accuracy of preparing a target (linear-amplitude) state | Number of qubits | 1 − total-variation distance from the ideal distribution |
| **Dynamical Localization** | Preservation of localization dynamics under repeated kicks | System size | Normalized localization peak (geometric mean over kick counts) |
Some benchmarks enforce a minimum problem size (for example, GHZ and Adder start
at 3). The IDE enforces these limits in the configuration form.
## Benchmarking in the Classiq IDE
Open the **Execution** page in the IDE and switch the mode toggle from **Quantum
Program** to **Benchmark**.
### Configure the run
Select a benchmark type. A short description and its problem-size parameter are
shown. Then set:
* **Problem sizes:** the range of sizes to sweep, as **min / max / step** (for
example, GHZ at 4, 8, 16). Each size runs as its own job.
* **Backends:** multi-select from the available backends (up to **10** per
session). Includes QPUs, hardware emulators, and simulators.
* **Shots:** number of shots per job (default: 1,000).
* **Run via Classiq:** per-backend toggle. When on, the job runs against your
Classiq-allocated budget using Classiq's provider credentials, so you don't need
your own account with that provider.
* **Emulate:** run against the target hardware's noise model without consuming
real QPU time or credits.
* **Name:** an optional name for the benchmark session.
Click **Run Benchmark** to submit.
### Cancel, history, and the Jobs page
**Cancel** stops the session: jobs that already finished (Done or Failed) stay in
the table and chart; jobs still Pending or Running are set to Cancelled.
Reopening a past session re-hydrates its full chart and table.
# Managing Execution Budget
Source: https://docs.classiq.io/user-guide/execution/budget-management
Enrolled users can run quantum programs on multiple backends without needing to provide their own credentials, by using `run_via_classiq`.
When a job is submitted using `run_via_classiq`, it will only proceed if the estimated cost is within the remaining budget allocated for the chosen provider.
Additionally, we offer methods to monitor usage and set limits, helping you control and optimize your spending.
For example, to set up execution using `run_via_classiq` on the Amazon Braket SV1 simulator:
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QBit]):
allocate(x)
qprog = synthesize(main)
exec_pref = ExecutionPreferences(
backend_preferences=AwsBackendPreferences(
backend_name="SV1",
run_via_classiq=True,
)
)
# Assuming you have a pre-defined quantum program "qprog"
with ExecutionSession(qprog, execution_preferences=exec_pref) as es:
result = es.sample()
```
## Checking the Remaining Budget
To view your remaining execution budget, run the following command:
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import *
budget = get_budget()
print(budget)
```
A table will be displayed:
## Setting a Custom Budget Limit
You can also define a custom spending limit to stay within a desired budget (lower than your total budget). For example:
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import *
budget = set_budget_limit(
provider=ProviderVendor.AMAZON_BRAKET,
limit=90, # Set a custom limit below the provider's remaining budget
)
```
To verify the updated limit, simply run `print(budget)` again. The output will now reflect the new budget cap:
To clear user-defined budget limits, run `clear_budget_limit("Amazon Braket")`.
# Calculate State Vector
Source: https://docs.classiq.io/user-guide/execution/calculate-state-vector
The `calculate_state_vector(...)` function is used when you want direct access to the quantum state itself, including amplitudes and phases.
Related pages:
* [Execution overview](./index)
* [Sampling](./sample)
* [Observe](./observe)
## When to use state-vector calculation
Use `calculate_state_vector(...)` when you want the full quantum state rather than measurement statistics or a single expectation value.
State-vector calculations are only available only on Classiq simulators.
This is useful when you want to:
* inspect amplitudes directly
* understand the exact state prepared by the circuit
* analyze phases and probabilities
* debug or study a circuit without sampling noise
Unlike sampling, noiseless state-vector calculation is deterministic. It does not rely on repeated measurements, so it does not introduce statistical fluctuations.
## Basic example
```python theme={null}
from classiq import *
backend_name = "simulator"
@qfunc
def main(res: Output[QBit]) -> None:
allocate(res)
H(res)
qprog = synthesize(main)
df = calculate_state_vector(
qprog,
backend=backend_name,
)
df
```
**Example output**
| x | amplitude | magnitude | phase | probability | bitstring |
| - | ------------------ | --------- | ----- | ----------- | --------- |
| 0 | 0.707107+0.000000j | 0.71 | 0.00π | 0.5 | 0 |
| 1 | 0.707107+0.000000j | 0.71 | 0.00π | 0.5 | 1 |
### Understanding the result
The returned object is a DataFrame describing the full state.
Common columns include:
* **quantum variables** - the quantum number values, quantum arrays, and qubits
* **amplitude** — the complex amplitude of the basis state
* **magnitude** — the absolute value of the amplitude
* **phase** — the phase angle
* **probability** — the squared magnitude
* **bitstring** — the computational basis state
Because the result is a DataFrame, you can inspect or manipulate it using standard operations.
### Filtering small amplitudes
By default, very small amplitudes are filtered out below a threshold of $10^{-16}$.
You can control this behavior using `amplitude_threshold`:
[comment]: DO_NOT_TEST
```python theme={null}
df = calculate_state_vector(
qprog,
backend=backend_name,
amplitude_threshold=0.01
)
```
This is useful for reducing numerical noise and simplifying the displayed state,
especially for larger systems where many amplitudes may be negligible.
## Parameterized execution
State-vector calculation also supports parameterized quantum programs.
This means you can define symbolic parameters in your circuit and provide their numerical values at execution time.
**Example**
```python theme={null}
from classiq import *
backend_name = "simulator"
@qfunc
def main(angle_rx: CReal, angle_ry: CReal, x: Output[QBit]):
allocate(x)
RX(angle_rx, x)
H(x)
RY(angle_ry, x)
qprog = synthesize(main)
exec_params = {
"angle_rx": 0.5,
"angle_ry": 0.3
}
df = calculate_state_vector(
qprog,
backend=backend_name,
parameters=exec_params,
)
df
```
| x | amplitude | magnitude | phase | probability | bitstring |
| - | ------------------ | --------- | ------ | ----------- | --------- |
| 1 | 0.779815+0.146834j | 0.79 | 0.06π | 0.629672 | 1 |
| 0 | 0.575048-0.199119j | 0.61 | -0.11π | 0.370328 | 0 |
In this workflow:
* the circuit structure stays the same
* the parameter values are supplied at execution time
* the returned DataFrame describes the exact state corresponding to those values
## Summary
Use `calculate_state_vector(...)` when you need the full quantum state.
State-vector calculation:
* returns a DataFrame
* provides amplitudes, phases, and probabilities
* is deterministic
* supports parameterized execution
* only allowed on simulators
# Execution on Alice and Bob Quantum Cloud
Source: https://docs.classiq.io/user-guide/execution/cloud-providers/alice-and-bob-backends
The Classiq executor supports execution on Alice and Bob logical hardwares.
## Usage
Alice and Bob provide multiple logical targets that we can use.
Execution on Alice and Bob requires a valid API key. Additionally, Alice and Bob introduces several
customizable hardware parameters (Available through SDK only):
### average\_nb\_photons
Bit-flip probability decreases exponentially with this parameter, phase-flip probability increases linearly.
### kappa\_1
The rate at which the cat qubit loses one photon, creating a bit-flip. Lower values mean lower error rates.
### kappa\_2
The rate at which the cat qubit is stabilized using two-photon dissipation. Higher values mean lower error rates.
### distance
The number of times information is duplicated in the repetition code. Phase-flip probability decreases exponentially with this parameter, bit-flip probability increases linearly.
## Execution
### Setting up Backend Preferences
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import AliceBobBackendNames, AliceBobBackendPreferences
backend_preferences = AliceBobBackendPreferences(
backend_service_provider="Alice & Bob",
api_key="",
backend_name=AliceBobBackendNames.LOGICAL_TARGET,
kappa_1=10.0, # OR Remove it to keep default value
kappa_2=1000, # OR Remove it to keep default value
distance=3, # OR Remove it to keep default value
average_nb_photons=7, # OR Remove it to keep default value
)
```
### Setting up execution preferences and adding number of shots
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import ExecutionPreferences
execution_preferences = ExecutionPreferences(
num_shots=1000,
backend_preferences=backend_preferences,
)
```
### Prepare for Hardware-aware synthesis
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import Preferences
preferences = Preferences(
backend_service_provider=ProviderVendor.ALICE_AND_BOB,
backend_name=AliceBobBackendNames.LOGICAL_TARGET,
)
```
### Execute
At this point you should just create your model, set execution preferences and perform Hardware-aware synthesize then execute.
[comment]: DO_NOT_TEST
```python theme={null}
quantum_program = synthesize(your_model, preferences=preferences)
quantum_program = set_quantum_program_execution_preferences(
quantum_program, execution_preferences
)
result = execute(quantum_program).result()
```
Choose Model/Graphical Model tab in IDE, and go to ***"Synthesis Configuration"*** section
***After synthesizing***, you will be navigated to ***Execution*** page, or you can just navigate to it and choose ***Alice & Bob*** backend(s)
## Supported Backends
* "LOGICAL\_EARLY"
* "LOGICAL\_TARGET"
* "LOGICAL\_NOISELESS"
# Execution on Amazon Braket Cloud
Source: https://docs.classiq.io/user-guide/execution/cloud-providers/amazon-backends
The Classiq executor supports execution on Amazon Braket's cloud simulators and hardware.
Backends may sometimes be unavailable. Check the availability windows with Amazon Braket.
## Usage
Execution on Amazon Braket requires an AWS account, and a role that Classiq can assume for execution.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import AwsBackendPreferences
preferences = AwsBackendPreferences(
backend_name="Name of requested simulator or hardware",
aws_access_key_id="Amazon access key ID for the user with Braket access",
aws_secret_access_key="Secret access key for the user's key ID",
s3_bucket_name="S3 bucket name to save the results",
s3_folder="The folder path within the S3 bucket, where the results will be saved",
job_timeout="Timeout for execution (Optional)",
)
```
### Initial Account Setup
Before first use, the platform needs your permission to connect to your
AWS account. This is done by creating a cross-account role.
Classiq provides with the attached CloudFormation `AssumeRole.cf.yaml` file. It only has the permissions needed for Braket.
To create the cross-account role that only Classiq can use, deploy the CloudFormation file to your account:
1. Download the [AssumeRole.cf.yaml](./resources/AssumeRole.cf.yaml.txt) file.
2. Install [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).
3. Contact [Classiq support](mailto:support@classiq.io) to obtain these parameters:
1. `CORRECT_TRUSTED_ACCOUNT`
2. `CORRECT_EXTERNAL_ID_VALUE`
4. Execute this command:
```
aws cloudformation create-stack --stack-name ClassiqBraketRole --template-body file://AssumeRole.cf.yaml --capabilities CAPABILITY_NAMED_IAM --parameters ParameterKey=TrustedAccount,ParameterValue=${CORRECT_TRUSTED_ACCOUNT} ParameterKey=ExternalId,ParameterValue=${CORRECT_EXTERNAL_ID_VALUE}
```
The required parameters may differ between users.
Contacting Classiq support is required!
To learn more about IAM roles, refer to the [AWS documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html).
### Required Credentials
When executing via the platform using AWS Cloud, there are several
required credentials:
1. `aws_access_key_id`
1. Create a user with Braket full access
2. Create AWS secret key for this user
3. Fill the access key id as you got in the earlier steps
2. `aws_secret_access_key`
1. Fill the Secret access key from the steps above
3. `s3_bucket_name`
1. Create a new bucket. Its name must start with `amazon-braket-`.
2. Use the bucket name as the `s3_bucket_name`.
This is the bucket that saves the execution results.
4. `s3_folder`
1. Enter the path to the folder in the `S3 bucket`.
This is the path in the bucket where the execution results are
saved.
For further support, contact [Classiq support](mailto:support@classiq.io).
## Device emulation (emulate)
Set `emulate=True` on [`AwsBackendPreferences`](/sdk-reference/providers/AWS) to use Classiq’s **device-aware Braket circuit preparation** for the selected Amazon Braket **device**: the circuit is translated using constraints from that device before the job is submitted. This path differs from the default Qiskit–Braket conversion and can be required for some programs targeting specific hardware.
* **Default** `emulate=False`: standard adapter from Qiskit to Braket.
* **`emulate=True`**: use Classiq’s emulator-style translation for the chosen device. If compilation fails, try without `emulate` or another backend; see the error message from the executor.
Behavior depends on the Braket device and circuit; refer to [Amazon Braket documentation](https://docs.aws.amazon.com/braket/) for device capabilities.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import AwsBackendPreferences
preferences = AwsBackendPreferences(
backend_name="Ankaa-3",
aws_access_key_id="…",
aws_secret_access_key="…",
s3_bucket_name="amazon-braket-…",
s3_folder="results",
emulate=True,
)
```
## Supported Backends
The Classiq executor supports any available gate-based Amazon Braket simulator and quantum hardware.
Included hardware:
* "Forte 1"
* "Emerald"
* "Ankaa-3"
* "Garnet"
Included simulators:
* "SV1"
* "TN1"
* "dm1"
# Execution on Azure Quantum Cloud
Source: https://docs.classiq.io/user-guide/execution/cloud-providers/azure-backends
The Classiq executor supports execution on Azure Quantum cloud simulators and hardware.
Backends may sometimes be unavailable. Check the availability windows with Azure Quantum.
## Usage
Possible modes of operation:
* Running via Classiq-Azure integration. In this mode you do not need to provide credentials or location.
* Executing on your private Azure Quantum Workspace by providing credentials.
For more details, see [Executing on Your Quantum Workspace](#executing-on-your-quantum-workspace).
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
AzureCredential,
AzureBackendPreferences,
)
# Running via Classiq-Azure integration:
preferences = AzureBackendPreferences(
backend_name="Name of requsted simulator or hardware",
)
# Running via a private Azure account:
cred = AzureCredential(
tenant_id="Azure Tenant ID (from Azure Active Directory)",
client_id="Azure Application (client) ID",
client_secret="Azure Client Secret",
resource_id="Azure Quantum Workspace Resource ID",
)
preferences = AzureBackendPreferences(
backend_name="Name of requsted simulator or hardware",
credentials=cred,
location="Azure region of Quantum Workspace",
)
```
For academic users, backends run via Classiq-Azure integration by default. To override this configuration, switch on "Run with my own credentials" in the backends summary section on the Execution page:
## Executing on Your Quantum Workspace
Execution on your private Azure Quantum Workspace requires an Azure account with
an active subscription. To authenticate, provide these details:
* `Resource ID`: Azure Quantum Workspace resource ID.
* `Location`: Azure region of the Quantum Workspace.
* `Tenant ID`: Azure Active Directory tenant ID.
* `Client ID`: Azure client ID of a registered application.
* `Client secret`: Azure client secret of a registered application.
Following is a brief description of the steps to configure and acquire these details:
1. Create an Azure Quantum Workspace (see
[Azure documentation](https://docs.microsoft.com/en-us/azure/quantum/how-to-create-workspace)).
In the workspace overview are the `Location` and `Resource ID`.
2. Register a new application in Azure, including creating a client secret (see
[Azure documentation](https://learn.microsoft.com/en-us/azure/developer/python/sdk/authentication-on-premises-apps?tabs=azure-portal#1---register-the-application-in-azure)).
At the end of this step are the settings for `Client ID`, `Client secret`, and `Tenant ID`.
3. Assign the `Contributor` role to the registered application on the Quantum Workspace
or a resource group containing the Quantum Workspace (see
[Azure documentation](https://learn.microsoft.com/en-us/azure/developer/python/sdk/authentication-on-premises-apps?tabs=azure-portal#2---assign-roles-to-the-application-service-principal)).
4. Add the `Jobs.ReadWrite` permission (under `Azure Quantum`) to the application (see
[Azure documentation](https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-add-app-roles-in-azure-ad-apps#assign-app-roles-to-applications)).
## Supported Backends
Included hardware:
* "ionq.qpu.forte-1"
* "ionq.qpu.forte-enterprise-1"
Included simulators:
* "ionq.simulator"
* "rigetti.sim.qvm"
* "quantinuum.sim.h2-1sc"
* "quantinuum.sim.h2-1e"
## IonQ hardware noise simulation on Azure Quantum (emulate)
For **IonQ QPU** targets on Azure Quantum (`backend_name` values that start with `ionq.qpu.`), set `emulate=True` on [`AzureBackendPreferences`](/sdk-reference/providers/Azure) to enable IonQ’s **hardware noise model simulation**. Classiq passes Azure’s `noise` job options using the matching noise profile for the selected backend.
Behavior details, allowed profiles, shots, and qubit limits are defined by Azure and IonQ; see [Noise model simulation (Microsoft Learn)](https://learn.microsoft.com/en-us/azure/quantum/provider-ionq#noise-model-simulation).
When `emulate` does **not** apply, it is **ignored** (no error): for example `ionq.simulator`, Quantinuum targets, Rigetti targets, or any backend that is not an IonQ QPU. That lets you reuse one preferences object across several Azure targets.
`emulate` is separate from `ionq_error_mitigation_flag`, which controls debiasing-style error mitigation on IonQ hardware.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import AzureBackendPreferences
preferences = AzureBackendPreferences(
backend_name="ionq.qpu.aria-1",
emulate=True,
)
```
# Execution on C12 Quantum Cloud
Source: https://docs.classiq.io/user-guide/execution/cloud-providers/c12
[C12](https://www.c12qe.com/) is building scalable carbon-based quantum computers. Classiq supports execution on C12 QPU-emulators.
C12 simulator Callisto imitates the physical parameters of noise from C12's hardware. The fidelity parameters of the simulator can be accessed from C12's [documentation](https://c12qe.github.io/c12-callisto-clients/0.%20README.html).
## Configuration
C12 introduces several customizable hardware parameters:
### inilabel
The initial state specified using a binary label format, such as "00", "01", etc.
### inistatevector
The initial state vector for each qubit, provided as a comma-separated list of complex values.
Example: "1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j"
Note: Either `inilabel` or `inistatevector` can be provided but not both.
### ininoisy
Indicates whether noisy initialization of the circuit should be used.
###
## Usage Example
If you are using [Classiq IDE](https://platform.classiq.io/), simply choose C12 in the checkbox menu under Execution page.
### Setting up Backend Preferences
[comment]: DO_NOT_TEST
```python theme={null}
from classiq.execution import C12BackendPreferences
from classiq import ExecutionPreferences, ExecutionSession, synthesize
backend_preferences = C12BackendPreferences(
backend_name="c12sim-iswap",
inilabel="00", # Either inilabel or inistatevector must be provided
# inistatevector="1.+0.j, 0.+0.j,", # Either inilabel or inistatevector must be provided
ininoisy=True,
)
execution_preferences = ExecutionPreferences(
num_shots=1000,
backend_preferences=backend_preferences,
)
```
### Execute with ExecutionSession
Create your model, set execution preferences, synthesize, then run with `ExecutionSession`:
[comment]: DO_NOT_TEST
```python theme={null}
quantum_program = synthesize(your_model, preferences=preferences)
with ExecutionSession(quantum_program, execution_preferences) as session:
result = session.sample()
```
## Supported Backends
* SIMULATOR = "Callisto Emulator"
# Execution on Classiq simulators
Source: https://docs.classiq.io/user-guide/execution/cloud-providers/classiq-backends
Classiq offers execution on simulators that are located at the Classiq backend.
These simulators don't require an account on a different cloud, and are usually
fast to execute.
## Simulator Usage
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import ClassiqBackendPreferences
preferences = ClassiqBackendPreferences(
backend_name="Name of requested quantum simulator"
)
```
Classiq supports following simulators:
1. `simulator`: A general-purpose quantum simulator capable of handling circuits with up to 28 qubits.
2. `simulator_statevector`: Returns the full state vector, including phase information of the output state produced by the quantum circuit. Due to the exponential growth of the state vector, this simulator is suitable only for circuits with up to 18 qubits.
3. `simulator_density_matrix`: Uses density matrices to simulate open quantum circuits and supports simulations for circuits containing up to 28 qubits.
4. `simulator_matrix_product_state`: Efficiently simulates quantum circuits of up to 28 qubits, especially suited for circuits exhibiting low entanglement.
You can access these simulators through `ClassiqSimulatorBackendNames`.
## Custom noise models
Classiq simulators support user-defined gate and readout noise through
`ClassiqSimulatorNoiseSpecification`. This is separate from preset device noise
(`noise_model` on `ClassiqBackendPreferences`). See
[Custom noise models on Classiq simulators](./custom-noise-models) for channel types,
validation rules, and code examples.
## Nvidia Simulator Usage
Execution on Nvidia simulators requires specific license permissions.
Before first use, contact [Classiq support](mailto:support@classiq.io).
Classiq supports two types of Nvidia simulators, with the same inputs and outputs but different underlying infrastructure, capable of simulating circuits with up to 29 qubits:
1. The backends `ClassiqNvidiaBackendNames.SIMULATOR` and `ClassiqNvidiaBackendNames.SIMULATOR_STATEVECTOR` are better suited when multiple circuits need to be executed in sequence.
2. The backends `ClassiqNvidiaBackendNames.BRAKET_NVIDIA_SIMULATOR` and `ClassiqNvidiaBackendNames.BRAKET_NVIDIA_SIMULATOR_STATEVECTOR` are executed using Amazon Braket's infrastructure, and provide faster execution for single circuits. Credentials for AWS are not needed.
Both `ClassiqNvidiaBackendNames.SIMULATOR_STATEVECTOR` and `ClassiqNvidiaBackendNames.braket_nvidia_simulator_statevector` return the state vector at the end of the circuit's execution (analogous to the
above `simulator_statevector`).
**Precision:** Nvidia and Braket Nvidia simulators use **double precision** (float64) by default. Set `use_single_precision=True` in `ClassiqBackendPreferences` to use single precision (float32), which can be faster and use less memory at the cost of numerical precision.
```python theme={null}
from classiq import ClassiqBackendPreferences, ClassiqNvidiaBackendNames
preferences = ClassiqBackendPreferences(
backend_name=ClassiqNvidiaBackendNames.SIMULATOR
)
# Optional: use single precision (float32) instead of default double (float64)
preferences_single = ClassiqBackendPreferences(
backend_name=ClassiqNvidiaBackendNames.BRAKET_NVIDIA_SIMULATOR,
use_single_precision=True,
)
```
The number of execution requests to the NVIDIA simulator may be limited.
If you encounter any problem, contact
[Classiq support](mailto:support@classiq.io).
## DGX Statevector Simulator
Classiq offers a GPU-accelerated statevector simulator running on an NVIDIA DGX system. It is designed for large circuits, supporting up to **35 qubits**, making it well suited for state-vector simulations that exceed the capacity of the standard Classiq simulators.
Like the other GPU simulators, the DGX simulator requires specific license permissions. Before first use, contact [Classiq support](mailto:support@classiq.io).
The DGX simulator supports both execution modes:
1. **Sampling**: returns measurement counts for a given number of shots.
2. **Statevector**: returns the full output state vector. Because the state vector grows exponentially with the number of qubits, large statevector requests can be very large; filtering the returned registers is recommended.
The DGX simulator is selected by passing `backend="classiq/dgx_simulator"` to your execution call. For example:
[comment]: DO_NOT_TEST
```python theme={null}
sample(qprog, backend="classiq/dgx_simulator")
```
**Precision:** The DGX simulator runs in **single precision** (float32), which keeps the memory footprint low enough to reach its 35-qubit capacity.
The number of execution requests to the DGX simulator may be limited, and large circuits can take a long time to run. If you encounter any problem, contact [Classiq support](mailto:support@classiq.io).
## Supported Backends
Included simulators:
* "nvidia\_simulator\_statevector"
* "simulator"
* "simulator\_statevector"
* "simulator\_density\_matrix"
* "nvidia\_simulator"
* "braket\_nvidia\_simulator"
* "simulator\_matrix\_product\_state"
* "braket\_nvidia\_simulator\_statevector"
* "dgx\_simulator"
# Custom noise models on Classiq simulators
Source: https://docs.classiq.io/user-guide/execution/cloud-providers/custom-noise-models
Define depolarizing, Pauli, thermal relaxation, and readout noise for Classiq-hosted simulators.
Classiq-hosted simulators support **user-defined noise** through
[`ClassiqSimulatorNoiseSpecification`](/sdk-reference/providers/simulator-noise#classiqsimulatornoisespecification).
Combine any subset of gate and readout channels; an empty specification runs an ideal
(noise-free) simulation.
Custom noise is available on Classiq Aer simulators (`simulator`, `simulator_density_matrix`,
`simulator_matrix_product_state`, and related backends) and on Nvidia / Braket Nvidia
simulators. See [Execution on Classiq simulators](./classiq-backends) for backend names.
**Preset vs custom noise:** [`ClassiqBackendPreferences`](/sdk-reference/providers/Classiq)
accepts either `noise_model` (a named preset from `CLASSIQ_NOISE_MODELS`, such as
`ibm_pittsburgh`) **or** `simulator_noise_spec` (custom). Set at most one of them.
## Quick start
Attach a noise specification through backend preferences when you execute a program.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import *
@qfunc
def main(res: Output[QBit]) -> None:
allocate(res)
X(res)
qprog = synthesize(main)
noise_spec = ClassiqSimulatorNoiseSpecification(
readout_bit_flip_probability=0.02,
)
df = sample(
qprog,
backend="simulator",
config={"simulator_noise_spec": noise_spec},
num_shots=1000,
)
```
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import *
@qfunc
def main(res: Output[QBit]) -> None:
allocate(res)
X(res)
qprog = synthesize(main)
execution_preferences = ExecutionPreferences(
backend_preferences=ClassiqBackendPreferences(
backend_name=ClassiqSimulatorBackendNames.SIMULATOR,
simulator_noise_spec=ClassiqSimulatorNoiseSpecification(
readout_bit_flip_probability=0.02,
),
),
num_shots=1000,
)
with ExecutionSession(qprog, execution_preferences=execution_preferences) as session:
df = session.sample().dataframe
```
## Noise channels
The sections below describe each building block. Every section includes a minimal code
example you can copy into `ClassiqSimulatorNoiseSpecification(...)`.
### Depolarizing noise on gates
Depolarizing noise mixes the state with the maximally mixed state on the support of the
gate: with probability $(4^n-1)/4^n \cdot \lambda$ a uniform Pauli error is applied
(excluding identity), and otherwise the channel leaves the state unchanged, where $n$ is
the number of qubits the gate acts on and $\lambda$ is the `probability` parameter.
Use [`DepolarizingNoiseOnGate`](/sdk-reference/providers/simulator-noise#depolarizingnoiseongate)
to apply the same depolarizing channel on **every** occurrence of a named gate.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import ClassiqSimulatorNoiseSpecification, DepolarizingNoiseOnGate
ClassiqSimulatorNoiseSpecification(
gate_depolarizing_errors=[
DepolarizingNoiseOnGate(gate="x", probability=0.001, num_qubits=1),
DepolarizingNoiseOnGate(gate="cx", probability=0.01, num_qubits=2),
],
)
```
### Local depolarizing noise on gates
[`LocalDepolarizingNoiseOnGate`](/sdk-reference/providers/simulator-noise#localdepolarizingnoiseongate)
applies depolarizing noise only when the named gate acts on a **specific ordered tuple**
of qubit indices. Other placements of the same gate name are unaffected.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import ClassiqSimulatorNoiseSpecification, LocalDepolarizingNoiseOnGate
ClassiqSimulatorNoiseSpecification(
local_depolarizing_errors=[
LocalDepolarizingNoiseOnGate(
gate="cx",
num_qubits=2,
probability=0.02,
qubits=[0, 1],
),
],
)
```
### Pauli noise on gates
Pauli noise is a probabilistic mixture: each term is a Pauli product (written as a string
of `I`, `X`, `Y`, `Z` per qubit, e.g. `X` on one qubit, `IX` or `XY` on two) with an
associated probability. All term probabilities must sum to 1.
Use [`PauliNoiseTerm`](/sdk-reference/providers/simulator-noise#paulinoiseterm) and
[`PauliNoiseOnGate`](/sdk-reference/providers/simulator-noise#paulinoiseongate) to attach
a mixed Pauli channel to every occurrence of a gate. Include an identity (`I`) term when
you want a fraction of executions to stay error-free.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
ClassiqSimulatorNoiseSpecification,
PauliNoiseOnGate,
PauliNoiseTerm,
)
ClassiqSimulatorNoiseSpecification(
gate_pauli_errors=[
PauliNoiseOnGate(
gate="x",
num_qubits=1,
pauli_terms=[
PauliNoiseTerm(pauli="I", probability=0.99),
PauliNoiseTerm(pauli="X", probability=0.01),
],
),
],
)
```
### Thermal relaxation on single-qubit gates
Thermal relaxation models energy decay and dephasing over a gate duration. Use coherent
time constants `t1` (amplitude damping) and `t2` (dephasing) in any consistent unit, the
same unit for `time` as the gate duration, and optional `excited_state_population` for
the equilibrium $|1\rangle$ population. For physical consistency, require $T_2 \leq 2 T_1$.
[`ThermalRelaxationNoiseOnGate`](/sdk-reference/providers/simulator-noise#thermalrelaxationnoiseongate)
is defined for a single computational qubit; attach it only to single-qubit gate names.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import ClassiqSimulatorNoiseSpecification, ThermalRelaxationNoiseOnGate
ClassiqSimulatorNoiseSpecification(
gate_thermal_relaxation_errors=[
ThermalRelaxationNoiseOnGate(
gate="sx",
t1=60_000.0,
t2=20_000.0,
time=100.0,
),
],
)
```
### Global readout bit-flip probability
The symmetric one-parameter readout model swaps classical outcomes 0 and 1 with
probability `p` on **each** qubit, for both $|0\rangle$ and $|1\rangle$ pre-measurement
states. Set `readout_bit_flip_probability` on
[`ClassiqSimulatorNoiseSpecification`](/sdk-reference/providers/simulator-noise#classiqsimulatornoisespecification).
This field is mutually exclusive with `readout_assignment_probabilities`.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import ClassiqSimulatorNoiseSpecification
ClassiqSimulatorNoiseSpecification(
readout_bit_flip_probability=0.02,
)
```
### Global readout assignment matrix
Readout noise can also be specified with a 2-by-2 **assignment matrix**: row index is the
true pre-measurement computational state (0 or 1), column index is the classical
outcome (0 or 1); entry $(i,j)$ is the probability of recording outcome $j$ when the
qubit was in state $|i\rangle$. Each row must be non-negative and sum to 1.
Set `readout_assignment_probabilities` to apply one matrix to **every** qubit's measurement.
Mutually exclusive with `readout_bit_flip_probability`.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import ClassiqSimulatorNoiseSpecification
ClassiqSimulatorNoiseSpecification(
readout_assignment_probabilities=[[0.98, 0.02], [0.03, 0.97]],
)
```
### Local readout noise
[`LocalReadoutNoise`](/sdk-reference/providers/simulator-noise#localreadoutnoise) assigns a
full 2-by-2 assignment matrix to a **single** simulator qubit index. Use
`local_readout_errors` when different qubits need different readout confusion.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import ClassiqSimulatorNoiseSpecification, LocalReadoutNoise
ClassiqSimulatorNoiseSpecification(
local_readout_errors=[
LocalReadoutNoise(
qubit=0,
assignment_probabilities=[[0.9, 0.1], [0.15, 0.85]],
),
],
)
```
### Basis gates
`basis_gates` lists optional primitive gate names used when the simulator decomposes
circuits before attaching noise. If omitted, the backend uses its default primitive set
(commonly single-qubit rotations and one entangling gate type).
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import ClassiqSimulatorNoiseSpecification
ClassiqSimulatorNoiseSpecification(
basis_gates=["id", "rz", "sx", "cx", "x"],
)
```
## Combining channels
You can mix gate and readout channels in one specification. Global readout settings
(`readout_bit_flip_probability` or `readout_assignment_probabilities`) cannot both be set;
per-qubit readout in `local_readout_errors` uses the same matrix convention.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
ClassiqSimulatorNoiseSpecification,
DepolarizingNoiseOnGate,
LocalDepolarizingNoiseOnGate,
LocalReadoutNoise,
PauliNoiseOnGate,
PauliNoiseTerm,
ThermalRelaxationNoiseOnGate,
)
ClassiqSimulatorNoiseSpecification(
basis_gates=["id", "rz", "sx", "cx", "x"],
gate_depolarizing_errors=[
DepolarizingNoiseOnGate(gate="x", probability=0.001, num_qubits=1),
],
local_depolarizing_errors=[
LocalDepolarizingNoiseOnGate(
gate="cx", num_qubits=2, probability=0.02, qubits=[0, 1]
),
],
gate_pauli_errors=[
PauliNoiseOnGate(
gate="h",
num_qubits=1,
pauli_terms=[
PauliNoiseTerm(pauli="I", probability=0.99),
PauliNoiseTerm(pauli="Z", probability=0.01),
],
),
],
gate_thermal_relaxation_errors=[
ThermalRelaxationNoiseOnGate(gate="sx", t1=60_000.0, t2=20_000.0, time=100.0),
],
readout_assignment_probabilities=[[0.98, 0.02], [0.03, 0.97]],
local_readout_errors=[
LocalReadoutNoise(
qubit=0,
assignment_probabilities=[[0.9, 0.1], [0.15, 0.85]],
),
],
)
```
## Validation rules
The SDK validates noise specifications before execution. Common constraints:
| Rule | Applies to |
| -------------------------------------------------------------------------------------------- | ------------------------------------------ |
| `noise_model` and `simulator_noise_spec` are mutually exclusive | `ClassiqBackendPreferences` |
| `readout_bit_flip_probability` and `readout_assignment_probabilities` are mutually exclusive | `ClassiqSimulatorNoiseSpecification` |
| Pauli term probabilities must sum to 1 | `PauliNoiseOnGate` |
| `len(qubits)` must equal `num_qubits` | `LocalDepolarizingNoiseOnGate` |
| $T_2 \leq 2 T_1$ | `ThermalRelaxationNoiseOnGate` |
| Assignment matrices must be 2-by-2, non-negative, row-stochastic | `LocalReadoutNoise`, global readout fields |
For full field-level reference, see
[Simulator noise (SDK reference)](/sdk-reference/providers/simulator-noise).
# Execution on Google Cloud Platform
Source: https://docs.classiq.io/user-guide/execution/cloud-providers/google-backends
Classiq offers execution on a GPU based simulator that is located in the Google Cloud Platform.
This simulator doesn't require an account on GCP.
## Simulator Usage
Execution on this simulator requires specific license permissions.
Before first use, contact [Classiq support](mailto:support@classiq.io).
```python theme={null}
from classiq import GCPBackendPreferences
preferences = GCPBackendPreferences(backend_name="cuquantum")
```
## Supported Backends
Included simulators:
* "cuquantum"
* "cuquantum\_statevector"
# Execution on IBM Quantum Cloud
Source: https://docs.classiq.io/user-guide/execution/cloud-providers/ibm-backends
## Usage
### Execution on IBM Hardware
Execution on IBM hardware requires a valid IBM Quantum Cloud API access token, and access to the requested hardware with an IBM Quantum hub, group, and project name.
The access token is the API token that appears at the top of the [IBM Quantum Cloud page](https://quantum.cloud.ibm.com/), when you are logged in. You must create an account with IBM quantum if you do not have one already.
IBM Backend Preferences configuration options are described in the sections above and in [IBM hardware noise simulation (emulate)](#ibm-hardware-noise-simulation-emulate).
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
IBMBackendPreferences,
)
preferences = IBMBackendPreferences(
backend_name="Name of requsted quantum hardware",
access_token="A Valid API access token to IBM Quantum",
channel="IBM Cloud Channel",
instance_crn="IBM Cloud Instance CRN",
emulate=False,
)
```
## IBM hardware noise simulation (emulate)
Set `emulate=True` on [`IBMBackendPreferences`](/sdk-reference/providers/IBM) to run a simulator with a **Qiskit noise model** inferred from a **real IBM Quantum device** name (for example `ibm_pittsburgh`, `ibm_boston`). You do not pass a separate noise model; `backend_name` must be one of the IBM backends supported for this path in the SDK (see validation errors if the name is not supported).
**Requirements and limitations**
* Use **real** IBM hardware backend names (not `fake_*` simulators); fake backends already run locally and cannot be combined with `emulate=True`.
* With `emulate=True`, execution does not use IBM Quantum hardware; it uses IBM's hardware noise model profile on Classiq's resources.
* Emulation does not require IBM Quantum credentials or an IBM Quantum account.
* Emulation runs on Classiq's execution environment; it does not use IBM Quantum's job queue or wait for IBM hardware availability.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import IBMBackendPreferences
preferences = IBMBackendPreferences(
backend_name="ibm_pittsburgh",
access_token="…",
channel="ibm_cloud",
instance_crn="…",
emulate=True,
)
```
## Supported Backends
Included hardware:
* "ibm\_kingston"
* "ibm\_boston"
* "ibm\_marrakesh"
* "ibm\_torino"
* "ibm\_fez"
* "ibm\_pittsburg"
# Supported Cloud Providers
Source: https://docs.classiq.io/user-guide/execution/cloud-providers/index
Classiq offers integration with multiple cloud providers, to allow seamless
execution of quantum programs on multiple backends.
Some hardware providers may require an appropriate account.
To estimate execution cost before running, see [Cost Estimation](/user-guide/execution/cost-estimation).
* [Classiq](/user-guide/execution/cloud-providers/classiq-backends)
* [Custom noise models (Classiq simulators)](/user-guide/execution/cloud-providers/custom-noise-models)
* [Google](/user-guide/execution/cloud-providers/google-backends)
* [IBM](/user-guide/execution/cloud-providers/ibm-backends)
* [Intel](/user-guide/execution/cloud-providers/intel-backends)
* [Amazon Braket](/user-guide/execution/cloud-providers/amazon-backends)
* [IonQ](/user-guide/execution/cloud-providers/ionq-backends)
* [Azure Quantum](/user-guide/execution/cloud-providers/azure-backends)
* [Alice & Bob](/user-guide/execution/cloud-providers/alice-and-bob-backends)
* [C12](/user-guide/execution/cloud-providers/c12)
## `emulate` by provider
The SDK exposes an `emulate` flag on several backend preference types; **semantics differ by provider**:
| Provider | Doc section |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| IBM Quantum | [IBM hardware noise simulation (emulate)](/user-guide/execution/cloud-providers/ibm-backends#ibm-hardware-noise-simulation-emulate) |
| IonQ (direct API) | [IonQ hardware noise simulation (emulate)](/user-guide/execution/cloud-providers/ionq-backends#ionq-hardware-noise-simulation-emulate) |
| Azure Quantum | [IonQ hardware noise simulation on Azure Quantum (emulate)](/user-guide/execution/cloud-providers/azure-backends#ionq-hardware-noise-simulation-on-azure-quantum-emulate) |
| Amazon Braket | [Device emulation (emulate)](/user-guide/execution/cloud-providers/amazon-backends#device-emulation-emulate) |
# Execution on Intel Backends
Source: https://docs.classiq.io/user-guide/execution/cloud-providers/intel-backends
The Classiq executor supports execution on Intel® simulators.
## Usage
In Classiq's [web platform](https://platform.classiq.io/) simply choose Intel in the checkbox menu under "Execution".
In Classiq's Python SDK, use the following code:
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import IntelBackendPreferences
preferences = IntelBackendPreferences(
backend_name="intel_qsdk_simulator",
)
```
## Citing Intel® Quantum SDK
To cite the Intel® Quantum SDK, please reference:
Khalate, P., Wu, X.-C., Premaratne, S., Hogaboam, J., Holmes, A., Schmitz, A., Guerreschi, G. G., Zou, X. & Matsuura, A. Y., arXiv:2202.11142 (2022).
## Supported Backends
Included simulators:
* "intel\_qsdk\_simulator"
# Execution on IonQ Quantum Cloud
Source: https://docs.classiq.io/user-guide/execution/cloud-providers/ionq-backends
The Classiq executor supports execution on IonQ hardware and simulator.
## Usage
Execution on IonQ requires a valid IonQ API key.
IonQ Backend Preferences configuration options are summarized below; see [IonQ hardware noise simulation (emulate)](#ionq-hardware-noise-simulation-emulate) for the `emulate` flag.
* **Error mitigation:** `bool` — valid for IonQ hardware; defaults to `False`.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import IonqBackendPreferences
preferences = IonqBackendPreferences(
backend_name="qpu.forte-1",
api_key="A Valid IonQ API key",
error_mitigation=True,
emulate=False,
)
```
## IonQ hardware noise simulation (emulate)
Set `emulate=True` on [`IonqBackendPreferences`](/sdk-reference/providers/IonQ) to run on the **IonQ cloud simulator** while applying a **hardware noise profile** derived from your **QPU** backend name (for example `qpu.forte-1` → noise model `forte-1`). Classiq resolves the simulator backend and passes the appropriate run options to the IonQ provider.
**Requirements**
* `backend_name` must be a **QPU** id (prefix `qpu.`, e.g. `qpu.aria-2`, `qpu.forte-1`). If `emulate=True` with a non-QPU backend name, preferences validation fails.
**Usage**
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import IonqBackendPreferences
preferences = IonqBackendPreferences(
backend_name="qpu.forte-1",
api_key="…",
error_mitigation=False,
emulate=True,
)
```
## Supported Backends
Included hardware:
* "qpu.aria-2"
* "qpu.forte-1"
* "qpu.forte-enterprise-1"
* "qpu.forte-enterprise-2"
Included simulators:
* "simulator"
# Cost Estimation
Source: https://docs.classiq.io/user-guide/execution/cost-estimation
Before executing a quantum program, you can estimate the cost using `estimate_sample_cost` and `estimate_sample_batch_cost`. These functions return a `CostEstimateResult` with `cost` (in USD) and `currency` fields.
Cost estimation is supported for all quantum providers that Classiq integrates with. Each provider uses its own pricing model.
## Basic Usage
### Single Sample Cost
Use `estimate_sample_cost` to estimate the cost of sampling a quantum program with given execution preferences:
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
ClassiqBackendPreferences,
ClassiqSimulatorBackendNames,
ExecutionPreferences,
create_model,
estimate_sample_cost,
synthesize,
)
from classiq.qmod.builtins.operations import allocate
from classiq.qmod.qfunc import qfunc
from classiq.qmod.qmod_variable import Output, QBit
@qfunc
def main(res: Output[QBit]) -> None:
allocate(1, res)
qmod = create_model(main)
qprog = synthesize(qmod)
execution_preferences = ExecutionPreferences(
num_shots=100,
backend_preferences=ClassiqBackendPreferences(
backend_name=ClassiqSimulatorBackendNames.SIMULATOR
),
)
result = estimate_sample_cost(qprog, execution_preferences)
print(f"Estimated cost: {result.cost} {result.currency}")
```
### Batch Cost Estimation
Use `estimate_sample_batch_cost` to estimate the cost of sampling with multiple parameter sets:
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
ClassiqBackendPreferences,
ClassiqSimulatorBackendNames,
estimate_sample_batch_cost,
synthesize,
)
qprog = synthesize(qmod)
result = estimate_sample_batch_cost(
qprog,
execution_backend=ClassiqBackendPreferences(
backend_name=ClassiqSimulatorBackendNames.SIMULATOR
),
shots=100,
params=[{}, {}], # Two parameter sets
)
print(f"Estimated batch cost: {result.cost} {result.currency}")
```
## Provider-Specific Usage
Cost estimation works with the same backend preferences you use for execution. Configure the backend for your target provider and pass it to the estimation functions.
### Classiq Simulators
Classiq simulators support cost estimation without provider credentials.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
ClassiqBackendPreferences,
ClassiqSimulatorBackendNames,
ExecutionPreferences,
estimate_sample_cost,
)
# All Classiq simulators are supported
backends = [
ClassiqSimulatorBackendNames.SIMULATOR,
ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR,
ClassiqSimulatorBackendNames.SIMULATOR_DENSITY_MATRIX,
ClassiqSimulatorBackendNames.SIMULATOR_MATRIX_PRODUCT_STATE,
]
for backend_name in backends:
prefs = ExecutionPreferences(
num_shots=100,
backend_preferences=ClassiqBackendPreferences(backend_name=backend_name),
)
result = estimate_sample_cost(qprog, prefs)
print(f"{backend_name}: {result.cost} {result.currency}")
```
### Amazon Braket
Cost estimation supports both Braket simulators (SV1, TN1, dm1) and QPUs (e.g., Aspen-11, Lucy).
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
AwsBackendPreferences,
ExecutionPreferences,
estimate_sample_cost,
)
# Braket simulators
prefs = ExecutionPreferences(
num_shots=100,
backend_preferences=AwsBackendPreferences(
backend_name="SV1",
run_via_classiq=True,
),
)
result = estimate_sample_cost(qprog, prefs)
# Braket QPU (e.g., Ankaa-3)
prefs_qpu = ExecutionPreferences(
num_shots=1000,
backend_preferences=AwsBackendPreferences(
backend_name="Ankaa-3",
run_via_classiq=True,
),
)
result_qpu = estimate_sample_cost(qprog, prefs_qpu)
```
When using your own AWS credentials, omit `run_via_classiq` and provide `aws_access_key_id`, `aws_secret_access_key`, `s3_bucket_name`, and `s3_folder`.
### IonQ
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
IonqBackendPreferences,
ExecutionPreferences,
estimate_sample_cost,
)
# IonQ simulator
prefs = ExecutionPreferences(
num_shots=100,
backend_preferences=IonqBackendPreferences(
backend_name="simulator",
run_via_classiq=True,
),
)
result = estimate_sample_cost(qprog, prefs)
# IonQ QPU (e.g., Forte-1)
prefs_qpu = ExecutionPreferences(
num_shots=1000,
backend_preferences=IonqBackendPreferences(
backend_name="qpu.Forte-1",
run_via_classiq=True,
),
)
result_qpu = estimate_sample_cost(qprog, prefs_qpu)
```
### Azure Quantum
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
AzureBackendPreferences,
ExecutionPreferences,
estimate_sample_cost,
)
# Azure IonQ simulator
prefs = ExecutionPreferences(
num_shots=100,
backend_preferences=AzureBackendPreferences(
backend_name="ionq.simulator",
),
)
result = estimate_sample_cost(qprog, prefs)
# Azure Quantinuum simulator
prefs_quantinuum = ExecutionPreferences(
num_shots=100,
backend_preferences=AzureBackendPreferences(
backend_name="quantinuum.sim.h1-1e",
),
)
result_quantinuum = estimate_sample_cost(qprog, prefs_quantinuum)
```
When using `run_via_classiq`, omit `credentials`. Otherwise, provide Azure credentials.
## Summary by Provider
| Provider | Backend examples |
| ----------------- | ------------------------------------------------------------------------------------------------ |
| **Classiq** | simulator, simulator\_statevector, simulator\_density\_matrix, simulator\_matrix\_product\_state |
| **Amazon Braket** | SV1, TN1, dm1 (simulators); Aspen-11, Lucy (QPUs) |
| **IonQ** | simulator, qpu.aria-1, qpu.forte-1 |
| **Azure** | ionq.simulator, quantinuum.sim.h1-1e, rigetti.sim.qvm |
Use `run_via_classiq=True` when available to estimate costs without providing provider credentials. Your allocated budget is used for execution.
## API Reference
See the [execution SDK reference](/sdk-reference/execution) for full details on `estimate_sample_cost`, `estimate_sample_batch_cost`, and `CostEstimateResult`.
# CUDA-Q Integration
Source: https://docs.classiq.io/user-guide/execution/cudaq_integration
## Overview
The Classiq–CUDA-Q integration enables users to design quantum algorithms at a high level using Classiq, while leveraging CUDA-Q for execution, simulation, and hybrid quantum–classical workflows.
This integration is particularly well suited for variational algorithms, such as QAOA, where circuit synthesis, parameterized execution, and classical optimization must work together efficiently.
## Prerequisites
Before using the integration, ensure the following are installed in your python environment:
* Python 3.9 or later
* Classiq SDK
* CUDA-Q
Note: The integration is only supported on Linux. The simplest way to handle installations is to use [Classiq Studio](https://platform.classiq.io/studio/) and `pip install classiq[cudaq]`.
## Integration Core Functions
The Integration is built around two Classiq SDK helper functions:
* `qprog_to_cudaq_kernel()`\
Converts a synthesized Classiq quantum program (`qprog`) into a CUDA-Q kernel that can be executed using CUDA-Q SDK.
The default kernel type is a main kernel, which is compatible with CUDA-Q execution functions and key capabilities.
In case that the kernel is meant to be added as a component to another main kernel, use `is_main_kernel=False` so that it can be passed as a parameter to `apply_call`
(for example: `other_kernel.apply_call(your_kernel)`).
* `pauli_operator_to_cudaq_spin_op()`\
Transforms Qmod's `SparsePauliOp` data structure to CUDA-Q's `SpinOperator`.
## Usage Example
Here is a minimal example:
* Defining and synthesizing a parametric model using Classiq.
* Converting to CUDA-Q kernel, assigning value to the parameter and sampling.
[comment]: DO_NOT_TEST
```python theme={null}
# ! pip install classiq[cudaq]
from classiq import *
import cudaq
import math
@qfunc
def main(theta: CReal, q: Output[QBit]):
allocate(q)
RX(theta, q)
qprog = synthesize(main)
my_kernel = qprog_to_cudaq_kernel(qprog)
counts = cudaq.sample(my_kernel, math.pi / 3)
print(counts)
# example outputs -
# { 0:753 1:247 }
```
# Execution
Source: https://docs.classiq.io/user-guide/execution/index
Classiq lets you execute quantum programs on a variety of backends, including simulators and real quantum hardware.
Execution operates on synthesized `QuantumProgram` (see [Quantum Program Synthesis](/user-guide/synthesis/index)) and, for sampling, also OpenQASM 2.0 or 3.0.
Once you have defined the format of input for execution,
you can run it using a set of high-level APIs designed to be consistent and easy to use.
## Quick workflow
Execution typically consists of four steps:
1. Choose the execution function based on the desired result type:
* `sample(...)` for shot-based measurement results
* `calculate_state_vector(...)` for amplitudes and basis-state information
* `observe(...)` for expectation values
2. Choose a backend
Use `get_backend_details()` to inspect the available providers and devices.
Not all result types are available on all backends. For example, state vector results cannot be obtained from QPUs.
3. Pass execution settings in one place
Use `config=` for provider-specific configuration, together with common execution arguments such as `num_shots`, `random_seed`, and `transpilation_option`.
4. Inspect the returned result
* `sample(...)` returns a DataFrame
* `calculate_state_vector(...)` returns a DataFrame
* `observe(...)` returns a scalar
* If `parameters` is a list, the returned value is a list of results of the corresponding type
## Step 1 — Choose the type of result you want
Before running your program, it is important to decide what kind of information you want to extract.
There are three common execution functions:
| Function | When to use | Output |
| ------------------------ | ------------------------------- | --------- |
| `sample` | You want measurement statistics | DataFrame |
| `calculate_state_vector` | You want amplitudes and phases | DataFrame |
| `observe` | You want an expectation value | float |
Each function exposes a different level of information about your quantum program:
* Use [sample](./sample) when you want to see the outcomes that would be obtained by measuring the circuit many times.
* Use [calculate\_state\_vector](./calculate-state-vector) when you want the full quantum state, including amplitudes and phases.
* Use [observe](./observe) when you want to evaluate an observable and obtain a single expectation value.
For a detailed walkthrough of each function, continue to the relevant page:
[Sampling](./sample)
[State vectors](./calculate-state-vector)
[Expectation values](./observe)
## Step 2 — Inspect available backends
Before executing, you should inspect which backends are available.
```python theme={null}
from classiq import *
backends = get_backend_details()
backends
```
This returns a table containing:
* provider (e.g., classiq, azure, braket)
* backend (device name)
* type (simulator / hardware)
* num\_qubits
* is\_available
* queue\_time
## Provider-specific configuration
All execution functions ([sample](./sample), [observe](./observe), and [calculate\_state\_vector](./calculate-state-vector)) accept
a config argument that allows you to pass provider-specific configuration.
This is the main mechanism for customizing how your program is executed on a given backend.
### When to use config
Use config when you need to:
* Provide authentication details (e.g., API keys or credentials)
* Configure execution settings specific to a provider
* Enable features such as noise models on simulators
* Control advanced backend behavior that is not exposed through the common execution arguments
### Basic usage
The config argument can be passed as either:
* A plain Python dictionary, or
* a provider-specific configuration object (for example, IBMConfig, BraketConfig, etc.)
In the following examples, we enable `emulate` on an Azure backend to enable IonQ hardware noise simulation in
two different ways: First, using config as a dict, and then using config as a provider-specific object.
**Example: Using config as a dict**
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import *
backend_name = "azure/ionq.simulator"
azure_config = {"emulate": True}
@qfunc
def main(x: Output[QBit]):
allocate(x)
H(x)
qprog = synthesize(main)
res = sample(qprog,
backend=backend_name,
num_shots=1000,
config = azure_config,
run_via_classiq= True)
```
**Example: Using config as a provider-specific object**
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import *
backend_name = "azure/ionq.simulator"
azure_preferences = AzureBackendPreferences(
emulate = True
)
@qfunc
def main(x: Output[QBit]):
allocate(x)
H(x)
qprog = synthesize(main)
res = sample(qprog,
backend=backend_name,
num_shots=1000,
config = azure_preferences,
run_via_classiq= True)
```
## Key takeaways
* Execution always follows the same pattern:
1. Choose result type
2. Choose backend
3. Configure in one place
4. Analyze result
* Data is returned in ready-to-use structures
* DataFrames for sampling and state vector
* Scalars for observables
* Batch execution is automatic when passing a list of parameters
# Observe
Source: https://docs.classiq.io/user-guide/execution/observe
The `observe(...)` workflow is used when you want the expectation value of an observable rather than a full measurement distribution or the complete state vector.
Related pages:
* [Execution overview](./index)
* [Sampling](./sample)
* [State vectors](./calculate-state-vector)
## When to use observe
Use `observe(...)` when your goal is to compute the expectation value of an observable with respect to the executed quantum state.
**This is especially useful in workflows such as:**
* variational algorithms
* optimization loops
* cost-function evaluation
* repeated evaluation of the same circuit under different parameter values
Unlike sampling, which returns a distribution of measurement outcomes, `observe(...)` returns a single scalar. Unlike state-vector calculation, it does not expose the full quantum state.
## Basic example
```python theme={null}
from classiq import *
backend_name = "simulator"
@qfunc
def main(res: Output[QBit]) -> None:
allocate(res)
H(res)
qprog = synthesize(main)
#Define your observable using SparsePauliOp
my_observable = Pauli.Z(0) - Pauli.Y(0)
value = observe(
qprog,
observable=my_observable,
backend=backend_name,
num_shots=1000,
)
value
```
**Output:**
-0.013999999999999999
### Understanding the result
The returned value is a single scalar.
It represents the expectation value of the observable with respect to the state produced by the circuit.
In other words, it summarizes the behavior of the circuit relative to the operator you are interested in.
This is useful when you care about one derived quantity rather than the full result space.
### Choosing execution settings
As with the other execution functions, you can configure the execution using standard arguments such as:
* backend
* config
* num\_shots
* random\_seed
* parameters
For example:
[comment]: DO_NOT_TEST
```python theme={null}
value = observe(
qprog,
observable=my_observable,
backend=backend_name,
config={},
num_shots=2000,
random_seed=42,
)
```
## Parameterized execution
Many practical uses of `observe(...)` involve parameterized circuits.
Instead of fixing all values inside the circuit, you define symbolic parameters in the
quantum function and provide their values when you execute the program.
### Defining a parameterized quantum program
```python theme={null}
from classiq import *
backend_name = "simulator"
@qfunc
def main(angle_rx: CReal, angle_ry: CReal, x: Output[QBit]):
allocate(x)
RX(angle_rx, x)
H(x)
RY(angle_ry, x)
qprog = synthesize(main)
```
### Supplying parameter values
[comment]: DO_NOT_TEST
```python theme={null}
exec_params = {
"angle_rx": 0.5,
"angle_ry": 0.3
}
value = observe(
qprog,
observable=my_observable,
backend=backend_name,
parameters=exec_params,
num_shots=1000,
)
value
```
**Output:**
-0.748
This allows you to evaluate how the expectation value changes as the circuit parameters change.
# Batch of expectation values
A common pattern is to evaluate the same observable for many parameter settings.
Instead of calling `observe(...)` repeatedly, you can pass a list of parameter dictionaries.
The function then returns a list of scalar values, one per parameter set.
**Example**
[comment]: DO_NOT_TEST
```python theme={null}
rx_angles = [0.1, 0.2, 0.3, 0.4]
exec_params = [
{"angle_rx": angle, "angle_ry": 0.3}
for angle in rx_angles
]
values = observe(
qprog,
observable=my_observable,
backend=backend_name,
parameters=exec_params,
num_shots=1000,
)
values
```
**Output:**
\[-0.396, -0.526, -0.6100000000000001, -0.642]
### Understanding batch results
When `parameters` is a list:
* the output is a list of scalar values
* each value corresponds to one execution
* the order matches the order of the provided parameter dictionaries
This makes `observe(...)` a natural fit for optimization and sweep-style workflows, where you want to evaluate the same quantity many times.
## Summary
Use `observe(...)` when you care about the expectation value of an observable.
Observe:
* returns a scalar
* is ideal for cost functions and iterative algorithms
* supports both single and batch parameterized execution
# Sample
Source: https://docs.classiq.io/user-guide/execution/sample
Sampling is the most common execution workflow. It is used when you want to simulate or run
measurements and inspect the resulting bitstring distribution.
Related pages:
* [Execution overview](./index)
* [Observe](./observe)
* [State vectors](./calculate-state-vector)
## When to use sampling
Use `sample(...)` when you want to perform measurements. This method is typically used to
understand the probability distribution over measurement outcomes.
**Sampling is a good choice when:**
* you want to inspect measured bitstrings
* you want counts and probabilities
* you want to compare outputs across different parameter values
* you want behavior that resembles repeated measurements on a quantum device
Unlike state-vector calculation, sampling does not return the full internal quantum state.
Instead, it returns the measurement statistics that result from executing the circuit multiple times.
The `sample` function accepts these arguments:
| Argument | Description |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `qprog` | A synthesized `QuantumProgram`, or a string containing **OpenQASM 2.0 or 3.0** source (see [Sampling OpenQASM](#sampling-openqasm)). |
| `backend` | Backend specifier as `"provider/backend"`. Defaults to `"simulator"`. |
| `parameters` | A dict of parameter values, or a list of dicts for batch execution. Keys are parameter names of the main function. **Not supported** when `qprog` is an OpenQASM string. |
| `config` | Provider-specific configuration (API keys, etc.). Accepts a `dict` or a typed config object (e.g. `IBMConfig`, `BraketConfig`). |
| `num_shots` | Number of shots. Must be ≥ 1 if specified. |
| `random_seed` | Seed for transpilation and simulation. |
| `transpilation_option` | Transpilation level. See [`TranspilationOption`](/user-guide/synthesis/quantum-program-transpilation#transpilation-options). |
| `run_via_classiq` | Run using Classiq's provider credentials against your allocated budget. Defaults to `False`. |
## Basic examples
```python theme={null}
from classiq import *
backend_name = "simulator"
@qfunc
def main(res: Output[QBit]) -> None:
allocate(res)
H(res)
qprog = synthesize(main)
df = sample(
qprog,
backend=backend_name,
num_shots=1000,
)
df
```
| x | counts | probability | bitstring |
| - | ------ | ----------- | --------- |
| 1 | 502 | 0.502 | 1 |
| 0 | 498 | 0.498 | 0 |
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import *
backend_name = "ibm/fez"
@qfunc
def main(x: Output[QNum[2, UNSIGNED, 0]], y:Output[QArray[QBit]], res: Output[QBit]) -> None:
allocate(3, y)
allocate(res)
prepare_state([0.5, 0, 0, 0.5], 0.0, x)
H(y[1])
H(res)
qprog = synthesize(main)
df = sample(
qprog,
backend=backend_name,
num_shots=1000,
run_via_classiq=True,
)
df
```
| x | y | res | counts | probability | bitstring |
| - | ---------- | --- | ------ | ----------- | --------- |
| 0 | \[0, 0, 0] | 1 | 136 | 0.136 | 100000 |
| 3 | \[0, 0, 0] | 0 | 132 | 0.132 | 000011 |
| 0 | \[0, 0, 0] | 0 | 126 | 0.126 | 000000 |
| 0 | \[0, 1, 0] | 1 | 126 | 0.126 | 101000 |
| 3 | \[0, 1, 0] | 1 | 124 | 0.124 | 101011 |
| 3 | \[0, 1, 0] | 0 | 120 | 0.120 | 001011 |
| 0 | \[0, 1, 0] | 0 | 119 | 0.119 | 001000 |
| 3 | \[0, 0, 0] | 1 | 117 | 0.117 | 100011 |
### Understanding the result
The returned object is a DataFrame, which makes it easy to analyze using familiar tools.
**Common columns are:**
* **quantum variables** - the quantum number values, quantum arrays, and qubits values measured
* **bitstring** — the measured computational basis state
* **counts** — how many times this result was observed
* **probability** — normalized frequency
## Choosing execution settings
Sampling accepts the same common execution settings used by other high-level execution APIs.
For example:
[comment]: DO_NOT_TEST
```python theme={null}
df = sample(
qprog,
backend=backend_name,
config={},
num_shots=2000,
random_seed=42,
)
```
**A few important arguments are:**
* `backend` — the backend on which the program will run
* `config` — provider-specific configuration
* `num_shots` — how many times to execute the circuit
* `random_seed` — useful for reproducibility
* `parameters` — values for parameterized quantum programs
In most introductory workflows, using the default simulator with a chosen number of shots is enough.
## Parameterized Execution
Many quantum programs are parameterized. Instead of hardcoding values directly into the circuit,
you define them as inputs to your quantum function and provide their values at execution time.
**This is useful for:**
* variational algorithms
* parameter sweeps
* repeated evaluation of the same circuit structure with different values
Execution of parameterized OpenQASM is not supported.
### Defining a parameterized quantum program
```python theme={null}
from classiq import *
backend_name = "simulator"
@qfunc
def main(angle_rx: CReal, angle_ry: CReal, x: Output[QBit]):
allocate(x)
RX(angle_rx, x)
H(x)
RY(angle_ry, x)
qprog = synthesize(main)
```
**In this example:**
* `angle_rx` and `angle_ry` are symbolic parameters
* the structure of the quantum program is fixed
* the actual numerical values are supplied during execution
### Supplying parameter values
To execute the parameterized program, pass a dictionary to `parameters`:
[comment]: DO_NOT_TEST
```python theme={null}
exec_params = {
"angle_rx": 0.5,
"angle_ry": 0.3
}
df = sample(
qprog,
backend=backend_name,
parameters=exec_params,
num_shots=1000,
)
df
```
Each key in the dictionary must match a parameter name in the quantum function.
**Example output:**
| x | counts | probability | bitstring |
| - | ------ | ----------- | --------- |
| 1 | 642 | 0.642 | 1 |
| 0 | 358 | 0.358 | 0 |
This means the parameter values are first bound to the quantum program, and the resulting instantiated circuit is then sampled.
## Batch sampling
Often, you want to evaluate the same circuit for multiple parameter values.
Instead of calling `sample(...)` repeatedly in a loop, you can pass a list of parameter dictionaries.
In that case, the function performs one execution per parameter set and returns a list of DataFrames.
### Example
[comment]: DO_NOT_TEST
```python theme={null}
rx_angles = [0.1, 0.2, 0.3, 0.4]
exec_params = [
{"angle_rx": angle, "angle_ry": 0.3}
for angle in rx_angles
]
results = sample(
qprog,
backend=backend_name,
parameters=exec_params,
num_shots=1000,
)
results[1]
```
| x | counts | probability | bitstring |
| - | ------ | ----------- | --------- |
| 1 | 639 | 0.639 | 1 |
| 0 | 361 | 0.361 | 0 |
### Understanding batch results
**When parameters is a list:**
* the output is a list of DataFrames
* each DataFrame corresponds to one execution
* the order of the outputs matches the order of the parameter dictionaries you passed in
This is convenient when scanning over parameters and comparing how the sampled distribution changes.
## Sampling OpenQASM
You can pass **OpenQASM 2.0 or 3.0** text as the first argument to `sample` instead of a `QuantumProgram`. The backend runs the circuit the same way as for a synthesized program; the returned DataFrame still includes `bitstring`, `counts`, and related columns.
OpenQASM from anytool is supported as long as you pass a string, for example:
[comment]: DO_NOT_TEST
```python theme={null}
from qiskit import QuantumCircuit, qasm2
from classiq.execution import sample
qc = QuantumCircuit(1)
qc.h(0)
openqasm = qasm2.dumps(qc)
df = sample(openqasm, backend="simulator", num_shots=500)
```
Hand-written OpenQASM 3 is also valid:
[comment]: DO_NOT_TEST
```python theme={null}
from classiq.execution import sample
openqasm = """
OPENQASM 3;
include "stdgates.inc";
qubit[1] q;
h q[0];
"""
df = sample(openqasm, backend="simulator", num_shots=500)
```
Limitations when using a string:
* Do not pass `parameters` for OpenQASM strings; use a `QuantumProgram` if you need Qmod `main` parameters, or express parameters inside the QASM (e.g. Qiskit `Parameter` and `assign_parameters` before dumping).
* Batch sampling with a list of parameter dicts is only defined for `QuantumProgram` execution.
## Summary
Use sampling when your goal is to understand measurement outcomes rather than the full state or a single expectation value.
**Sampling:**
* returns a DataFrame
* is well suited for measured distributions
* supports both single and batch parameterized execution
# State Vector Filtering
Source: https://docs.classiq.io/user-guide/execution/state-vector-filtering
Before measurement, a quantum circuit creates a state which can be described
as a vector of $2^n$ amplitudes, where $n$ is the number of qubits. Though this
state vector cannot be directly accessed on a quantum computer (as measurement
destroys the state), certain quantum simulators make this information available.
Classiq supports two simulators which return the full statevector, both under
the Classiq provider: `simulator_statevector` and `nvidia_simulator_statevector`.
Since the data size grows exponentially, large circuits cannot be simulated.
However, in certain applications such as those that use block encoding, not all
of the $2^n$ amplitudes are of interest. For example, some methods of
post-processing discard certain results wholesale, and thus the amplitudes
corresponding to those measured states are irrelevant.
In these instances, filtering out the amplitudes that are not of interest can
greatly save memory. Use the method
`ExecutionSession.set_measured_state_filter`, to specify the execution output
values of interest.
## Example
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QBit], y: Output[QNum], z: Output[QNum]) -> None:
allocate(1, x)
hadamard_transform(x)
prepare_state(probabilities=[0.5, 0, 0.25, 0.25], bound=0.01, out=y)
z |= y + 1
quantum_program = synthesize(main)
execution_preferences = ExecutionPreferences(
backend_preferences=ClassiqBackendPreferences(
backend_name=ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR
)
)
with ExecutionSession(
quantum_program, execution_preferences=execution_preferences
) as session:
session.set_measured_state_filter("x", lambda state: state == 1)
session.set_measured_state_filter("y", lambda state: state == 2)
results = session.sample()
```
Filtering ensures that `results` will contain only the amplitudes that correspond
to states where x is 1 and y is 2.
## Amplitude Threshold
By default, state vector simulation filters out states with exactly zero amplitude from the result. You can tighten this filter by setting `amplitude_threshold` in `ExecutionPreferences` to exclude states whose amplitude magnitude is below a given threshold:
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QNum]) -> None:
prepare_state(probabilities=[0.5, 0, 0.25, 0.25], bound=0.01, out=x)
quantum_program = synthesize(main)
execution_preferences = ExecutionPreferences(
backend_preferences=ClassiqBackendPreferences(
backend_name=ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR
),
amplitude_threshold=1e-4,
)
with ExecutionSession(
quantum_program, execution_preferences=execution_preferences
) as session:
results = session.sample()
```
States with `|amplitude| <= amplitude_threshold` are excluded from `results`. This reduces the size of the result for circuits where most amplitudes are negligibly small (e.g. block-encoded circuits).
Setting `include_zero_amplitude_outputs=True` overrides `amplitude_threshold` and includes all states regardless of amplitude.
Filtering removes states from the returned state vector. As a result, the remaining amplitudes will not sum to a norm of 1. Do not rely on the filtered state vector being normalized.
## Limitations
Currently, filtering is only available on Classiq's `simulator_statevector`
(`ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR`) and
`nvidia_simulator_statevector` (`ClassiqNvidiaBackendNames.SIMULATOR_STATEVECTOR`).
Filtering is only available for quantum scalars (`QuantumBit`s and `QuantumNumeric`s).
Additionally, only a single value per variable is supported. For example,
`session.set_measured_state_filter("x", lambda x: x < 5)` is not allowed.
# User Guide
Source: https://docs.classiq.io/user-guide/index
Welcome to the User Guide!
This section guides you through all the key features and functionalities of the platform.
# Controlled Operations
Source: https://docs.classiq.io/user-guide/modeling/controlled-operations
## Introduction
Controlled operations are one of the main ways quantum programs apply operations depending on the state of quantum variables. In classical programming,
an `if` statement chooses which instructions run based on a classical Boolean value. In quantum programming, the analogous idea is more subtle: the
condition may itself be quantum, meaning it may be in superposition.
In Qmod, controlled quantum behavior is expressed using the `control` statement. The statement applies a unitary operation conditionally,
depending on a quantum state, and may optionally apply a different operation if the condition does not hold. The condition can be given
either as a single qubit or qubit array, or as a quantum Boolean expression over quantum variables. When the control variable is in
superposition, the controlled operation entangles the objects used in the controlled block with the condition.
In this guide, we cover:
* **Controlled operations**: applying quantum operations only on states that satisfy a quantum condition.
* **Else blocks**: applying one operation when the condition is true and another when it is false.
* **Operations controlled by expressions**: using Boolean expressions over quantum variables as control conditions.
## Controlled operations
A controlled operation applies a quantum operation subject to a condition satisfied by the quantum state.
The simplest case is control by a single qubit. If the control qubit is in state $\vert 1 \rangle$, the operation
is applied to the target. If the control qubit is in state $\vert 0 \rangle$, the operation is not applied.
In Qmod, this is written with `control`:
```python theme={null}
from classiq import *
@qfunc
def main(ctrl: Output[QBit], target: Output[QBit]):
allocate(ctrl)
allocate(target)
H(ctrl)
control(ctrl, lambda: Y(target))
```
In the Python SDK, the controlled statement block is passed as a Python callable, commonly written using `lambda`.
This quantum program:
* Allocates a control qubit `ctrl` and a target qubit `target`.
* Applies the Hadamard gate, $H$, to `ctrl`, creating the superposition $\vert \text{ctrl} \rangle = \frac{1}{\sqrt{2}}\left( \vert 0 \rangle + \vert 1 \rangle\right)$.
* Applies the Pauli-Y gate to `target` conditioned on `ctrl == 1`.
* The resulting state is $\frac{1}{\sqrt{2}}\left( \vert 00 \rangle + i\vert 11 \rangle\right),$ where the first qubit is `ctrl` and the second is `target`.
This means that the target is flipped only in the part of the state where the control qubit is 1. Since the control qubit is in superposition,
the result is an entangled state rather than a classical branch selection. This is the same control mechanism underlying gates such as CY, but
Qmod generalizes it to arbitrary statement blocks and quantum expressions.
The `control` statement applies quantum operations coherently. It should not be interpreted as measuring the condition and then choosing a branch.
### Multi-qubit control
The control variable can also be a quantum array. In that case, the controlled block is applied only when all qubits in the control array are in state $\vert 1 \rangle$.
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
@qfunc
def main(ctrl: Output[QArray[QBit]], target: Output[QArray[QBit]]):
allocate(3, ctrl)
allocate(4, target)
hadamard_transform(ctrl)
control(ctrl, lambda: qft(target))
```
This quantum program:
* Allocates a 3-qubit control array.
* Puts the control array into a uniform superposition over all 3-bit strings.
* Applies a Quantum Fourier Transform to `target` only on the basis state `ctrl == 111`.
Because the control array is in superposition, the QFT is applied only to the component corresponding to `ctrl == 111`.
## Else blocks
A control statement may include an `else_block`. The main block is applied for states where the condition is true, and the else block is applied for states where the condition is false.
When the condition is a qubit array, the condition holds only when all qubits in the control array are in state $\vert 1 \rangle$; otherwise, the else block applies.
```python theme={null}
from classiq import *
@qfunc
def main(ctrl: Output[QBit], target: Output[QBit]):
allocate(ctrl)
allocate(target)
H(ctrl)
control(
ctrl,
lambda: X(target),
lambda: H(target),
)
```
This quantum program:
* Allocates `ctrl` and `target`.
* Puts `ctrl` in superposition.
* Applies the Pauli-X gate to `target` on the branch where `ctrl == 1`.
* Applies Hadamard gate (H) to `target` on the branch where `ctrl == 0`.
This is analogous to the following classical structure:
[comment]: DO_NOT_TEST
```python theme={null}
if ctrl:
X(target)
else:
H(target)
```
However, the quantum version is not a classical branching. If `ctrl` is in superposition, both branches are applied coherently to the corresponding parts
of the quantum state.
### Example: choosing between two rotations
The next example uses an else block to apply one rotation when a control qubit is 1 and a different rotation when it is 0.
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
@qfunc
def main(ctrl: Output[QBit], target: Output[QBit]):
allocate(ctrl)
allocate(target)
H(ctrl)
control(
ctrl,
lambda: RX(pi / 2, target),
lambda: RX(pi / 3, target),
)
```
Whose outputs are closer to:
| ctrl | target | counts | probability | bitstring |
| ---- | ------ | ------ | ----------- | --------- |
| 1 | 0 | 749 | 0.245117 | 01 |
| 0 | 0 | 749 | 0.365723 | 00 |
| 0 | 1 | 502 | 0.128906 | 10 |
| 1 | 1 | 533 | 0.260254 | 11 |
This program creates a state in which the target qubit is rotated differently depending on the value of `ctrl`. Since `ctrl` is in superposition,
the two rotations are applied to different components of the full quantum state.
A `control` statement, like other control-flow statements such as `if_`, `repeat`, `foreach`, and `power`, must preserve the initialization status
of variables declared outside its blocks. A variable declared outside the controlled block may be allocated inside the block only if it is also
released within that same block. Similarly, variables declared inside a controlled block must be uninitialized by the end of that block.
## Operations controlled by expressions
In Qmod, a control condition may also be a quantum logical expression over quantum variables. Expressions over quantum variables evaluate coherently
over superpositions, producing correlated quantum values rather than a single classical value.
Qmod supports arithmetic operators such as +, -, \*, \*\*, relational operators such as `==`, `!=`, `<`, `<=`, `>`, `>=`, and logical operators such as
`logical_and`/`&`, `logical_or`/`|`, and `logical_not`/ `~` for Boolean expressions.
### Example: Uniformly controlled rotations
The following example applies a sequence of multi-controlled rotations
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
num_qubits = 2
max_iterations = 2**num_qubits
min_angle = pi/max_iterations
@qfunc
def main(x: Output[QNum], target: Output[QBit]):
allocate(num_qubits, x)
allocate(target)
hadamard_transform(x)
repeat(max_iterations,
lambda i: control( x == i,
lambda: RX(min_angle * i, target)))
```
This quantum program:
* Allocates `x` as a 2-qubit quantum number.
* Places `x` in a superposition over the values $\{0, 1, 2, 3\}$.
* Applies a RX rotation with angle dependent on the numeric value of x.
This can be interpreted as:
| x value | Operation on target |
| ------- | ------------------- |
| 0 | No rotation |
| 1 | $RX(\pi / 4)$ |
| 2 | $RX(\pi / 2)$ |
| 3 | $RX(3\pi / 4)$ |
The target qubit becomes entangled with `x`, because only different rotations occur depending on the values of `x`.
### Example: Arithmetic condition
Control expressions can involve arithmetic over multiple quantum variables.
This is useful in search, optimization, and oracle construction, where a state should be marked or modified only if it satisfies a predicate.
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
@qfunc
def main(x: Output[QNum[2]], y: Output[QNum[2]], target: Output[QBit]):
allocate(x)
allocate(y)
allocate(target)
hadamard_transform(x)
hadamard_transform(y)
control(x + y >= 5, lambda: X(target))
```
This program:
* Allocates two 2-qubit quantum numbers, `x` and `y`.
* Places both in uniform superposition.
* Flips `target` only for basis states satisfying `x + y >= 5`
The satisfying assignments are:
| x | y |
| - | - |
| 2 | 3 |
| 3 | 2 |
| 3 | 3 |
After the controlled operation, the target qubit is entangled with the predicate `x + y >= 5`. If `target` is later measured as 1,
the variables `x` and `y` collapse to the subspace of satisfying assignments.
This style is useful for expressing predicates directly in terms of problem variables, without manually decomposing the condition into lower-level gates.
### Example: Controlled phase
A common use of controlled operations is to apply a phase only to selected states. This is central in algorithms such as Grover search,
phase oracles, QAOA, and Hamiltonian-inspired constructions.
The `phase` statement applies a fixed or state-dependent phase shift to the quantum state. For example, phase(x**2, pi / 4)
applies a phase proportional to the value of x**2. When `x` is initialized over the values 0, 1, 2, and 3, the phase statement rotates each
basis state according to the expression value.
A controlled phase applies such a phase only under a control condition.
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
@qfunc
def main(q: Output[QArray[QBit, 2]]):
allocate(q)
hadamard_transform(q)
control(q[0], lambda: phase(pi / 4))
```
This quantum program:
* Allocates two qubits.
* Places them in a uniform superposition.
* Applies a fixed phase of $\pi/4$ only when `q[0] == 1`.
The affected states are those whose first qubit is 1:
| q state | Relative phase |
| ------- | ------------------ |
| \[0,0] | unchanged |
| \[0,1] | unchanged |
| \[1,0] | rotated by $\pi/4$ |
| \[1,1] | rotated by $\pi/4$ |
It is possible to apply `phase` under both single-qubit and multi-qubit controls; the resulting phases accumulate on states satisfying
the respective control conditions.
### Example: Phase oracle from an expression
A controlled phase can be used to mark states satisfying a Boolean expression. The following example treats `v` as a selection register
over the list `S`. Each basis state of `v` represents a subset of the elements of `S`: if `v[i] == 1`, then `S[i]` is selected. The
controlled phase marks states that select exactly three elements whose sum is at most 16.
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
S = [1, 3, 5, 8, 11]
@qfunc
def main(v: Output[QArray]):
allocate(5, v)
hadamard_transform(v)
selected_count = sum(v[i] for i in range(v.len))
selected_sum = sum(S[i] * v[i] for i in range(v.len))
condition = (selected_count == 3) & (selected_sum <= 16)
control(condition, lambda: phase(pi))
```
This program:
* Prepares `v` in uniform superposition.
* Applies a relative phase of $\pi$ to states representing three selected elements of `S` whose sum is at most 16.
* Leaves all other states unchanged.
Since a phase of $\pi$ corresponds to multiplying the selected amplitudes by -1, this implements a phase oracle for the satisfying assignments.
This pattern is common in Grover-style algorithms: rather than writing a result into a separate flag qubit, the oracle marks satisfying states by
changing their phase.
## The `control` statement and runtime `if_`
Qmod provides two distinct mechanisms for conditional execution: the `control` statement for quantum conditions, and the `if_` statement for classical conditions.
| Construct | Condition type | Evaluated | Effect |
| --------- | -------------- | ----------------------- | ------------------------------------------------------------------------------ |
| `control` | Quantum | Runtime | Applies a unitary coherently, conditioned on a quantum state |
| `if_` | Classical | Compile time or runtime | Conditionally executes a branch based on a symbolic or runtime classical value |
Use `control` when the condition depends on quantum variables such as qubits, quantum arrays, or expressions over quantum numbers. Use `if_` when the condition is a
classical Qmod expression — whether symbolic or a runtime value such as a mid-circuit measurement result. Use a Python `if` when the condition is a concrete Python value
known at model construction time, including Python-type parameters in [generative functions](/qmod-reference/language-reference/generative-descriptions).
## See also
[Control statement](/qmod-reference/language-reference/statements/control/)
[Phase statement](/qmod-reference/language-reference/statements/phase/)
[Expressions](/qmod-reference/language-reference/expressions)
[Within-apply](/qmod-reference/language-reference/statements/within-apply)
[Quantum Numbers and Arithmetics](/user-guide/modeling/quantum-numbers-arithmetics)
# Modeling
Source: https://docs.classiq.io/user-guide/modeling/index
This under construction section is where you can learn the concepts and syntax needed to design quantum models—simply put, to write quantum code using Classiq.
If you prefer a faster, exercise-oriented path to learning, see the [Classiq Tutorial](/getting-started/classiq_tutorial/index).
For a complete, formal specification of the language, refer to the [language reference](/qmod-reference/language-reference/index).
# Measurements, Observables, and Hermitian Operators
Source: https://docs.classiq.io/user-guide/modeling/observables-and-operators
## Introduction
In quantum computing, measurement defines how information is extracted from a quantum program and made available for classical processing. Depending on the algorithm and execution mode, this information may take the form of sampled quantum states, interpreted output values, or expectation values of observables. These different notions of measurement serve different purposes and are applied through explicit measurement operations within the execution workflow. In many algorithms - especially variational ones - the relevant result is not an individual sample but an expectation value of an observable, for example a Hamiltonian expressed as a linear combination of Pauli strings.
This stems from the realization that many quantum algorithms do not optimize over samples, but over classical quantities derived from quantum states, such as energies or cost functions. In quantum algorithms, measurement is therefore more than a final readout step: it defines the classical quantity that is optimized, compared, or post-processed. In Classiq, this includes sampling-based measurements through execution functions and methods, which return counts of bitstrings or parsed values, as well as expectation-value estimation workflows, which repeatedly evaluate an expectation value such as $\langle H \rangle$ for a given observable $H$ using the same synthesized program under different parameters. In addition, Qmod supports mid-circuit measurement, which collapses a qubit and returns its classical value, enabling limited run-time control flow within a quantum program when needed.
## Measurements in Qmod
In this guide, we cover the concepts:
* **Measurement**: extracting classical information from qubits.
* **Observables**: Hermitian operators whose expectation values are estimated.
* **Quantum operators**: unitaries applied to evolve the quantum state.
Quantum variables declared as `Output[...]` in `main` specify what is measured in a quantum program.
When the program is executed using sampling-based execution methods, these output variables are measured in the computational ($Z$) basis on every shot. The results can be accessed as raw bitstring samples and their counts or as parsed values, where the measured bits are interpreted according to the declared [quantum variable types](/user-guide/modeling/quantum-numbers-arithmetics).
Only variables declared as outputs of `main` are reported as execution results.
In many algorithms, the goal is not to analyze individual measurement outcomes but to compute an expectation value of an observable, $\langle H \rangle$, commonly expressed as a linear combination of Pauli strings. In Classiq, expectation values are computed using `estimate`. Rather than returning samples over the computational basis, this function evaluates the expectation value of a specified observable with respect to the quantum state prepared by the program. This is the primary measurement mode in variational and optimization-based algorithms.
The following example illustrates sampling-based measurement in Qmod:
```python theme={null}
from classiq import *
from classiq.qmod.symbolic import pi
@qfunc
def prepare_pair(angle: CReal, a: QBit, b: QBit):
RY(angle, a)
CX(a, b)
@qfunc
def main(a: Output[QBit], b: Output[QBit]):
allocate(a)
allocate(b)
prepare_pair(pi / 2, a, b)
```
This quantum program:
1. Allocate two different qubits, `a` and `b`.
2. Prepare the following state by applying a `prepare_pair`:
$\vert a, b \rangle = \cos(\theta)\vert 0, 0\rangle + \sin(\theta/2) \vert 1,1\rangle,$
with $\theta = \pi/2$.
A representative sample output may look like this (each outcome should be measured at a \~$50\%$ probability):
| a | b | counts | probability | bitstring |
| - | - | ------ | ----------- | --------- |
| 0 | 0 | 1047 | 0.511230 | 00 |
| 1 | 1 | 1001 | 0.488769 | 11 |
Which represents the outcomes of a maximally entangled Bell state.
## Observables as a Pauli string
In the context of quantum mechanics, an observable is represented by a Hermitian operator. In digital quantum computing, these operators are most commonly expressed as a linear combination of Pauli strings. A Pauli operator is a tensor product of single-qubit Pauli matrices $(I, X, Y, Z)$ acting on specific qubits.
In Qmod, it is possible to define these observables using `SparsePauliOp`. This enables specifying the physical quantity to estimate — such as energy in a molecular Hamiltonian or a cost function in a combinatorial optimization problem.
A Pauli operator, when represented using `SparsePauliOp`, consists of:
* **A list of Pauli terms**: Each term corresponds to a Pauli tensor product (a Pauli “string”) acting on specific qubits.
* **A coefficient for each term**: Each Pauli string is associated with a real or complex coefficient, and the full operator is given by the linear combination of these terms.
Mathematically, this means that any observable $H$ can be represented as:
$H = \sum_i c_i \, P_i,$
where $\{c_i\}_i$ are real coefficients and $\{P_i\}_i$ are Pauli strings, such as $X \otimes Y \otimes Z$.
To construct these observables in Python, use `SparsePauliOp` objects (Check [Classical Types](/qmod-reference/language-reference/classical-types/#hamiltonians)). In particular, using a SparsePauliOp is an efficient way to define a sparse observable. Where “sparse” refers to the structure of each Pauli string—specifically, that many qubits are acted on by the identity operator $I$, and only a relatively small number have non-identity Pauli matrices. This representation compactly encodes such strings while storing only the terms that actually appear in the operator.
[comment]: DO_NOT_TEST
```python theme={null}
# Define the same observable, but using a SparsePauliOp: 0.5 * Z0 * Z1 + 0.8 * X0
my_sparse_observable = 0.5 * Pauli.Z(0) * Pauli.Z(1) + 0.8 * Pauli.X(0)
```
## Expectation value estimation
Once an observable is defined, it is possible to evaluate its expectation value from a quantum program. For this, use [`observe`](../execution/observe).
[comment]: DO_NOT_TEST
```python theme={null}
qprog = synthesize(main)
observe(
qprog,
observable=my_sparse_observable,
num_shots=1000
)
res.value
```
`(0.49531250000000004+0j)`
When the quantum program is parameterized, the observable can be estimated as a function of the program parameters. Parameters correspond to classical arguments of main (for example `CReal`), and values are provided at execution time using a dictionary keyed by the parameter name. More information about it can be obtained from the [Execution Tutorial](/getting-started/classiq_tutorial/execution_tutorial_part2).
## Pauli operators as quantum operators
Beyond their role in defining observables for expectation-value estimation, Pauli operators can also be interpreted as quantum operators that generate unitary evolution. In this context, a Pauli operator represents a Hermitian operator that can be exponentiated to form a unitary of the form
$U = e^{-i t H },$
where $P$ is a Pauli operator and $t$ is a real-valued parameter.
This interpretation is central when simulating time evolution under a Hamiltonian or when constructing circuits that implement operator exponentials derived from physical models.
### Hamiltonian evolution and operator decomposition
Consider a Hamiltonian expressed as a linear combination of Pauli strings,
$H = \sum_i c_i \, P_i$
In general, the Pauli terms $P_i$ do not commute, which means the unitary evolution $U(t) = e^{-i t H },$ cannot be implemented exactly as a single operation. Instead, it is approximated by decomposing the evolution into a sequence of exponentials of individual Pauli strings.
This decomposition turns Pauli operators into building blocks of quantum dynamics, rather than merely objects to be measured.
**Example: Suzuki–Trotter decomposition**
One widely used approach for approximating Hamiltonian evolution is the Suzuki–Trotter decomposition. In its first-order form, the time evolution under $H$ is approximated as:
$e^{-i H t} \approx \prod_i e^{-it c_i P_i}$
with the approximation improving as the evolution is split into more, smaller time steps.
From a modeling perspective, the same Pauli operator structure used to define observables naturally extends to defining operator evolution, making Pauli operators a unifying representation for both measurement and dynamics. We can see an example of it when using the `suzuki_trotter` function, as in the example below.
```python theme={null}
from classiq import *
quantum_operator = (
Pauli.X(0) * Pauli.Y(1) + Pauli.Z(1) + Pauli.Z(2) + Pauli.Y(3) * Pauli.X(2)
)
measured_observable = Pauli.X(0) + Pauli.Y(1) + Pauli.Z(2) + Pauli.X(3)
@qfunc
def main(x: Output[QArray]):
allocate(4, x)
suzuki_trotter(
quantum_operator, evolution_coefficient=1.0, order=1, repetitions=1, qbv=x
)
qprog = synthesize(main)
res = observe(
qprog,
observable=measured_observable,
num_shots=1000
)
res
```
`(-0.4814453125+0j)`
This code:
* Synthesizes the quantum program defined in main, which prepares the quantum state and applies the Suzuki–Trotter evolution generated by the specified Pauli operator Hamiltonian.
* Uses `observe` to execute the synthesized program.
* Estimates the expectation value of `measured_observable`, computing a classical quantity derived from the final quantum state rather than returning raw measurement samples.
This demonstrates that the same Pauli operator formalism underlies both quantum dynamics and measurement in Qmod: Pauli operators define the operators that evolve the state, while observables define the quantities extracted from it. Understanding this distinction clarifies why Pauli operators play a dual role in quantum programs, motivating the discussion that follows on how observables and operators are treated differently despite sharing the same mathematical representation.
Although Pauli operators appear in both operator evolution and observable definitions, their roles are distinct:
* As **observables**, Pauli operators specify what quantity is measured or estimated from a quantum state.
* As **operators**, Pauli operators define unitary transformations applied to the quantum state during execution.
## See also
The [Execution page](../execution/index).
Definitions for [SparsePauliOp](/sdk-reference/qmod/classical-types#sparsepauliop), [observe](../execution/observe), and [suzuki\_trotter](/sdk-reference/qmod/functions/core_library/exponentiation#suzuki_trotter).
# Quantum Numbers and Arithmetics
Source: https://docs.classiq.io/user-guide/modeling/quantum-numbers-arithmetics
## Introduction
Qmod allows modeling quantum data using typed variables that behave much like variables in classical programming languages: you declare them, allocate them, and then use them in arithmetic and logical expressions over them. In this guide, we focus on quantum numeric variables (for example, integers or fixed-point values represented on qubits) and how to use them in arithmetic expressions, such as addition, comparisons, and bitwise logic, to build useful subroutines for quantum algorithms.
A key motivation is that these expressions are not simply for “doing math”: they are a practical way to encode conditions over quantum states, which appear throughout quantum algorithms. For instance, many search and optimization-style algorithms require marking the states that satisfy a certain condition, often implemented as a phase oracle. In Qmod, such predicates can be written directly as a arithmetic or boolean expression, such as `x + y == target`. We therefore start with a minimal “a + b” example to build intuition about computation over values in superposition, and then expand toward expressing and combining conditions in a way that scales to real algorithmic use cases.
In this guide, you will find:
* An introduction to **quantum numeric variables (`QNum`)** in Qmod and how they represent **integers or fixed-point values** stored on qubits.
* An explanation of how to **declare and allocate quantum numbers**, including the meaning of `QNum[size, is_signed, fraction_digits]` and when its type attributes can be **inferred automatically**.
* A walkthrough showing how **superposition affects arithmetic results**, and how computed outputs (e.g., `z = x + y`) become **correlated/entangled** with the input variables.
* A description of **assignment** (`|=`) as the main way to compute expressions and store results in a target variable.
* A clear distinction between **out-of-place** (`z |= x + y`) and **in-place** updates (`x += y`, `z ^= condition`), including when each is useful.
* Examples of how to specify richer **quantum arithmetic and predicate expressions** using arithmetic, comparison, and bitwise operators to **mark target states** (as used in Grover-like algorithms).
## Quantum numeric variables
In Qmod, once a quantum variable is allocated, it references a quantum object stored on one or more qubits. Quantum variables are declared with a *quantum type* that defines characteristics such as how many qubits are used and how the state is interpreted. In the case of a quantum number (`QNum`), the state is interpreted as an integer or a fixed-point real number.
When expressing algorithm logic, it is often useful to treat a quantum object as a number and write code that resembles classical numeric programming. However, the values stored in quantum variables may present quantum effects, such as entanglement and superposition. Before diving into how to use quantum numbers, consider the following quantum program:
```python theme={null}
from classiq import *
@qfunc
def prepare_superposition(q: QArray[QBit]):
H(q[1])
@qfunc
def main(
x: Output[QNum[3, UNSIGNED, 0]], y: Output[QNum[3, UNSIGNED, 0]], z: Output[QNum]
):
allocate(x)
allocate(y)
prepare_superposition(x)
prepare_superposition(y)
z |= x + y
```
At a high level, this quantum program:
1. Allocate two different quantum numbers, `x` and `y`.
2. Prepare the following superposition states by applying a Hadamard gate on different qubits using `prepare_superposition`:
$\vert x \rangle = \frac{1}{\sqrt{2}}\left(\vert 0 \rangle + \vert 2 \rangle\right), \quad \vert y \rangle = \frac{1}{\sqrt{2}}\left(\vert 0 \rangle + \vert 2 \rangle\right).$
3. Evaluate the arithmetic operation `x + y` and assign its result to the variable `z`.
A representative sample output may look like this (each outcome should be measured at a \~25% probability):
| x | y | z | counts | probability | bitstring |
| - | - | - | ------ | ----------- | ---------- |
| 0 | 0 | 0 | 519 | 0.253417 | 0000000000 |
| 2 | 2 | 4 | 497 | 0.242675 | 0100010010 |
| 2 | 0 | 2 | 508 | 0.248046 | 0010000010 |
| 0 | 2 | 2 | 524 | 0.255859 | 0010010000 |
Since variables `x` and `y` are in superposition, the value of `z` will vary according to the values measured in `x` and `y`. Consequently, `z` is entangled with `x` and `y`.
### Declaring quantum numbers
Now, let’s dive into the declaration of the quantum numbers `x` and `y`. In the example above, they are declared using the type hint `Output[QNum[3, UNSIGNED, 0]]`. A type hint is an annotation next to a variable that specifies what kind of value it represents.
Here, `QNum` indicates that `x` and `y` represent numbers, and their type attributes specifies their numeric attributes:
* 3: the total number of qubits used to store the number (size)
* `UNSIGNED`: the number has no sign (i.e., non-negative). This field is optional, and set to `UNSIGNED` by default.
* 0: the number has no fraction digits. This means the number is interpreted as an integer. If $\text{fraction_digits} > 0$, the value is interpreted as a fixed-point number, scaled by $2^{-\text{fraction_digits}}$. This field is optional, and set to 0 by default.
This matches the definition of a quantum number type in Qmod as:
QNum\[size, is\_signed, fraction\_digits]
Here, `is_signed` is an optional field, set to `UNSIGNED` by default, and `fraction_digits` is an optional field set to 0.
It is also possible to use the booleans `False`/`True` instead of `SIGNED`/`UNSIGNED`.
A useful point when writing more general Qmod code is that the type attributes (such as `size`, `is_signed`, and `fraction_digits`) can also be used as Python expressions, which allows you to write code that adapts to the numeric configuration of a quantum variable.
`size` is an attribute accessible by every quantum type, not only quantum numbers.
### Omitting type attributes and inference
Note that `z` is declared as `Output[QNum]` without specifying numeric attributes. This is intentional: numeric attributes are optional, and when they are not provided, the Qmod compiler infers them upon the variable’s first initialization (including cases such as assignment). The use of this feature is restricted to when it is possible to infer the type attributes from the quantum number, otherwise the quantum program might raise errors. For instance, if `y` is not correctly declared in the above example, the following error will arise:
Could not infer the size of variable 'y'.
For a complete description of the numeric inference rules, check the [Language Reference](/qmod-reference/language-reference/quantum-types#numeric-inference-rules).
### Alternative: Providing type attributes in `allocate`
Instead of specifying numeric attributes in the type hint, you can provide them in the `allocate` call. The following two declarations are equivalent according to the numeric inference rules and initialization behavior:
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QNum[3, SIGNED, 1]]):
allocate(x)
```
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QNum]):
allocate(3, SIGNED, 1, x)
```
## Numeric assignment
Numeric assignment is the Qmod mechanism that lets you compute with quantum numbers using expressions that resemble classical code. Conceptually, you write an expression such as `x + y`, and the Qmod compiler synthesizes a gate-level description that computes the result in the computational basis, even when `x` and `y` are in superposition.
This can be written using `|=`. For example,
[comment]: DO_NOT_TEST
```python theme={null}
z |= x + y
```
can be read as:
"Compute x + y and store the result in the variable z."
In the earlier example, `z` is declared as `Output[QNum]` without specifying how many qubits it uses. This works because Qmod can infer the right size when `z` is first initialized. In this case, `z` is a 4-qubit unsigned quantum number with 0 fraction digits.
This is why the assignment line is doing more than “just storing a value”: it is also the moment where `z` gets its final numeric attributes if you did not specify it explicitly.
### In-place and out-of-place assignment
When you compute something like x + y, you must determine where the result will be stored.
There are two options:
1. **Out-of-place**: write the result into a new variable (leave the inputs unchanged)
This is what happens with:
[comment]: DO_NOT_TEST
```python theme={null}
z |= x + y
```
* `x` and `y` remain the same variables, with the same qubits.
* `z` is the output where the result is computed.
* This typically creates or initializes storage for `z` (therefore it should not be initialized yet).
* Quantum effect: if `x` and `y` are in superposition, `z` becomes correlated with them (often entangled), but `x` and `y` are not overwritten.
This is analogous to performing the following classical operation:
[comment]: DO_NOT_TEST
```python theme={null}
z = x + y
```
This is called out-of-place because the result is written in an additional variable `z`.
2. **In-place**: write the result into the same variable (update an existing variable)
This is what happens with operators like += and ^=:
[comment]: DO_NOT_TEST
```python theme={null}
x += y
```
* The result is stored back into x.
* `x` must already be allocated (because it is being modified).
* `x` keeps the same number of qubits, so if the operation would need more bits, the result may wrap around (modulo $2^{\rm{size}}$).
This is called in-place because the computation updates the same storage in-place, instead of creating a new variable where the result is assigned.
You can think of this exactly as classical code `x+=y`.
### Two common in-place operators
1. `+=` **(add into the same variable)**
The in-place add can be used to increment a quantum variable's value. To better understand this, we can analyze the following example:
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QNum[3]], y: Output[QNum[2]]):
allocate(y)
hadamard_transform(y)
x |= 1
x += y
```
Whose outputs are close to
| x | y | counts | probability | bitstring |
| - | - | ------ | ----------- | --------- |
| 4 | 3 | 508 | 0.258046 | 11100 |
| 3 | 2 | 513 | 0.250488 | 10011 |
| 2 | 1 | 522 | 0.254882 | 01010 |
| 1 | 0 | 505 | 0.256582 | 00001 |
This quantum program:
* Initializes two quantum numbers, `x` and `y`
* `x` is assigned the integer value 1, while `y` is in a superposition of the values in $[0, 1, 2, 3]$
* Performs the quantum operation `x = x + y`, where `y` is in a superposition and, consequently, `x` becomes superposed as well.
This way, the variable `x` is always an increment of variable `y`.
2. `^=` **(in-place XOR)**
The bitwise XOR operator is a binary operation that compares the bitstrings of two numeric values and produces a result bit of 1 when the bits differ and 0 when they are the same. In Qmod, it is implemented by applying this rule between corresponding qubits (or between a qubit and a classical bit) across the operands. The in-place form `^=` computes the XOR and writes the result back into the left-hand variable.
In the example below, `x + y == 3` combines this value with `z` using XOR and writes the result back into `z`. This means that `z` is updated only when the condition evaluates to 1.
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QNum[3]], y: Output[QNum[2]], z: Output[QBit]):
allocate(y)
allocate(z)
hadamard_transform(y)
x |= 1
z ^= x + y == 3
```
Whose outputs are close to
| x | y | z | counts | probability | bitstring |
| - | - | - | ------ | ----------- | --------- |
| 1 | 0 | 0 | 503 | 0.255605 | 000001 |
| 1 | 1 | 0 | 517 | 0.252441 | 001001 |
| 1 | 2 | 1 | 532 | 0.259765 | 110001 |
| 1 | 3 | 0 | 496 | 0.242187 | 011001 |
This quantum program:
* Initializes two quantum numbers, `x` and `y`, and a qubit `z`.
* Assign the numeric value 1 to `x` and generates a uniform superposition in `y`.
* Flips the state of `z` whenever `x + y == 3`.
This way, the in-place XOR operation serves as a powerful way of "marking" target states - a very important tool in search and optimization algorithms, such as [Simon's algorithm](/explore/algorithms/foundational/simon/simon).
## Quantum Arithmetics
Qmod supports quantum expressions, including arithmetic expressions, in a manner analogous to classical programming languages. Both quantum and classical expressions may appear on the right-hand side of assignment statements, and quantum expressions may also be used in other contexts, such as the conditions of control statements.
When a quantum expression is written, Qmod records the expression symbolically and translates it into a reversible quantum subroutine that implements the corresponding operation. This ensures that the resulting operation is unitary and can be applied to quantum variables.
### Writing Arithmetic Expressions
Qmod supports a wide range of arithmetic and logical operators inside expressions used for numeric assignment. In practice, this means you can write expressions such as:
* Arithmetic: `+`, `-`, `*`
* Comparisons (produce a boolean / predicate): `==`, `!=`, `<`, `<=`, `>`, `>=`
* Bitwise logic: `&`, `|`, `^`, `~`
* Boolean composition of predicates: `logical_and`, `logical_or`, `logical_not` (depending on the expression context)
A simple example using different arithmetics and boolean operations is:
```python theme={null}
from classiq import *
@qfunc
def main(x: Output[QNum[2]], y: Output[QNum[2]], z: Output[QBit]):
allocate(y)
allocate(x)
allocate(z)
hadamard_transform(x)
hadamard_transform(y)
z ^= (x + y - 1) * (x - y + 1) == -1
```
This quantum program:
* Allocates two quantum numbers `x` and `y`, and a qubit `z`
* Puts the quantum numbers in superposition over all possible values
* Computes the predicate
$(x + y - 1) \cdot (x - y + 1) = -1$
and conditionally modofies the state of `z` when the predicate is satisfied.
In this context, we are correlating the auxiliary qubit `z` with the values of `x` and `y`. The quantum numbers `x` and `y` themselves are not modified. Instead, `z` becomes entangled with them such that:
* For basis states where the expression evaluates to -1, the state of `z` is changed to $\vert 1 \rangle$
* For all other basis states, `z` remains $\vert 0 \rangle$
As a result, measuring `z` and obtaining 1 would collapse `x` and `y` into a superposition of only those value pairs that satisfy the equality.
A technical description of numeric assignment is available at the [Language Reference](/qmod-reference/language-reference/statements/assignment).
## See also
For more information regarding quantum types, see [Quantum Types](/qmod-reference/language-reference/quantum-types).
# Getting Started with Studio
Source: https://docs.classiq.io/user-guide/studio/Studio-Guide
The Studio is Classiq's browser-based development environment, giving you a ready-to-use workspace for writing and running quantum programs without any local installation.
## **Setup and Get Started**
To get started with the Studio, follow these steps:
1. Sign in to the platform: access is by invitation only, so if you do not yet have a Classiq account, first request access through the [Registration](/getting-started/registration_installations) guide. Once your account is set up, sign in at [platform.classiq.io](https://platform.classiq.io/) with your Google/Microsoft account or a general email address, and you'll be redirected to the platform home page.
2. Access the Studio from the platform home page using the sidebar button, as shown below.
3. Your environment is loaded in a new browser tab (initial setup could take a couple of minutes).
4. Please trust the Classiq workspace author to open the Classiq extension and load your workspace.
Now your Studio is ready for use.
Access your workspace via the "EXPLORER" icon on the top left.
Your workspace consists of two sections:
* Workspace: persistent storage; any edits you make are saved.
* Classiq library: This is your place to explore the world of quantum algorithms. You can click on any notebook, modify it, and run it. But remember that this is non-persistent storage: any edits to these files are reverted when the Studio is shut down (after 1 hour of being idle). If you've made changes you want to save, copy-paste the file to the personal workspace section.
* You can also upload any file into your persistent storage by right-clicking on "user workspace" and selecting "upload".
5. When running a notebook for the first time, you will be asked to install the kernel. Click on the "Select Kernel" button and choose the recommended Python kernel (Python 3.12.8).
6. A drop-down menu appears; select "Python Environments" (or press "Enter").
7. Select "classiq-venv".
* More advanced users who are comfortable managing their own environment are welcome to set up and use their own virtual environment.
8. Start coding, experiment, and create quantum algorithms.
9. When calling the method `show()` you might see a pop-up that asks you to trust an external domain - click on "trust all domains from classiq.io" to see this pop-up only once. The circuit will open up in a separate tab.
## **Best Practices**
In the Studio, each user has their own dedicated persistent storage (2 GB).
This means that every time you reload, you can keep working right where you left off, just as you would locally on your computer.
Keep the following considerations and best practices in mind:
### **Data Persistence**
#### **Location**
The explorer (file browser) is divided into two sections: Workspace and Classiq library. The Classiq library is non-persistent, and any edits to these files are reverted when the Studio is shut down (after 1 hour of being idle). Thus, we recommend copying the desired notebook to the Workspace section.
#### **Retention Period**
Please note that this feature is still under development, and we are working on improving it. Thus, we will do our best to keep your data and work safe, but we cannot guarantee that your data will be kept forever. We recommend backing up your work locally (by downloading the files) or in a remote repository.
### **Using Git**
We highly recommend using Git and GitHub (or similar) to keep track of your work. You can use Git in the terminal or in the Studio. Check out [this section](/user-guide/studio/git-getting-started) to get started with Git.
After committing locally, it's best to push your work into a remote repository for backup and collaborative work.
### **Using the Virtual Environment Wisely**
You have a virtual environment installed in your Studio. You can install any pip package you need for your work (e.g., Qiskit, TensorFlow, etc.), but keep in mind that you have limited space. Also, environments are often hard to maintain, and you can get into a dependency rabbit hole. If you want to experiment with new packages, create a new venv with whatever packages you need and delete it when you're done.
We guarantee that the "classiq-venv" is set and working.
#### **Resetting the Virtual Environment**
If you encounter issues or simply want a clean slate, you can reset your virtual environment by running the following command in the terminal:
```bash theme={null}
reset-user-env
```
Running this command will remove any additional packages or modifications
you've made in your virtual environment, restoring it to its default state.
This is especially useful if you experience dependency issues or if the environment becomes cluttered from experimentation.
> ***Pro Tip:*** To manually reset your virtual environment, you can run:
> `rm -rf /classiq-venv/*`
## **Pre-Installed LaTeX (latexmk)**
`latexmk` and a TeX Live subset (`texlive-latex-base`, `texlive-latex-recommended`, `texlive-latex-extra`, `texlive-fonts-recommended`, `texlive-science`) are pre-installed in the Studio. This means you can run the benchmarking application from the Classiq library and have it build its PDF report out of the box, without any additional setup.
# Getting started with git
Source: https://docs.classiq.io/user-guide/studio/git-getting-started
This page contains a practical guide on how to get started with git and GitHub, so you can get the most out of working with the Studio and writing code in general
## **what is git?**
Git is a version control system that tracks changes in your code. It lets you:
Keep a history of modifications.
Work on different versions of your code.
Collaborate with others without overwriting changes.
Restore previous versions if something breaks.
It runs locally on your machine, but when combined with platforms like GitHub or GitLab, it enables seamless collaboration.
### **What is a Repository?**
A repository (repo) is a storage space where your project’s files, code, and version history are managed by Git.
A local repository exists inside your project folder and tracks changes.
A remote repository is stored on a hosting service like GitHub, GitLab, or Bitbucket, allowing multiple people to work on the same project.
We highly recommend to push your code to a remote repository. It will promise you that your work is backed up, and you can access it from anywhere.
## **Common commands and quick setup**
The Studio comes with Git pre-installed, so you can start using it right away.
### **Initialize a Git Repository**
Inside your project folder, run:
```bash theme={null}
git init
```
This creates a local repository, allowing you to track changes in your project.
### **Clone an Existing Repository**
You can always copy (clone) an existing project from a remote repository (e.g., GitHub) to your workspace:
```bash theme={null}
git clone
```
### **Useful commands:**
#### **Check the status of your project:**
```bash theme={null}
git status
```
#### **Add changes to the next commit:**
```bash theme={null}
git add .
```
#### **Save your changes:**
```bash theme={null}
git commit -m "Description of changes"
```
#### **Push and Pull**
Push – Send your changes to a remote repository (called origin):
```bash theme={null}
git push origin main
```
Pull – Get the latest updates from the remote repository:
```bash theme={null}
git pull origin main
```
When you start feeling comfortable with git, you can start using branches, pull requests, and more advanced features. You can read more about it in attached linked.
## **How does it work with GitHub?**
GitHub (or alternatives like GitLab and Bitbucket) acts as a remote repository, meaning it stores your code in the cloud and enables collaboration.
### **What is a Remote Repository?**
A remote repository is a version of your project that is hosted online. It allows you to:
* Store your code securely.
* Access your work from any device.
* Collaborate with team members in real-time.
### **Connect your local repository to a remote repository, use:**
clone the repo:
```bash theme={null}
git clone
```
add it to your local workspace
```bash theme={null}
git remote add origin
```
Then, push your local changes to the remote repo:
```bash theme={null}
git push -u origin main
```
Best Practices for Using Git with GitHub
Use branches – Work on a separate branch before merging changes to the main project:
```bash theme={null}
git checkout -b feature-branch
```
### **Best practice to combine git and GitHub (or gitlab etc. - it's up to you :)**
* Write clear commit messages – describe what changed and why.
* Pull before pushing – always get the latest updates before sending your changes.
* Use `.gitignore` – avoid committing unnecessary files.
* Create pull requests – review changes before merging into main.
## **How to use git in the Studio**
* Open the terminal in the Studio.
* We have already installed git inside the studio, so you can start using it right away.
## **Read more**
There are infinite number of guides available on using git, integration with GitHub or others. We have collected some of our favorites:
* [Git official documentation](https://git-scm.com/doc)
* [GitHub official documentation](https://docs.github.com/en/get-started/)
* [Git cheat sheet](https://www.atlassian.com/git/tutorials/atlassian-git-cheatsheet)
# Studio - Web-based IDE with Classiq inside
Source: https://docs.classiq.io/user-guide/studio/index
The Studio is a VSCode environment part of the platform.
It bypasses the need to install the Python SDK package and its dependencies,
and includes the complete and updated Classiq Library git repository of quantum functions, algorithms, applications, and tutorials.
## **Key features**
**Code editing and running** – Write and modify your code using the latest Qmod and python SDK version in a fully featured editor with syntax highlighting, autocompletion, go-to definition, jupyterlab extension and more.
Using your favorite code editing tools - vscode or jupyterlab
**Work from anywhere** - We supply a persistent user workspace to save and manage code and projects.
**Ready-to-use library** - The Classiq library contains tens of state-of-the-art quantum algorithms ready for use.
**Integrated debugging** – Step through execution and inspect intermediate results.
## **Getting started**
**Access the Studio** – Open the Studio from the [platform](https://platform.classiq.io/) (once you are granted access) and follow the instructions [here](/user-guide/studio/Studio-Guide)
**Write Your First Program** – Use the editor to create your first quantum program or load an example of our applications from the build in Classiq library.
## **Next steps**
* Explore the code editor guide to learn about the features, capabilities and best practice of the editor
* Read the [Qmod reference](/qmod-reference/index), [SDK reference](/sdk-reference/index) and the [Execution section](/user-guide/execution/index) to get started with Classiq and start writing and running quantum algorithms and programs.
# Quantum Program Constraints
Source: https://docs.classiq.io/user-guide/synthesis/constraints
When synthesizing a quantum program, you can pass a maximum width constraint to the generation; for example, requiring that no more than 20 qubits are used.
Pass constraints as follows:
```python theme={null}
from classiq import *
constraints = Constraints(max_width=20)
@qfunc
def main(res: Output[QBit]) -> None:
allocate(res)
synthesize(main, constraints=constraints)
```
## Optimization Parameter
When synthesizing a quantum program, to optimize the quantum program according to a
parameter, set the `optimization_parameter` field. The possible
parameters are the same parameters that can be constrained.
The following example shows how to remove the width constraint in the quantum program, setting it instead
as the optimization parameter.
```python theme={null}
from classiq import (
qfunc,
Constraints,
OptimizationParameter,
Output,
QBit,
TranspilerBasisGates,
allocate,
set_constraints,
synthesize,
)
constraints = Constraints(
max_width=20,
optimization_parameter=OptimizationParameter.DEPTH,
)
@qfunc
def main(res: Output[QBit]) -> None:
allocate(1, res)
synthesize(main, constraints=constraints)
```
# Getting Started with Quantum Program Synthesis
Source: https://docs.classiq.io/user-guide/synthesis/getting-started
The first steps in quantum program synthesis are defining the algorithms, its constraints,
and your preferences. These are described in detail in the following sections.
Once your model is fully defined, it is time to synthesize it.
In the IDE, describe the model in the [model](https://platform.classiq.io/dsl-synthesis) page.
After writing down the model, click `Synthesize` on the bottom right of the page.
After synthesis, you are automatically redirected to the quantum program page.
Initiate the synthesis process by performing the `synthesize` method on a model. Alternatively, you can use the async
`synthesize_async` method as part of an async code.
```python theme={null}
from classiq import qfunc, Output, QBit, allocate, synthesize
@qfunc
def main(res: Output[QBit]) -> None:
allocate(1, res)
qprog = synthesize(main)
```
# Hardware-Aware Synthesis
Source: https://docs.classiq.io/user-guide/synthesis/hardware-aware-synthesis
Quantum computers differ from one other in many significant parameters, such as basis
gates, connectivity, and error rates. The device specifications determine the
possibility of executing the quantum program, and logically equivalent programs might
require different implementations to optimize the probability of success.
The platform allows you to provide information about the hardware you want to use
to run your quantum program. The synthesis engine takes the parameters of this hardware into
account. For example, the engine could choose the implementation of a function that
requires the least number of swaps, given the connectivity of the hardware.
If the hardware device's basis gate set contains the Clifford gates `X`, `Z`,
`H`, `T`, and `CX` but does not contain arbitrary-angle rotation gates such as `RX`,
the platform uses the Solovay-Kitaev algorithm to approximate
single-qubit gates when necessary. You can set the maximum iterations of the
Solovay-Kitaev algorithm in the preferences, thus tuning the algorithm target
accuracy. (Larger values usually result in better and longer approximations,
at the expense of longer running times.)
## Specifying a Backend
To synthesize your quantum program for a specific backend, specify the backend provider and the name of the backend.
The platform supports these backend providers:
* Amazon Braket: All gate-based backends in [Amazon Braket](https://docs.aws.amazon.com/braket/latest/developerguide/braket-devices.html) including all Rigetti devices, `Lucy`, and `IonQ Device`.
* Azure Quantum: `ionq` and `quantinuum`.
* IBM Quantum: Those listed on [IBM Quantum's official website](https://quantum-computing.ibm.com/services/resources?tab=systems). Note that you should specify the name of the backend without the `ibmq_` prefix.
```python theme={null}
from classiq import *
@qfunc
def main(res: Output[QBit]) -> None:
allocate(res)
preferences = Preferences(
backend_service_provider="IBM Quantum", backend_name="ibm_boston"
)
qprog = synthesize(main, preferences=preferences)
```
## Customizing Hardware Settings
To synthesize the quantum program for hardware that is not available in
the platform, you can specify the custom settings of the hardware.
This includes the basis gate set and the connectivity map of the hardware.
Note that all hardware parameters are optional.
### Basis Gate Set
These are the allowed gates:
* Single-qubit gates: `u1`, `u2`, `u`, `p`, `x`, `y`, `z`, `t`, `tdg`, `s`, `sdg`, `sx`, `sxdg`, `rx`, `ry`, `rz`, `r`, `id`, `h`
* Basic two-qubit gates: `cx`, `cy`, `cz`
* Extra two-qubit gates: `swap`, `rxx`, `ryy`, `rzz`, `rzx`, `ecr`, `crx`,
`cry`, `crz`, `csx`, `cu1`, `cu`, `cp`, `ch`
* Three-qubit gates: `ccx`, `cswap`
If you do not specify gates in the IDE, the field remains empty. During synthesis, default
basis gates are applied automatically based on connectivity. To override, select one or
more gates in this field.
### Connectivity Map
The connectivity map is given by a list of pairs of qubit IDs. Each pair in the list means
that a two-qubit gate (e.g., `cx`) can be performed on the pair of qubits. If the coupling map is symmetric,
then both qubits can act as control. If the coupling map is asymmetric, then the first
qubit can act only as control, and the second qubit can act only as target.
To determine whether the provided map is symmetric, set the ` is_symmetric_connectivity` argument.
If you do not specify the connectivity map, the engine assumes full connectivity.
### Example
The following example specifies a backend with 6 qubits in a 2-by-3 grid, where each
qubit connects to its immediate neighbors. The backend uses four basis gates:
`cx`, `rz`, `sx`, and `x`.
```python theme={null}
from classiq import (
qfunc,
CustomHardwareSettings,
Output,
Preferences,
QBit,
allocate,
synthesize,
set_preferences,
)
@qfunc
def main(res: Output[QBit]) -> None:
allocate(1, res)
custom_hardware_settings = CustomHardwareSettings(
basis_gates=["cx", "rz", "sx", "x"],
connectivity_map=[(0, 1), (0, 3), (1, 4), (1, 2), (2, 5), (3, 4), (4, 5)],
is_symmetric_connectivity=True,
)
preferences = Preferences(custom_hardware_settings=custom_hardware_settings)
synthesize(main, preferences=preferences)
```
# Quantum Program Synthesis
Source: https://docs.classiq.io/user-guide/synthesis/index
Quantum algorithm design is a complex task, and solutions based on the
approach of designing at the gate level are not scalable. Likewise, solutions based on
combining existing building blocks are very limited in their scope. The platform allows a high level
description of quantum algorithms at the functional level and automatically synthesizes a
corresponding quantum program. The synthesis process refines the functional requirements, then allocates and optimizes
available resources such as the number of qubits available.
The basic description of quantum algorithms in the platform is through quantum functions. A
quantum function can be implemented in multiple ways, each with different properties
such as number of qubits, number of auxiliary qubits, depth, and approximation level. You can define any level of refinement of the function, from the purely abstract to the fully
defined. The synthesis engine fills in the details to provide a concrete implementation satisfying all
your requirements.
Moreover, a complete quantum algorithm can be realized in multiple ways, utilizing different
design choices such as function implementations, placement, uncompute strategies,
qubit management, and wirings. The platform sifts through the design space and finds a
best realization given your requirements and resource constraints.
This section describes how to define your algorithm and synthesize a quantum program that implements it:
* [Getting Started](/user-guide/synthesis/getting-started)
* [Constraints](/user-guide/synthesis/constraints)
* [Preferences](/user-guide/synthesis/preferences)
# Synthesis Preferences
Source: https://docs.classiq.io/user-guide/synthesis/preferences
You can modify these synthesis process preferences:
* [Output formats](#output-formats)
* [Hardware-aware settings](/user-guide/synthesis/hardware-aware-synthesis)
* [Timeouts](#timeouts)
* [Optimization level](#optimization-level)
* [Toggling quantum program visualization support](#toggling-circuit-visualization-support)
In this example, the chosen output format includes both Q# and OpenQASM.
Specific basis gates are selected for the synthesis:
controlled not, controlled phase, square root of not, Z-rotation,
and not gates.
[comment]: DO_NOT_TEST
```python theme={null}
from classiq import (
qfunc,
Output,
QBit,
allocate,
synthesize,
show,
CustomHardwareSettings,
Preferences,
QuantumProgram,
allocate,
)
@qfunc
def main(res: Output[QBit]) -> None:
allocate(1, res)
custom_hardware_settings = CustomHardwareSettings(
basis_gates=["cx", "cp", "sx", "rz", "x"]
)
preferences = Preferences(
output_format=["qasm", "qsharp"], custom_hardware_settings=custom_hardware_settings
)
qprog = synthesize(main, preferences=preferences)
show(qprog)
print(qprog.qsharp)
```
## Output Formats
The platform provides different ways to format the output of
synthesized quantum programs. You can choose multiple output formats.
* In the SDK, you can print or save the desired output format after synthesizing.
* In the IDE, you can download the desired output format after synthesizing.
The output options:
* `"qasm"` - OpenQASM. The qasm circuit is in `qprog.qasm`.
* By default, the platform uses OpenQASM 2.0. To use OpenQASM 3.0 instead, set the
`qasm3` field of the preferences to `True`.
* `"qsharp"` - Q#. The qsharp circuit is in `qprog.qsharp`.
* `"qir"` - Microsoft's QIR. The QIR circuit is in `qprog.qir`.
* `"ionq"` - IonQ Json format is in `qprog.ionq`.
* `"cirq_json"` - Cirq Json format is in `qprog.cirq_json`.
* `"qasm_cirq_compatible"` - OpenQASM 2.0 is compatible with Cirq, which is in `qprog.qasm_cirq_compatible`.
## Optimization Level
Some optimization strategies employed by the synthesis engine are computationally heavy.
You can control the tradeoff between synthesis time and the exhaustiveness of the search for
optimal circuit. Use `optimization_level` with the following values:
* `NONE` (0) - take the most time-efficient path
* `LOW` (1) - perform only light-optimizations
* `MEDIUM` (2) - skip the most time-consuming optimizations
* `HIGH` (3) - employ the most aggressive and time-consuming optimizations
Notes:
* Lower optimization levels may fail to satisfy user-specified synthesis constraints
(see [Quantum Program Constraints](/user-guide/synthesis/constraints#optimization-parameter)). In such cases you can retry with a higher
optimization level.
* Lower optimization levels may result in missing details in the quantum-program visualization
in the IDE. This limitation will be lifted in future releases.
* Higher optimization levels may take longer to complete, and may yield better results, but
neither is guaranteed.
## Timeouts
The platform offers two timeouts:
* `timeout_seconds` – A timeout value for the end-to-end synthesis process.
* `optimization_timeout_seconds` – A timeout value specifically controlling the search process
when given constraints and optimization directives
(see [Quantum Program Constraints](/user-guide/synthesis/constraints#optimization-parameter)).
You can specify both timeouts. Just make sure that the optimization timeout is
smaller than the generation timeout. Both timeouts are specified in a whole number of seconds.
## Toggling Quantum Program Debug Information
The platform allows users to toggle quantum program debug information:
* `debug_mode` - When the flag is set to `True` (default), the quantum program
will contain debug information for enhanced visualization (See [Quantum
Program Visualization Tool](/user-guide/analysis/visualization-of-quantum-programs)).
Setting this flag to `False` can potentially decrease the quantum program's size
and increase synthesis speeds.
# Quantum Program Transpilation
Source: https://docs.classiq.io/user-guide/synthesis/quantum-program-transpilation
Transpilation is the process of optimizing an already-synthesized quantum program and
matching it to the desired hardware. It includes optimizations, such as
combining a sequence of gates into an equivalent single gate; and
transformations, such as qubit routing (i.e., using swap gates to
apply 2-qubit gates on partially connected hardware).
Classiq synthesis returns an execution-ready quantum program. It contains a description, in a restricted subset of Qmod, that defines the concrete implementation of high-level constructs and folds in all resource-allocation decisions. This description preserves the function hierarchy and symbolic control flow of the Qmod source and can be displayed via the [QP visualizer](/user-guide/analysis/visualization-of-quantum-programs). However, it is not yet transpiled to a specific backend's gate set or connectivity.
Transpilation happens later, only when a concrete circuit is needed: when you [`export`](/sdk-reference/synthesis#export) the program to a supported [target language](/sdk-reference/synthesis#targetlanguage), when you request its transpiled metrics with [`get_transpiled_circuit_metrics`](/sdk-reference/synthesis#get_transpiled_circuit_metrics), or when you execute it on a designated backend, where the Classiq execution service transpiles it for that hardware so that every gate is compatible.
To restore the legacy flow, in which transpilation runs during synthesis, set `compatibility_mode=True` in [`Preferences`](/sdk-reference/synthesis#preferences).
If you set preferences in the synthesis step, for example a transpilation option or a target backend in the synthesis [`Preferences`](/sdk-reference/synthesis#preferences), they are saved with the quantum program and applied when you export it (by setting `transpilation_config=True`) or read its transpiled metrics. To use a different transpilation option on export, pass an explicit [`TranspilationConfig`](/sdk-reference/synthesis#transpilationconfig) instead of `True`; this overrides the synthesis settings entirely. Execution, on the other hand, disregards the synthesis transpilation option and transpiles for whichever backend you run on, at the `decompose` transpilation option by default. See [execution preferences](/sdk-reference/execution#executionpreferences) for the options available at execution.
## Transpilation Options
* `none`: no transpilation. This is the default transpilation option of [`export`](/sdk-reference/synthesis#export) if no [`transpilation_config`](/sdk-reference/synthesis#transpilationconfig) is passed.
* `decompose`: decompose all of the functions according to the basis gates of the backend.
* `light`: the lightest optimization pass; fast, and best suited for fully connected hardware.
* `medium`: a heavier pass that optimizes the quantum program further, at the cost of longer runtime. A balanced choice for hardware with moderate connectivity.
* `auto optimize`: chooses the transpilation automatically between `light` and `medium`, based on the chosen backend. This is the default transpilation option in [`get_transpiled_circuit_metrics`](/sdk-reference/synthesis#get_transpiled_circuit_metrics) and in [`export(..., transpilation_config=True)`](/sdk-reference/synthesis#export) when no transpilation option is set as a preference at synthesis.
* `intensive`: the heaviest pass, for maximum optimization. Well-suited for hardware with complex connectivity.
* `custom`: offers a personalized approach to optimizing quantum programs while weighing various factors. It takes specific optimization criteria into account, transpiling the quantum program to maximize efficiency and resource utilization for the chosen backend, with a primary focus on delivering the best possible circuit performance.
The heavier the transpilation option, the better the quantum program is optimized, but transpilation takes longer.