Skip to content

Design - The Qmod Language

The first step in quantum software development is designing your software, your algorithm. Classiq features a unique high-level modeling language called Qmod, that naturally captures the core concepts of quantum algorithm design. There are two ways to design in Qmod: * Directly, via the Classiq IDE using the Qmod native syntax * With Classiq Python SDK package, that gives access to the Qmod language via Python

Once you finished designing your algorithm you send it to the Classiq synthesis engine (compiler) to create a concrete quantum circuit implementation - a quantum program.

Concrete Example

Let's get started and understand Qmod through a concrete example.

Our task is to design a quantum algorithm that computes the arithemtic operation \(y=x^2+1\) coherently, for a quantum variable \(|x\rangle\) that is a superpostion of all the numbers between \(0\) and \(7\): \(\begin{equation} |x\rangle = \frac{1}{\sqrt{8}}(|0\rangle+|1\rangle+\dots +|7\rangle. \end{equation}\) The expected output is

\(\begin{equation} |x\rangle |y\rangle = |x\rangle |x^2+1\rangle = \frac{1}{\sqrt{8}}\sum_{i=0}^{7}|i\rangle|i^2+1\rangle, \end{equation}\) where \(|x\rangle\) is entangled to \(|y\rangle\).

Sounds complicated? The following code in Qmod with a few lines creates the desired algorithm with Classiq:

from classiq import Output, QNum, allocate, hadamard_transform, qfunc

def main(x: Output[QNum], y: Output[QNum]):

    allocate(4, x)
    hadamard_transform(x)  # creates a uniform superposition
    y |= x**2 + 1

and the desired quantum program can be synthesized and viewed:

from classiq import create_model, show, synthesize

quantum_program = synthesize(create_model(main))

Key Qmod Principles

The above code is a quantum model written in Qmod. A model is composed of quantum functions with at least one quantum function called main. In Python, quantum functions are defined using regular Python functions decorated with @qfunc, and in the native Qmod syntax they are defined with the qfunc keyword.

Quantum functions manipulate quantum objects which are represented using quantum variables. Every variable needs to be declared and initialized before it is used.

The following explains these principles:

1) There must be a qfunc decorator in Python or keyword in the native syntax

We can see the qfunc decorator (@qfunc) in the Python implementation, and the corresponding keyword in the native implementation. This in Qmod that we are dealing with quantum functions that manipulate quantum objects.

2) There must be a main function

Every quantum algorithm written in Qmod must have a main function. From this main function the quantum program is created using the synthesize(create_model(main)) command in Python, or just by pressing the Synthesis button in the IDE.

3) The arguments of the main function must be declared as outputs

In the above example, there are two arguments of the main function: x and y, both are quantum variables. The type of both them is QNum(qnum in the native syntax) which stands for a quantum number (see Quantum Variables). In addition to the type, the variables of the main function must be declared as output which indicates these quantum variables are not initialized outside the scope of the function.

Types of Quantum Variables In Qmod there are 3 types of quantum variables: 1. `QBit` (`qbit`) 2. `QArray[QBit]` (`qbit[]`) 3. `QNum` (`qnum`)

4) Every quantum variable needs to be declared before it is used

Here we declare the the variables x and y as arguments of the main function, but we could also declare variables in the scope of a function (see Quantum Variables).

Declaration within a Scope of a Function You can declare a quantum variable within the scope of a function with === Python x = QNum('x') === Native x:qnum;

5) Every quantum variable needs to be initialized

After a quantum variable is declared it needs to be initialized. There are several ways to initialize quantum variables, and in the above example we can see two ways:

  • x is initialized with the allocate operation.
  • y i initialized with the |= (= in native) numeric assignment.
Types of Initializations There are a few ways to initialize a quantum variable: 1. With `allocate` or `allocate_num` 2. With `prepare_int`, `prepare_state` or `prepare_amplitudes` 3. As the result of a numeric operation, like in the example above 4. With the `bind` operation (`->` in native) 5. With any function that declares its quantum variable argument as `output`

Next Steps

Now that you are familiar with the foundations of Qmod, you can continue to understand it in a bit more detail, with: * Quantum Variables and Functions * Quantum Operations * Classical Control Flow

from classiq import write_qmod

write_qmod(create_model(main), "design")