diff --git a/tests/resources/timeouts.yaml b/tests/resources/timeouts.yaml
index 6f07bc32a..2c74c4f3a 100644
--- a/tests/resources/timeouts.yaml
+++ b/tests/resources/timeouts.yaml
@@ -144,6 +144,8 @@ hamiltonian_simulation_guide_trotter.qmod: 300
hamiltonian_simulation_qsvt.qmod: 300
hamiltonian_simulation_qubitization.qmod: 300
hamiltonian_simulation_with_block_encoding.ipynb: 900
+hamming_weights.qmod: 1799
+hamming_weights_compilation_workshop.ipynb: 1799
hardware_aware_mcx.ipynb: 56
hardware_aware_mcx_all_to_all.qmod: 36
hardware_aware_mcx_grid.qmod: 10
diff --git a/tests/test_hamming_weights_compilation_workshop.py b/tests/test_hamming_weights_compilation_workshop.py
new file mode 100644
index 000000000..8e6a08ddb
--- /dev/null
+++ b/tests/test_hamming_weights_compilation_workshop.py
@@ -0,0 +1,12 @@
+from tests.utils_for_testbook import (
+ validate_quantum_program_size,
+ validate_quantum_model,
+ wrap_testbook,
+)
+from testbook.client import TestbookNotebookClient
+
+
+@wrap_testbook("hamming_weights_compilation_workshop", timeout_seconds=1801)
+def test_notebook(tb: TestbookNotebookClient) -> None:
+ # test notebook content
+ pass # Todo
diff --git a/tutorials/workshops/hamming_weights_compilation_tutorial/hamming_weights.qmod b/tutorials/workshops/hamming_weights_compilation_tutorial/hamming_weights.qmod
new file mode 100644
index 000000000..f76dda7b5
--- /dev/null
+++ b/tutorials/workshops/hamming_weights_compilation_tutorial/hamming_weights.qmod
@@ -0,0 +1,27 @@
+qstruct PermutationStruct {
+ lsb: qbit[3];
+ target: qbit;
+ msb: qbit;
+}
+
+qfunc copy_var(x: qnum, y: qnum) {
+ y ^= x;
+}
+
+qfunc set_target(target: qbit, lsb: qbit[3]) {
+ target ^= ((lsb[0] + lsb[1]) + lsb[2]) == 2;
+}
+
+qfunc unitary_permute(x: PermutationStruct) {
+ control (x.msb == 0) {
+ set_target(x.target, x.lsb);
+ }
+}
+
+qfunc main(output result: qnum, output reference: qnum) {
+ allocate(5, result);
+ allocate(5, reference);
+ hadamard_transform(result);
+ copy_var(result, reference);
+ unitary_permute(result);
+}
diff --git a/tutorials/workshops/hamming_weights_compilation_tutorial/hamming_weights.synthesis_options.json b/tutorials/workshops/hamming_weights_compilation_tutorial/hamming_weights.synthesis_options.json
new file mode 100644
index 000000000..7aa1d681c
--- /dev/null
+++ b/tutorials/workshops/hamming_weights_compilation_tutorial/hamming_weights.synthesis_options.json
@@ -0,0 +1,44 @@
+{
+ "constraints": {
+ "max_gate_count": {},
+ "optimization_parameter": "no_opt"
+ },
+ "preferences": {
+ "custom_hardware_settings": {
+ "basis_gates": [
+ "id",
+ "t",
+ "s",
+ "cz",
+ "u",
+ "rz",
+ "u1",
+ "sx",
+ "cy",
+ "u2",
+ "ry",
+ "tdg",
+ "r",
+ "cx",
+ "sxdg",
+ "rx",
+ "sdg",
+ "y",
+ "x",
+ "h",
+ "p",
+ "z"
+ ],
+ "is_symmetric_connectivity": true
+ },
+ "debug_mode": true,
+ "machine_precision": 8,
+ "optimization_level": 1,
+ "output_format": ["qasm"],
+ "pretty_qasm": true,
+ "random_seed": 192315740,
+ "synthesize_all_separately": false,
+ "timeout_seconds": 300,
+ "transpilation_option": "auto optimize"
+ }
+}
diff --git a/tutorials/workshops/hamming_weights_compilation_tutorial/hamming_weights_compilation_workshop.ipynb b/tutorials/workshops/hamming_weights_compilation_tutorial/hamming_weights_compilation_workshop.ipynb
new file mode 100644
index 000000000..0c9cc07e8
--- /dev/null
+++ b/tutorials/workshops/hamming_weights_compilation_tutorial/hamming_weights_compilation_workshop.ipynb
@@ -0,0 +1,2065 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Equal Hamming Weights, the Unitary, and Hardware Transpilation and Compilation Workshop\n",
+ "## Introduction to Classiq and Qmod\n",
+ "\n",
+ "The Classiq platform features a high-level quantum modeling language called Qmod. Qmod is compiled into concrete gate-level implementation using a powerful synthesis engine that optimizes and adapts the implementation to different target hardware/simulation environments.\n",
+ "\n",
+ "In this workshop, we will learn how to write quantum models using Qmod. We will be using the Python embedding of Qmod, available as part of the Classiq Python SDK. We will learn basic concepts in the Qmod language, such as functions, operators, quantum variables, and quantum types. \n",
+ "\n",
+ "The [Classiq webpage](https://docs.classiq.io/latest/) covers these concepts more systematically and includes more examples. For specific function you can use the [reference manual](https://docs.classiq.io/latest/qmod-reference) tab.\n",
+ "\n",
+ "For each exercise, find the solution at the bottom of the notebook.\n",
+ "\n",
+ "### Preparations\n",
+ "\n",
+ "Make sure you have a Python version of 3.9 through 3.12 installed.\n",
+ "\n",
+ "Install Classiq’s Python SDK by following the instructions on this page: [Getting Started - Classiq](https://docs.classiq.io/latest/getting-started/).\n",
+ "\n",
+ "### Designing a quantum program\n",
+ "\n",
+ "The first step in quantum software development is designing your software and 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:\n",
+ "* Directly, via the Classiq IDE using the Qmod native syntax\n",
+ "* With Classiq Python SDK package, that gives access to the Qmod language via Python\n",
+ "\n",
+ "Once you finish designing your algorithm, you send it to the Classiq synthesis engine (compiler) to create a concrete quantum circuit implementation - a quantum program.\n",
+ "\n",
+ "### Python Qmod Exercises - General Instructions\n",
+ "\n",
+ "There must be a qfunc decorator to specify this is a quantum function.\n",
+ "\n",
+ "Quantum functions manipulate quantum objects, which are represented using quantum variables. Every variable needs to be declared and initialized before it is used.\n",
+ "\n",
+ "In order to synthesize and execute your Qmod code, you should:\n",
+ "1. Make sure you define a `main` function that calls functions you create.\n",
+ "2. Use `create_model` by running `qmod = create_model(main)` to construct a representation of your model.\n",
+ "3. You can synthesize the model (using `qprog = synthesize(qmod)`) to obtain an implementation - a quantum program.\n",
+ "4. You can then visualize the quantum program (`show(qprog)`) or execute it using `execute(qprog)`. See: [Execution - Classiq](https://docs.classiq.io/latest/getting-started/classiq_tutorial/execution_tutorial/). You can also execute it with the IDE after visualizing the circuit.\n",
+ "\n",
+ "\n",
+ "Through the following example, we will explain some basic Qmod principles.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Example\n",
+ "\n",
+ "Let's get started and understand Qmod through a concrete example.\n",
+ "\n",
+ "\n",
+ "Our task is to design a quantum algorithm that computes the arithmtic operation $y=x^2+1$ coherently for a quantum variable $|x\\rangle$ that is a superposition of all the numbers between $0$ and $7$:\n",
+ "$\\begin{equation}\n",
+ "|x\\rangle = \\frac{1}{\\sqrt{8}}(|0\\rangle+|1\\rangle+\\dots +|7\\rangle.\n",
+ "\\end{equation}$\n",
+ "The expected output is \n",
+ "\n",
+ "$\\begin{equation}\n",
+ "|x\\rangle |y\\rangle = |x\\rangle |x^2+1\\rangle = \\frac{1}{\\sqrt{8}}\\sum_{i=0}^{7}|i\\rangle|i^2+1\\rangle,\n",
+ "\\end{equation}$\n",
+ "where $|x\\rangle$ is entangled to $|y\\rangle$.\n",
+ "\n",
+ "Sounds complicated? The following code in Qmod with a few lines creates the desired algorithm with Classiq:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from classiq import Output, QNum, allocate, hadamard_transform, qfunc\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def main(x: Output[QNum], y: Output[QNum]):\n",
+ "\n",
+ " allocate(4, x)\n",
+ " hadamard_transform(x) # creates a uniform superposition\n",
+ " y |= x**2 + 1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "The desired quantum program can be synthesized and viewed:\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "4",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Quantum program link: https://platform.classiq.io/circuit/37qCCeymbWDrQLQlbCp251a7bG4\n"
+ ]
+ }
+ ],
+ "source": [
+ "from classiq import create_model, show, synthesize\n",
+ "\n",
+ "quantum_program = synthesize(create_model(main))\n",
+ "show(quantum_program)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "and also executed:\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "6",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[{'x': 10, 'y': 101}: 142,\n",
+ " {'x': 2, 'y': 5}: 140,\n",
+ " {'x': 12, 'y': 145}: 136,\n",
+ " {'x': 6, 'y': 37}: 135,\n",
+ " {'x': 4, 'y': 17}: 133,\n",
+ " {'x': 14, 'y': 197}: 133,\n",
+ " {'x': 8, 'y': 65}: 132,\n",
+ " {'x': 1, 'y': 2}: 130,\n",
+ " {'x': 5, 'y': 26}: 129,\n",
+ " {'x': 13, 'y': 170}: 129,\n",
+ " {'x': 7, 'y': 50}: 125,\n",
+ " {'x': 15, 'y': 226}: 119,\n",
+ " {'x': 0, 'y': 1}: 117,\n",
+ " {'x': 3, 'y': 10}: 117,\n",
+ " {'x': 9, 'y': 82}: 116,\n",
+ " {'x': 11, 'y': 122}: 115]"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from classiq import execute\n",
+ "\n",
+ "results = execute(quantum_program).result()\n",
+ "results[0].value.parsed_counts"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7",
+ "metadata": {},
+ "source": [
+ "## Part 1 - Apply Unitary \n",
+ "\n",
+ "General guideline to this workshop -- uncomment the relevant exercise block when implementing it, and fill in the missing code.\n",
+ "We will look at two approaches to implement the use case.\n",
+ "The first is brute force, which works on any Unitary. Here, only transpilation is used. Many times, more optimizations are applied.\n",
+ "In the second approach, we will look at the logic of the permutation and implement it.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8",
+ "metadata": {},
+ "source": [
+ "### Task 1 - Apply Unitary Operator\n",
+ "\n",
+ "Here, you will need to define a quantum function that applies a given unitary operator to a set of qubits. The unitary operator is given as a matrix. The function should take a set of qubits and apply the unitary operator to them.\n",
+ "Please note the following points:\n",
+ "\n",
+ "* In Qmod, there are three types of quantum variables: `QBit`, `QNum`, `QArray[QBit]` (or a `QArray` of any other quantum type). See [quantum variables](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-variables) and [quantum types](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types).\n",
+ "* Ensure you allocate the qubits before applying the unitary operator. See [allocate](https://docs.classiq.io/latest/qmod-reference/api-reference/operations/?h=allocate#classiq.qmod.builtins.operations.allocate).\n",
+ "* The unitary operator is given as a matrix. You can use the `unitary` function to apply the unitary operator to the qubits. See [unitary](https://docs.classiq.io/latest/explore/functions/qmod_library_reference/qmod_core_library/unitary/unitary/?h=unitary).\n",
+ "* See also explanation on the [main](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-entry-point) and on quantum [functions](https://docs.classiq.io/latest/qmod-reference/language-reference/functions).\n",
+ "\n",
+ "Use the following unitary matrix:\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "UNITARY = [\n",
+ " [\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " 0,\n",
+ " ],\n",
+ " [\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 0,\n",
+ " 1,\n",
+ " ],\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from classiq import *\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def main(x: Output[QArray[QBit]]):\n",
+ " # Use allocate to allocate 5 qubits (it's a (2**5=32)x32 matrix)\n",
+ " # Use unitary to apply the UNITARY operator to the qubits\n",
+ " pass # delete the \"pass\" call and add your code here"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "11",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Uncomment the following lines:\n",
+ "\n",
+ "# qmod = create_model(main)\n",
+ "# qprog = synthesize(qmod)\n",
+ "# show(qprog)\n",
+ "\n",
+ "# print(\"depth:\", qprog.transpiled_circuit.depth, \"width:\", qprog.data.width)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "12",
+ "metadata": {},
+ "source": [
+ "### Task 2 - Explore Hardware-Aware Synthesis\n",
+ "\n",
+ "In this exercise, you will explore the hardware-aware synthesis feature of Classiq. This feature allows you to synthesize quantum programs for specific quantum hardware. You can specify the backend service provider and the backend name in the preferences of the model.\n",
+ "\n",
+ "Uncomment the commented lines in the code below and fill in a backend service provider and a backend name. Then, synthesize the quantum program and print the depth and width of the transpiled circuit. You can see the available backends in the Classiq IDE execution tab. You can look at it in the context of the previous exercise. \n",
+ "\n",
+ "Synthesize for the Azure Quantum backend service provider and the some IBM backend name, and then for IonQ and qpu.aria-1.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# qmod = create_model(\n",
+ "# entry_point=main,\n",
+ "# preferences=Preferences(\n",
+ "# backend_service_provider=\"\",\n",
+ "# backend_name=\"\"\n",
+ "# ),\n",
+ "# )\n",
+ "\n",
+ "# synthesize\n",
+ "# show\n",
+ "# print depth and width"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "14",
+ "metadata": {},
+ "source": [
+ "## Part 2 - Build the Quantum Logic\n",
+ "In the this approach, we will look at the logic of the permutation and implement it. This approach shows the power of the Qmod language in expressing quantum algorithms.\n",
+ "\n",
+ "### Task 1 - Understand the Unitary\n",
+ "Observe the unitary matrix and understand the permutation it represents. \n",
+ "* How many qubits are there? How many states are there?\n",
+ "* What does the permutation do? Which states does it operate on? Write down the permutation in terms of the states it operates on.\n",
+ "* Translate it to binary representation. What are the bits that change? What are the bits that remain the same? Wh\n",
+ "\n",
+ "Write down your answers and plan your implementation. You may use the given hints for help.\n",
+ "The next task will guide you through a possible implementation. SPOILER ALERT! Proceed to the next task only when you're ready."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "15",
+ "metadata": {},
+ "source": [
+ "\n",
+ " Hint -- what does the unitary do?
\n",
+ "\n",
+ "It switches between the states: 3 and 11, 5 and 13, and 6 and 14 \n",
+ " \n",
+ "3 = 00011, 11 = 01011,\n",
+ "5 = 00101, 13 = 01101,\n",
+ "6 = 00110, 14 = 01110,\n",
+ " \n",
+ " - 00011 -- 01011\n",
+ " - 00101 -- 01101\n",
+ " - 00110 -- 01110\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "16",
+ "metadata": {},
+ "source": [
+ "\n",
+ " Hint -- observations
\n",
+ " \n",
+ " 1. What states does the permutation operator on? In all of them (on the left-hand side), there are two 1s in the three least significant bits.\n",
+ " 2. These three least significant bits are the same before and after the permutation.\n",
+ " 3. Therefore, we can see that the permutation is a bit flip of the 4th qubit, in specific situations.\n",
+ " 4. This flip happens only if the 5th qubit is 0, and if there are two 1s and one 0 in the 1st, 2nd and 3rd qubits together.\n",
+ "\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17",
+ "metadata": {},
+ "source": [
+ "### Task 2 - The Quantum Building Blocks\n",
+ "Now that we have observed what this Unitary does, we will build the quantum building blocks for it. \n",
+ "We need to flip the 4th qubit if (1) the 5th qubit is 0, and (2) if there are two 1s and one 0 in the 1st, 2nd and 3rd qubits together.\n",
+ "\n",
+ "Let's plan the implementation:\n",
+ "1. We will need to allocate 5 qubits.\n",
+ "2. We will need to define relevant quantum variables on these qubits (MSB - 5th, target_flip - 4th, LSBs - 1st to 3rd).\n",
+ "3. We will use quantum control-flow to determine if the MSB qubit is 0.\n",
+ "4. We will use quantum arithmetics to determine if the LSBs have two 1s and one 0, and if so we'll flip the target_flip qubit.\n",
+ "\n",
+ "Now, let's implement the logic in Qmod. \n",
+ "We will first learn how to use the Classiq Platform to create the different building blocks.\n",
+ "We will tie all them together in the next task."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "18",
+ "metadata": {},
+ "source": [
+ "#### Quantum Variables (1 and 2)\n",
+ "\n",
+ "Uncomment block and fill in the relevant missing code blocks\n",
+ "\n",
+ "Define a Qstruct that represents the permutation. The Qstruct should have the following quantum variables: MSB, target_flip, and LSBs. These should be of the appropriate quantum types. See more on [QStruct](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types/?h=qstruct#examples_3).\n",
+ "Also, define a main and allocate 5 qubits in it. When you execute this function, you can see the quantum variables in the quantum program results."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "19",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# from classiq import *\n",
+ "#\n",
+ "# class PermutationStruct(QStruct):\n",
+ "# # Define the quantum variables here\n",
+ "#\n",
+ "# @qfunc\n",
+ "# def main(result: Output[PermutationStruct]):\n",
+ "# # allocate 5 qubits into the result variable\n",
+ "#\n",
+ "# qmod = create_model(main)\n",
+ "# qprog = synthesize(qmod)\n",
+ "# show(qprog)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "20",
+ "metadata": {},
+ "source": [
+ "#### Quantum Control-Flow (3)\n",
+ "Now, we will learn the use of control flow. In the next task, we will adapt it to our the Unitary application.\n",
+ "The `control` operator is the conditional operation, with the condition being that the control qubit is in the state |1>, then an operation is applied on the second qubit. This notion is generalized in QMOD to other control states, where the condition is specified as a comparison between a quantum numeric variable, symbolic expression, `QArray` for example the [multi-control gates](https://github.com/Classiq/classiq-library/blob/main/functions/function_usage_examples/mcx/mcx_example.ipynb) and `QBit` (for simple control operation) and a numeric value.\n",
+ " **It is very similar to a classical `if` statement.** Quantum numeric variables are declared with class `QNum`.\n",
+ "\n",
+ "See also [Numeric types](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types).\n",
+ "\n",
+ "In QMOD, this generalization is available as a native `control` function.\n",
+ "\n",
+ "See also [control](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/control), and follow the instructions:\n",
+ "\n",
+ "1. Declare a `QNum` output argument using `Output[QNum]` and name it `x`.\n",
+ "2. Use the `|=` inplace allocation function to initialize it to `9`. Note that you don't need to specify the `QNum` attributes - size, sign, and fraction digits, as they are inferred at the point of initialization.\n",
+ "3. Execute the circuit and observe the results.\n",
+ "4. Declare another output argument of type `QBit` and perform a `control` such that under the condition that `x` is 9, the qubit is flipped. Execute the circuit and observe the results. Repeat for a different condition.\n",
+ "\n",
+ "Example of control: `control(ctrl = x==1, operand = lambda: H(q))` where `q` is a qubit.\n",
+ "The `control` is applied only for states that `x==1` and apply a `H` gate on it.\n",
+ "\n",
+ "**Fill in the missing parts and uncomment the last lines of the synthesis to see the circuit.**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "21",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from classiq import *\n",
+ "\n",
+ "\n",
+ "# Your code here:\n",
+ "@qfunc\n",
+ "def main(x: Output[QNum], target: Output[QBit]) -> None:\n",
+ " # Make an integer of the x\n",
+ " # Allocate the target register to have 1 qubit\n",
+ " # Use control that accept control(ctrl = , operand = )\n",
+ " # In the operand, use the lambda function using the X gate\n",
+ " # Your code here:\n",
+ " pass\n",
+ "\n",
+ "\n",
+ "# qmod = create_model(main)\n",
+ "# qprog = synthesize(qmod)\n",
+ "# show(qprog)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "22",
+ "metadata": {},
+ "source": [
+ "#### Quantum arithmetics (4)\n",
+ "In this exercise, we will use quantum numeric variables and calculate expressions over them.\n",
+ "\n",
+ "See details on the syntax of numeric types under [Quantum types](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types).\n",
+ "See more on quantum expressions under [Numeric assignment](https://docs.classiq.io/latest/qmod-reference/language-reference/statements/numeric-assignment).\n",
+ "\n",
+ "Create the following quantum programs:\n",
+ "1. Initialize variables `x=5`, `y=7` and computes `res = x + y`.\n",
+ "\n",
+ "Guidance:\n",
+ "* Use the operator `|=` to perform out-of-place assignment of arithmetic expression.\n",
+ "* To initialize the variables, use the function `prepare_int`.\n",
+ "\n",
+ "See an example:\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "23",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Quantum program link: https://platform.classiq.io/circuit/37qCDBMqW7YcMc46p1DxHWeJwno\n"
+ ]
+ }
+ ],
+ "source": [
+ "from classiq import *\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def main(res: Output[QNum]):\n",
+ " x = QNum(\"x\")\n",
+ " y = QNum(\"y\")\n",
+ " x |= 5\n",
+ " y |= 7\n",
+ " res |= x + y\n",
+ "\n",
+ "\n",
+ "qmod = create_model(main)\n",
+ "qprog = synthesize(qmod)\n",
+ "show(qprog)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "24",
+ "metadata": {},
+ "source": [
+ "Create the following quantum programs:\n",
+ "1. Initialize variables `x=2`, `y=7` and computes `res = x + y`.\n",
+ "2. Initialize variables `x=2`, `y=7` and computes `res = x * y`.\n",
+ "3. Initialize variables `x=2`, `y=7`, `z=1` and computes `res = x * y - z`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "25",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# from classiq import *\n",
+ "#\n",
+ "#\n",
+ "# @qfunc\n",
+ "# def main(res: Output[QNum]):\n",
+ "# pass # your code here\n",
+ "#\n",
+ "#\n",
+ "# qmod = create_model(main)\n",
+ "# qprog = synthesize(qmod)\n",
+ "# show(qprog)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "26",
+ "metadata": {},
+ "source": [
+ "### Task 3 - Tie it all together\n",
+ "\n",
+ "Uncomment block and fill in the relevant missing code blocks.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "27",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# from classiq import *\n",
+ "#\n",
+ "# class PermutationStruct(QStruct):\n",
+ "# pass\n",
+ "# # Define the quantum variables here\n",
+ "#\n",
+ "# # Implement a quantum function that receives two variable: a qubit and a quantum-array.\n",
+ "# # This function will check if the quantum-array has two 1s and one 0, and if so, flip the qubit.\n",
+ "# @qfunc\n",
+ "# def set_target(target: QBit, lsb: QArray[QBit, 3]):\n",
+ "# # Sum up the values in the array and compare it to the needed value\n",
+ "# # Flip the target qubit if the condition is met\n",
+ "# pass # delete the \"pass\" call and add your code here\n",
+ "#\n",
+ "# @qfunc\n",
+ "# def unitary_permute(x: PermutationStruct):\n",
+ "# # Use control to call the \"set_target\" function, if the MSB is 0\n",
+ "# pass # delete the \"pass\" call and add your code here\n",
+ "#\n",
+ "# @qfunc\n",
+ "# def main(result: Output[QNum]):\n",
+ "# pass\n",
+ "# # allocate 5 qubits into the result variable\n",
+ "#\n",
+ "# # call unitary_permute to apply unitary logic. Notice the implicit cast done here.\n",
+ "#\n",
+ "#\n",
+ "# qmod = create_model(main)\n",
+ "# qprog = synthesize(qmod)\n",
+ "# show(qprog)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "28",
+ "metadata": {},
+ "source": [
+ "### Task 4 - Make sure it works as expected\n",
+ "\n",
+ "Now we want to make sure the permutation does as expected. For that, we will use the hadamard function to create a superposition of all the states and then copy the result to another variable. We will then apply the permutation and check if the quantum state is permuted as expected. For that, please see: [repeat](https://docs.classiq.io/latest/qmod-reference/api-reference/operations/?h=repeat#classiq.qmod.builtins.operations.repeat), [hadamard transform](https://docs.classiq.io/latest/explore/functions/qmod_library_reference/classiq_open_library/hadamard_transform/hadamard_transform/?h=hadam)\n",
+ "\n",
+ "Uncomment block and fill in the relevant missing code blocks."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "29",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# # Part 2 full solution test functionality\n",
+ "# from classiq import *\n",
+ "#\n",
+ "# # Use these three functions from the previous tasks\n",
+ "#\n",
+ "# # class PermutationStruct(QStruct):\n",
+ "# #\n",
+ "# # @qfunc\n",
+ "# # def set_target(target: QBit, lsb: QArray[QBit, 3]):\n",
+ "# #\n",
+ "# # @qfunc\n",
+ "# # def unitary_permute(x: PermutationStruct):\n",
+ "#\n",
+ "# @qfunc\n",
+ "# def copy_var(x: QNum, y: QNum):\n",
+ "# # copy the state of x to y - create an entanglement between the two states\n",
+ "#\n",
+ "# @qfunc\n",
+ "# def main(result: Output[QNum], reference: Output[QNum]):\n",
+ "# # allocate 5 qubits into the result variable\n",
+ "#\n",
+ "# # perform the reference trick:\n",
+ "# # allocate 5 qubits into the reference variable\n",
+ "# # hadamard_transform the result variable\n",
+ "# # copy the result variable to the reference variable\n",
+ "#\n",
+ "# # call unitary_permute to apply unitary logic. Notice the implicit cast done here.\n",
+ "#\n",
+ "#\n",
+ "# qmod = create_model(main)\n",
+ "# qprog = synthesize(qmod)\n",
+ "# show(qprog)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "30",
+ "metadata": {},
+ "source": [
+ "### Task 5 - Re-Explore Hardware-Aware Synthesis \n",
+ "Explore the results of different properties of the quantum program with the hardware-aware synthesis feature.\n",
+ "You can also explore the power of the synthesis engine with different optimization parameters, such as \"depth\" and \"width\", and the trade-offs between them.\n",
+ "\n",
+ "Uncomment block and fill in the relevant missing code blocks."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "31",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# qmod = create_model(\n",
+ "# entry_point=main,\n",
+ "# preferences=Preferences(\n",
+ "# backend_service_provider=\"\", # fill in the backend service provider\n",
+ "# backend_name=\"\", # fill in the backend name\n",
+ "# ),\n",
+ "# constraints=Constraints(optimization_parameter=\"depth\") # \"width\"\n",
+ "# )\n",
+ "# qprog = synthesize(qmod)\n",
+ "# show(qprog)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "32",
+ "metadata": {},
+ "source": [
+ "## Solutions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "33",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Quantum program link: https://platform.classiq.io/circuit/37qCDjUR6ktAn8Tw0RaR6fIC4F5\n",
+ "depth: 638 width: 5\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Part 1\n",
+ "\n",
+ "from classiq import *\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def main(x: Output[QArray[QBit]]):\n",
+ " allocate(5, x)\n",
+ " unitary(UNITARY, x)\n",
+ "\n",
+ "\n",
+ "qmod = create_model(\n",
+ " entry_point=main,\n",
+ " preferences=Preferences(\n",
+ " backend_service_provider=\"IonQ\", # Azure Quantum\n",
+ " backend_name=\"qpu.forte-1\", # ankaa-2\n",
+ " ),\n",
+ ")\n",
+ "qprog = synthesize(qmod)\n",
+ "show(qprog)\n",
+ "\n",
+ "print(\"depth:\", qprog.transpiled_circuit.depth, \"width:\", qprog.data.width)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "34",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Quantum program link: https://platform.classiq.io/circuit/37qCE5yIN5OwS1lGhENvdE5HkRi\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Part 2 - tasks 2 - variables\n",
+ "\n",
+ "from classiq import *\n",
+ "\n",
+ "\n",
+ "class PermutationStruct(QStruct):\n",
+ " lsb: QArray[QBit, 3]\n",
+ " target: QBit\n",
+ " msb: QBit\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def main(result: Output[PermutationStruct]):\n",
+ " allocate(5, result)\n",
+ "\n",
+ "\n",
+ "qmod = create_model(main)\n",
+ "qprog = synthesize(qmod)\n",
+ "show(qprog)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "35",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Quantum program link: https://platform.classiq.io/circuit/37qCELQC1eg7ndTnVPaPASYUavB\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Part 2 - tasks 2 - control flow\n",
+ "\n",
+ "from classiq import *\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def main(x: Output[QNum], target: Output[QBit]) -> None:\n",
+ " x |= 9\n",
+ " allocate(1, target)\n",
+ " control(x == 9, lambda: X(target))\n",
+ "\n",
+ "\n",
+ "model = create_model(main)\n",
+ "qprog = synthesize(model)\n",
+ "show(qprog)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "id": "36",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Quantum program link: https://platform.classiq.io/circuit/37qCElGvAA0kLCFu2eWdtMSWndq\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Part 2 - tasks 2 - arithmetics\n",
+ "\n",
+ "from classiq import *\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def main(res: Output[QNum]) -> None:\n",
+ " x = QNum(\"x\")\n",
+ " y = QNum(\"y\")\n",
+ " z = QNum(\"z\")\n",
+ " x |= 2\n",
+ " y |= 7\n",
+ " z |= 1\n",
+ " # res |= x + y\n",
+ " # res |= x * y\n",
+ " res |= x * y - z\n",
+ "\n",
+ "\n",
+ "model = create_model(main)\n",
+ "qprog = synthesize(model)\n",
+ "show(qprog)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "id": "37",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Quantum program link: https://platform.classiq.io/circuit/37qCFBRzEInrNKRXsBsdflmgoP6\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Part 2 tie it all together full solution\n",
+ "from classiq import *\n",
+ "\n",
+ "\n",
+ "class PermutationStruct(QStruct):\n",
+ " lsb: QArray[QBit, 3]\n",
+ " target: QBit\n",
+ " msb: QBit\n",
+ "\n",
+ "\n",
+ "# Generic solution for set_target:\n",
+ "# @qfunc(generative=True)\n",
+ "# def set_target(target: QBit, lsb: QArray[QBit, 3]):\n",
+ "# target ^= (sum([lsb[i] for i in range(lsb.size)]) == 2)\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def set_target(target: QBit, lsb: QArray[QBit, 3]):\n",
+ " target ^= lsb[0] + lsb[1] + lsb[2] == 2\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def unitary_permute(x: PermutationStruct):\n",
+ " control(x.msb == 0, lambda: set_target(x.target, x.lsb))\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def main(result: Output[QNum]):\n",
+ " allocate(5, result)\n",
+ "\n",
+ " # apply unitary logic\n",
+ " unitary_permute(result)\n",
+ "\n",
+ "\n",
+ "qmod = create_model(main)\n",
+ "qprog = synthesize(qmod)\n",
+ "show(qprog)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "id": "38",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Quantum program link: https://platform.classiq.io/circuit/37qCFMVG1COwexa5wWVYHrmoWYC\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Part 2 full solution test functionality\n",
+ "from classiq import *\n",
+ "\n",
+ "\n",
+ "class PermutationStruct(QStruct):\n",
+ " lsb: QArray[QBit, 3]\n",
+ " target: QBit\n",
+ " msb: QBit\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def copy_var(x: QNum, y: QNum):\n",
+ " # Another solution: repeat(x.len, lambda i: CX(x[i], y[i]))\n",
+ " y ^= x\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def set_target(target: QBit, lsb: QArray[QBit, 3]):\n",
+ " target ^= lsb[0] + lsb[1] + lsb[2] == 2\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def unitary_permute(x: PermutationStruct):\n",
+ " control(x.msb == 0, lambda: set_target(x.target, x.lsb))\n",
+ "\n",
+ "\n",
+ "@qfunc\n",
+ "def main(result: Output[QNum], reference: Output[QNum]):\n",
+ " allocate(5, result)\n",
+ "\n",
+ " # reference trick\n",
+ " allocate(5, reference)\n",
+ " hadamard_transform(result)\n",
+ " copy_var(result, reference)\n",
+ "\n",
+ " # apply unitary logic\n",
+ " unitary_permute(result)\n",
+ "\n",
+ "\n",
+ "qmod = create_model(main)\n",
+ "write_qmod(\n",
+ " qmod,\n",
+ " \"hamming_weights\",\n",
+ " decimal_precision=15,\n",
+ ")\n",
+ "qprog = synthesize(qmod)\n",
+ "show(qprog)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "id": "39",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Quantum program link: https://platform.classiq.io/circuit/37qCFpJ1ecHgLggAtuctZfGoWUl\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Part 2 - tasks 5 - hardware-aware synthesis\n",
+ "\n",
+ "qmod = create_model(\n",
+ " entry_point=main,\n",
+ " # preferences=Preferences(\n",
+ " # backend_service_provider=\"Azure Quantum\",\n",
+ " # backend_name=\"rigetti.qpu.ankaa-2\",\n",
+ " # ),\n",
+ " constraints=Constraints(optimization_parameter=\"depth\"), # \"width\"\n",
+ ")\n",
+ "qprog = synthesize(qmod)\n",
+ "show(qprog)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 9
+}