Application notes

Designing and Implementing Quantum Algorithms with Functional Level Programming



Functional level modeling is the core difference between the existing methods of gate-based quantum circuit construction.

In this application note, we’ll learn how simple it is to design algorithms using the Classiq Platform. Let’s start with one of the most fundamental building blocks in quantum algorithms design: the state preparation. The state we want to generate is the following distribution of probabilities over 8 possible states:

probabilities = [0.4, 0.05, 0.2, 0.05, 0.3, 0, 0, 0]

Because the probability vector is over 8 possible states, we know that the register that stores the values contains 3 qubits (23=8).

Final Circuit

Let’s start at the end, with the final circuit we will create, and then go through the process of building it. At the high level, which is the level we will design it, the circuit is represented by simply what we want it to do - prepare a state using 3 qubits.

This block is implemented by some underlying gates the Classiq Platform will automatically synthesize according to the functionality we define. The underlying circuit is seen below, with more functional level blocks exposed.

We can better understand this circuit by expanding another block. The core concept behind functional level programming is designing at the most abstract level and letting the Classiq Platform calculate the best implementation of such a design in the lower, gate-based levels.

How to Build a Functional Model

With the Classiq Platform, we build functional models of the quantum algorithm, and then we let the platform synthesize the optimized circuit for the given models.

For any algorithm, be it the simplest or the most complex one, the model is built in the Classiq IDE according to three simple steps:

  1. Defining the functional blocks - in our example we have only 1 functional block, the state preparation.
  2. Defining a high-level functional model that will contain the functional blocks.
  3. Wiring the blocks within the high-level functional model.

First, we should confirm we have the right Classiq version and are in the proper working environment. Though the functionality is equivalent with the Classiq Python SDK, this application note will feature our Classiq Integrated Development Environment (IDE).

0. Entering the Classiq Platform

The Classiq IDE is available at with access limited to authenticated academic and enterprise users.

Once access is confirmed, login by clicking the icon in the top-right corner. This will pop up a sign in screen, where the credentials entered must match the credentials given for authentication.

Upon successfully logging in, the IDE screen will show four main sections.

  • The sidebar on the left (gray) indicates synthesis, circuit view and analysis, and execution - currently displaying synthesis, where we design our algorithms.
  • The upload section (yellow) allows users to bring already created models into the Classiq Platform.
  • The model section (pink) is where our designing occurs, with models consisting of constraints that limit our circuits’ size, accuracy, and so on and the logic flow that indicates what functionality our circuits will have or what problems they solve.
  • The application suites and customization panel (blue) has examples and parameters for users to customize their algorithms.

1. Defining The Functional Block - Logic Flow

The functional block we have is the state preparation. We will define a StatePreparation object that encapsulates the functionality we want within the logic flow of our model. This object receives parameters, such as the desired probability distribution and an upper bound for an error of the implementation (since usually there is a trade-off between the accuracy of the implementation and the number of qubits and/or depth of the circuit).

The final circuit implements the desired probability distribution with an error, in this case - the Kullback-Leibler divergence, which is bounded by the 0.1 upper bound given. This is a measure of how close our circuit’s resulting probabilities are to those we defined.

"logic_flow": [
      "function": "StatePreparation",
      "function_params": {
        "probabilities": [
        "error_metric": {
          "KL": {
            "upper_bound": 0.1

 2. Defining the High-Level Functional Model - Hardware Constraints

The high-level functional model encapsulates the functionality of our algorithm - specifically the StatePreparation block we have defined. The model is stored within the .json code block consisting of the logic flow we defined already, as well as any hardware constraints; in this case, we’re preventing any circuits with more than 12 qubits or more than 200 gates on the most used qubit from being synthesized.

We can add these constraints by typing the following code or by entering the values in the constraints customization section on the right panel, which automatically adjusts the model’s code.

"constraints": {
    "max_width": 12,
    "max_depth": 200

 3. Wiring the Blocks within the High-Level Functional Model

Within the IDE, we combine or wire our functional blocks together in the logic flow, and as we have only one function (our StatePreparation), our model is fully designed and ready for synthesis. We’ll see more sophisticated examples in upcoming application notes showing the wiring of functions together, with many sample programs available on our documentation.

To synthesize our circuit, simply click the Synthesize button in the lower right corner.

That’s it! We have our circuit, and we can explore the functional levels by interacting with the plus/minus icons on the circuit or using the toolbar on the right.

Executing a Functional Model

 Now we can execute our circuit to get the measurement results. When we navigate to the Execution tab, we see all of the hardware options listed with vendor - IBM Quantum, Azure Quantum, AWS Braket, IonQ, or NVIDIA - and type - simulator or hardware - filters.

Let’s choose the ibm_qasm_simulator, use 1000 shots, and click “Run.”

We can see a progress bar as the circuit executes, and then our results display.

Our measurement counts are seen in the histogram, and we can also download our execution results as a .json file with more information.


With little effort or understanding of the gate-based level of our algorithm, we were able to define what we want performed at the highest level and use the Classiq Platform to synthesize the circuit for us. In this application note, we learned what functional level programming is and designed a simple state preparation algorithm with the Classiq IDE. For more information about the Classiq Platform, visit our website or our documentation or schedule a demo.

See Also

No items found.

Start Creating Quantum Software Without Limits

contact us