diff --git a/community/QClass_2024/Submissions/HW1/Yasir_Mansour_HW1_QClass2024.ipynb b/community/QClass_2024/Submissions/HW1/Yasir_Mansour_HW1_QClass2024.ipynb new file mode 100644 index 00000000..725ecf86 --- /dev/null +++ b/community/QClass_2024/Submissions/HW1/Yasir_Mansour_HW1_QClass2024.ipynb @@ -0,0 +1,581 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "XtC66r2Y5_eT", + "tags": [] + }, + "source": [ + "# The Qmod Workshop - Introduction\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. We will develop useful building blocks and small algorithms.\n", + "\n", + "The QMOD language reference(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/) covers these concepts more systematically and includes more examples.\n", + "\n", + "This workshop consists of step-by-step exercises. It is structured as follows:\n", + "\n", + "- Part 1: Language Fundamentals - Exercises 1-5\n", + "- Part 2: Higher-Level Concepts - Exercises 6-10\n", + "- Part 3: Execution Flows - Exercises 11, 12\n", + "\n", + "The introduction and Part 1 are included in this notebook. Part 2 and 3 are each in its own separate notebook. For each exercise you will find the solution to the exercises at the bottom of the same notebook.\n", + "\n", + "### Preparations\n", + "\n", + "Make sure you have a Python version of 3.8 through 3.11 installed. Unfortunately, Classiq is not yet supported with Python 3.12.\n", + "\n", + "Install Classiq’s Python SDK by following the instructions on this page: Getting Started - Classiq(docs.classiq.io/latest/getting-started/).\n", + "\n", + "### Python Qmod Exercises - General Instructions\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(docs.classiq.io/latest/user-guide/platform/executor/#full-example)). You can also execute it with the IDE after visualizing the circuit.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "RatBmdhm5_e2" + }, + "source": [ + "### Exercise 0: From Model to Execution\n", + "\n", + "The following model defines a function that applies X and H gates on a single qubit, and subsequently calls it:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "DpF2vKUh5_e7", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "\n", + "# Define a quantum function using the @qfunc decorator\n", + "@qfunc\n", + "def qfn(q: QBit) -> None:\n", + " X(target=q)\n", + " H(target=q)\n", + "\n", + "\n", + "# Define a main function\n", + "@qfunc\n", + "def main(res: Output[QBit]) -> None:\n", + " allocate(1, res)\n", + " qfn(q=res)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "NXh4E69A5_fC" + }, + "source": [ + "Create a model from it, and synthesize, visualize, and execute it.\n", + "\n", + "Use the General Instructions above to do so.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "UB612BIP5_fE", + "outputId": "6658d861-fccb-4acb-8bf2-1b52dee5b6c4", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)\n", + "execute(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "s3CXWd3V5_fF" + }, + "source": [ + "In Qmod `QBit` is the simplest quantum type, and in this example, `q` is a quantum variable of type `QBit`. Quantum variables abstract away the mapping of quantum objects to qubits in the actual circuit.\n", + "\n", + "See also Quantum Variables(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/quantum-variables/).\n", + "\n", + "We will discuss other quantum types during the workshop.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "wtQE208K5_fH" + }, + "source": [ + "# The Qmod Workshop - Part 1: Language Fundamentals\n", + "\n", + "Follow exercises 1 through 5 for the first session of the workshop." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "8jM3lrC15_fI" + }, + "source": [ + "## Exercise 1 - Bell Pair\n", + "\n", + "Create a function that takes two single-qubit (`QBit`) quantum arguments and prepares the bell state on them (Bell state(en.wikipedia.org/wiki/Bell_state)) by applying `H` on one variable and then using it as the control of a `CX` function with the second variable as the target.\n", + "Create a main function that uses this function and has two single-qubit outputs, initialize them to the |0> state (using the `allocate` function), and apply your function to them.\n", + "\n", + "See also Functions(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/functions#syntax)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "fNOTP83I5_fJ", + "outputId": "4c0a03a2-6f67-4c15-957e-261b56f1ad91", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "# Define a quantum function using the @qfunc decorator\n", + "@qfunc\n", + "def bell(q1: QBit, q2: QBit) -> None:\n", + " H(target=q1)\n", + " CX(control=q1,target=q2)\n", + "\n", + "# Define a main function\n", + "@qfunc\n", + "def main(res1: Output[QBit], res2: Output[QBit]) -> None:\n", + " allocate(1, res1)\n", + " allocate(1, res2)\n", + " bell(q1=res1,q2=res2)\n", + "\n", + "# Your code here:\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)\n", + "execute(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AY_kkbyi5_fM" + }, + "source": [ + "Use qubit array subscript (the syntax - _variable_ **[** _index-expression_ **]**) to change the function from subsection 1 to receive a single quantum variable, a qubit array (`QArray`) of size 2.\n", + "Change your main function to declare a single output (also an array of size 2).\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "Y-c9r6OT5_fO", + "outputId": "8a2a41c7-bcee-4765-8906-4b7026bf3b71", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "# Define a quantum function using the @qfunc decorator\n", + "@qfunc\n", + "def bell(q: QArray) -> None:\n", + " H(target=q[0])\n", + " CX(control=q[0],target=q[1])\n", + "\n", + "# Define a main function\n", + "@qfunc\n", + "def main(res: Output[QArray]) -> None:\n", + " allocate(2, res)\n", + " bell(res)\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)\n", + "execute(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "SoXeCLcX5_fQ" + }, + "source": [ + "## Exercise 2 - Repeat\n", + "\n", + "Use the built-in `repeat` operator to create your own Hadamard transform function (call it `my_hadamard_transform`). The Hadamard transform function is a function that takes as argument a qubit array of an unspecified size and applies `H` to each of its qubit.\n", + "\n", + "See also Classical repeat(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/classical-control-flow/#classical-repeat).\n", + "\n", + "Set your main function to have a quantum array output of unspecified size, allocate 10 qubits, and then apply your Hadamard transform function.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "vFrcPTqi5_fS", + "outputId": "48c6573f-ba4d-4c47-b65f-dd2204818e8e", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "@qfunc\n", + "def my_hadamard(q: QArray) -> None:\n", + " repeat(count=q.len, iteration=lambda i: H(target=q[i]))\n", + "\n", + "# Define a main function\n", + "@qfunc\n", + "def main(res: Output[QArray]) -> None:\n", + " allocate(10, res)\n", + " my_hadamard(res)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)\n", + "execute(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "98liCUg15_fT" + }, + "source": [ + "### Note: Quantum Variable Capture\n", + "The `repeat` operator invokes a statement block multiple times. The statement block is specified using a Python callable, typically a lambda expression. Inside the block you can refer to variables declared in the outer function scope.\n", + "This concept is called `quantum variable capture`, equivalent to capture(en.wikipedia.org/wiki/Closure_(computer_programming)) in classical languages.\n", + "\n", + "See also Capturing context variables and parameters(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/operators/#capturing-context-variables-and-parameters)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "fonXAiHP5_fU" + }, + "source": [ + "### Exercise 3 - Power\n", + "Raising a quantum operation to a power appears in many known algorithms, for examples, in Grover search and Quantum Phase Estimation.\n", + "For most operations, it simply means repeating the same circuit multiple times.\n", + "\n", + "Sometimes, however, power can be simplified, thus saving computational resources.\n", + "The most trivial example is a quantum operation expressed as a single explicit unitary matrix (i.e., all n*n matrix terms are given) - raising the operation can be done by raising the matrix to that power via classical programming.\n", + "\n", + "See also Power operator(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/quantum-operators/#syntax).\n", + "\n", + "Use the following code to generate a 2-qubit (real) unitary matrix:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "tD_aBHoU5_fW", + "tags": [] + }, + "outputs": [], + "source": [ + "from typing import List\n", + "\n", + "import numpy as np\n", + "\n", + "from classiq import *\n", + "\n", + "rng = np.random.default_rng(seed=0)\n", + "random_matrix = rng.random((4, 4))\n", + "qr_unitary, _ = np.linalg.qr(random_matrix)\n", + "\n", + "unitary_matrix = QConstant(\"unitary_matrix\", List[List[float]], qr_unitary.tolist())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "yRWVHm1O5_fY" + }, + "source": [ + "In order to reuse some classical value we can define a `QConstant` to store that value.\n", + "\n", + "1. Create a model that applies `unitary_matrix` on a 2 qubit variable.\n", + "2. Create another model that applies `unitary_matrix` raised to power 3 on a 2 qubit variable.\n", + "3. Compare the gate count via the Classiq’s IDE in both cases.\n", + "\n", + "Note - the signature of function `unitary` is:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "bTtPgsj75_fZ", + "tags": [] + }, + "outputs": [], + "source": [ + "def unitary(\n", + " elements: CArray[CArray[CReal]],\n", + " target: QArray[QBit],\n", + ") -> None:\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "6Js8fNbl5_fa", + "outputId": "4d13cc20-3b3f-45b8-93fb-b353ab8cbea0", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "rng = np.random.default_rng(seed=0)\n", + "random_matrix = rng.random((4, 4))\n", + "qr_unitary, _ = np.linalg.qr(random_matrix)\n", + "\n", + "unitary_matrix = QConstant(\"unitary_matrix\", List[List[float]], qr_unitary.tolist())\n", + "\n", + "\n", + "@qfunc\n", + "def main(q: Output[QArray[QBit]]) -> None:\n", + " allocate(2, q)\n", + " power(3, lambda: unitary(unitary_matrix, q))\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)\n", + "execute(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "P-jP3v9O5_fb" + }, + "source": [ + "## Exercise 4 - User-defined Operators\n", + "Create a function that applies a given single-qubit operation to all qubits in its quantum argument (Call your function `my_apply_to_all`). Such a function is also called an operator, i.e. a function that one of its arguments is another function (its operand).\n", + "\n", + "See also Operators(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/operators/).\n", + "\n", + "Follow these guidelines:\n", + "1. Your function should declare a quantum argument of type qubit array. It should also declare an argument of a function type with a single qubit argument.\n", + "2. The body should apply the operand to all qubits in the argument.\n", + "\n", + "When you're done, re-implement `my_hadamard_transform` from exercise 2 using this function instead of `repeat`.\n", + "Use the same main function from exercise 2." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "vvMbP91D5_fc", + "outputId": "18fca5c9-3b26-4683-98c7-c17f27de698a", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "\n", + "@qfunc\n", + "def my_apply_to_all(operand: QCallable[QBit], q: QArray[QBit]) -> None:\n", + " repeat(q.len, lambda i: operand(q[i]))\n", + "\n", + "@qfunc\n", + "def my_hadamard(q: QArray[QBit]) -> None:\n", + " my_apply_to_all(lambda t: H(t), q)\n", + "\n", + "# Define a main function\n", + "@qfunc\n", + "def main(q: Output[QArray[QBit]]) -> None:\n", + " allocate(10, q)\n", + " my_hadamard(q)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)\n", + "execute(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "gh690ZGT5_fe" + }, + "source": [ + "# Exercise 5 - Quantum Conditionals\n", + "\n", + "### Exercise 5a - Control Operator\n", + "Use the built-in `control` operator to create a function that receives two single qubit variables and uses one of the variables to control an RY gate with a `pi/2` angle acting on the other variable (without using the `CRY` function).\n", + "\n", + "See also Quantum operators(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/quantum-operators/#syntax).\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "00trO6SJ5_ff", + "outputId": "b022f930-40a5-436c-b3af-0a4e4e5d21d7", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "from classiq.qmod.symbolic import pi\n", + "\n", + "\n", + "@qfunc\n", + "def my_controlled_ry(control_bit: QBit, target: QBit) -> None:\n", + " control(control_bit, lambda: RY(pi / 2, target))\n", + "\n", + "\n", + "@qfunc\n", + "def main(control_bit: Output[QBit], target: Output[QBit]) -> None:\n", + " allocate(1, control_bit)\n", + " allocate(1, target)\n", + " my_controlled_ry(control_bit, target)\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)\n", + "execute(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "GJ9y7jlY5_fh" + }, + "source": [ + "### Exercise 5b - Control (\"Quantum If\")\n", + "The `control` operator is the conditional application of some operation, with the condition being that all control qubits are in the state |1>. This notion is generalized in QMOD to other control states, where the condition is specified as a comparison between a quantum numeric variable and a numeric value, similar to a classical `if` statement. Quantum numeric variables are declared with class `QNum`.\n", + "\n", + "See also Numeric types(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/quantum-types/#syntax).\n", + "\n", + "In QMOD this generalization is available as a native statement - control.\n", + "\n", + "See also control(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/quantum-operators/).\n", + "\n", + "1. Declare a `QNum` output argument using `Output[QNum]` and name it `x`.\n", + "2. Use the `prepare_int` 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." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "IohNdRCA5_fi", + "outputId": "c3d53156-d530-48b8-e31b-80990b06e66d", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "@qfunc\n", + "def main(x: Output[QNum], target: Output[QBit]) -> None:\n", + " prepare_int(9, x)\n", + " allocate(1, target)\n", + " control(x == 9, lambda: X(target))\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 [Default]", + "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.9" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/community/QClass_2024/Submissions/HW2/Yasir_Mansour_HW2_QClass2024.ipynb b/community/QClass_2024/Submissions/HW2/Yasir_Mansour_HW2_QClass2024.ipynb new file mode 100644 index 00000000..43768e29 --- /dev/null +++ b/community/QClass_2024/Submissions/HW2/Yasir_Mansour_HW2_QClass2024.ipynb @@ -0,0 +1,751 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "view-in-github" + }, + "source": [ + "\"Open" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "NbVeWUvUOPPN" + }, + "source": [ + "# The Qmod Workshop - Part 2: Higher-Level Concepts\n", + "\n", + "This is the second part of the Qmod workshop, covering exercises 6 through 10. Make sure to go through Part 1 before continuing with this notebook." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import *" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "DLFwpFN8OPPd" + }, + "source": [ + "### Exercise 6 - Exponentiation and Pauli Operators\n", + "\n", + "The Qmod language supports different classical types: scalars, arrays, and structs. Structs are objects with member variables, or fields.\n", + "\n", + "See also Classical Types(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/classical-types/#structs).\n", + "\n", + "The builtin struct type `PauliTerm` is defined as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "EEjNNhY3OPPe" + }, + "outputs": [], + "source": [ + "@struct\n", + "class PauliTerm:\n", + " pauli: CArray[Pauli]\n", + " coefficient: CReal" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "oOlb_yyJOPPg" + }, + "source": [ + "Note that `Pauli` is an enum for all the Pauli matrices (I, X, Y, Z).\n", + "\n", + "Pauli based hamiltonian can be represented as a list of `PauliTerm`s. A Pauli operator defined this way is the argument to a hamiltonian evolution functions.\n", + "\n", + "In this exercise we will use the Suzuki-Trotter function to find the evolution of `H=0.5XZXX + 0.25YIZI + 0.3 XIZY` (captured as a literal value for the pauli-operator), with the evolution coefficient being 3, the order being 2, and use 4 repetitions.\n", + "\n", + "The declaration of the `suzuki_trotter` function is:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "uO1d4ba3OPPi" + }, + "outputs": [], + "source": [ + "@qfunc(external=True)\n", + "def suzuki_trotter(\n", + " pauli_operator: CArray[PauliTerm],\n", + " evolution_coefficient: CReal,\n", + " order: CInt,\n", + " repetitions: CInt,\n", + " qbv: QArray[QBit],\n", + ") -> None:\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "jGcQahGvOPPk" + }, + "source": [ + "Fill in the missing parts of the following code in order to complete this exercise:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "-ZPy2HjIOPPl", + "outputId": "fc91afc7-7cfc-4efe-b1d4-c3da484dfaeb" + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "\n", + "@qfunc\n", + "def main(q: Output[QArray[QBit]]) -> None:\n", + " allocate(4, q)\n", + " suzuki_trotter(\n", + " [\n", + " PauliTerm(pauli=[Pauli.X, Pauli.Z, Pauli.X, Pauli.X], coefficient=0.5),\n", + " PauliTerm(pauli=[Pauli.Y, Pauli.I, Pauli.Z, Pauli.I], coefficient=0.25),\n", + " PauliTerm(pauli=[Pauli.X, Pauli.I, Pauli.Z, Pauli.Y], coefficient=0.3),\n", + " ],\n", + " #[0.5XZXX + 0.25YIZI + 0.3 XIZY],\n", + " evolution_coefficient=3,\n", + " repetitions=4,\n", + " order=2,\n", + " qbv=q,\n", + " )\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "a2tiByHPVxIm" + }, + "source": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "YVauJN06OPPr" + }, + "source": [ + "### Exercise 7 - Basic Arithmetics\n", + "\n", + "#### Exercise 7a\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(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/quantum-types/#syntax).\n", + "See more on quantum expressions under Numeric assignment(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/numeric-assignment/)\n", + "\n", + "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`.\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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "2Ad42tEjOPPt", + "outputId": "0e3c5195-3914-4296-b400-067df17efb67" + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "@qfunc\n", + "def main(res1: Output[QNum], res2: Output[QNum], res3: Output[QNum], x: Output[QNum], y: Output[QNum], z: Output[QNum]):\n", + " prepare_int(2, x)\n", + " prepare_int(7, y)\n", + " prepare_int(1, z)\n", + " res1 |= x + y\n", + " res2 |= x * y\n", + " res3 |= x * y - z\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "oD9FFw0hOPPv" + }, + "source": [ + "#### Exercise 7b\n", + "Declare `x` to be a 2-qubit variable and `y` to be 3-qubit variable.\n", + "\n", + "We will perform an addition of two superposition states: `x` is an equal superposition of `0` and `2`, and `y` is an equal superposition of `1`, `2`, `3`, and `6`.\n", + "\n", + "1. Use `prepare_state` to initialize `x` and `y`. Note that `prepare_state` works with probabilities, not amplitudes.\n", + " The declaration of the `prepare_state` function is:\n", + " ```\n", + " @qfunc(external=True)\n", + " def prepare_state(\n", + " probabilities: CArray[CReal],\n", + " bound: CReal,\n", + " out: Output[QArray[QBit]],\n", + " ) -> None:\n", + " pass\n", + " ```\n", + " (Set the bound to 0 in your code)\n", + "2. Compute `res = x + y`. Execute the resulting circuit. What did you get?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "J5aQnWHEOPPx", + "outputId": "ea1de78b-3848-4255-d430-b1ae0bcc7cd2" + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "@qfunc\n", + "def main(res: Output[QNum], x: Output[QNum], y: Output[QNum]):\n", + " prepare_state([0.5, 0, 0.5, 0], bound=0.01, out=x)\n", + " prepare_state([0, 0.25, 0.25, 0.25, 0, 0, 0.25, 0], bound=0.01, out=y)\n", + " res |= x + y\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "QguPlrPLOPPz" + }, + "source": [ + "### Exercise 8 - Within-Apply\n", + "\n", + "The within-apply statement applies the pattern `U_dagger V U` that appears frequently in quantum computing.\n", + "It allows you to compute some function `V` within the context of another function `U`, and afterward uncompute `U` in order to release auxiliary qubits storing intermediate results.\n", + "\n", + "See also Within Apply(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/within-apply/).\n", + "\n", + "#### Exercise 8a\n", + "\n", + "In this exercise, we will use within-apply to compute an arithmetic expression in steps.\n", + "\n", + "Use the `within_apply` operation to calculate `res = x + y + z` from a two-variable addition building block with the following steps:\n", + "1. Add `x` and `y`\n", + "2. Add the result to `z`\n", + "3. Uncompute the result of the first operation\n", + "\n", + "For simplicity, initialize the registers to simple integers: `x=3`, `y=5`, `z=2`.\n", + "\n", + "Hints:\n", + "\n", + "* Use a temporary variable.\n", + "* Wrap the arithmetic operation in a function.\n", + "\n", + "Execute the circuit and make sure you obtain the expected result." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "gOMBLIf7OPP1", + "outputId": "ee6530e4-3fa1-4d46-d151-9862ee961b5e" + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "@qfunc\n", + "def q_add(res: Output[QNum], a:QNum, b:QNum) -> None:\n", + " res |= a + b\n", + "\n", + "@qfunc\n", + "def main(res: Output[QNum], x: Output[QNum],\n", + " y: Output[QNum], z: Output[QNum]) -> None:\n", + " prepare_int(3, x)\n", + " prepare_int(5, y)\n", + " prepare_int(2, z)\n", + " aux = QNum('aux')\n", + " within_apply(compute = lambda: q_add(aux, x, y),\n", + " action = lambda: q_add(res, aux, z))\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)\n", + "#13 qbits" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "umMhnAelOPP2" + }, + "source": [ + "#### Exercise 8b\n", + "\n", + "Why should we use `within-apply` and not just write three concatenated functions?\n", + "To understand the motivation, we will create another arithmetic circuit.\n", + "This time, however, we will also set Classiq’s synthesis engine to optimize on the circuit’s number of qubits, i.e., its width.\n", + "\n", + "Setting constraints can be done via the `set_constraints` operation - see here(docs.classiq.io/latest/user-guide/platform/synthesis/constraints/).\n", + "\n", + "Perform the operation `res = w + x + y + z`, where w is initialized to 4 and the rest as before:\n", + "\n", + "1. Add `x` and `y` (as part of the `within_apply` operation)\n", + "2. Add the result to `z` (as part of the within_apply operation)\n", + "3. Uncompute the result of the first operation (as part of the `within_apply` operation)\n", + "4. Add the result of the second operation to `w`. There’s no need to perform another uncomputation, as this brings our calculation to an end.\n", + "\n", + "Create the model, optimize on the circuit’s width, and run the circuit. Can you identify where qubits have been released and reused?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ED1iDS1aOPP5", + "outputId": "2260c2b1-d176-4c26-a83f-e0be9d1b6804" + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "@qfunc\n", + "def q_add(res: Output[QNum], a:QNum, b:QNum) -> None:\n", + " res |= a + b\n", + "\n", + "@qfunc\n", + "def main(res: Output[QNum], x: Output[QNum],\n", + " y: Output[QNum], z: Output[QNum], w: Output[QNum]) -> None:\n", + " prepare_int(3, x)\n", + " prepare_int(5, y)\n", + " prepare_int(2, z)\n", + " prepare_int(4, w)\n", + " aux1 = QNum('aux1')\n", + " aux2 = QNum('aux2')\n", + " within_apply(compute = lambda: q_add(aux1, x, y),\n", + " action = lambda: q_add(aux2, aux1, z),)\n", + " res |= aux2 + w\n", + "\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qmod = set_constraints(qmod,\n", + " Constraints(optimization_parameter='width'))\n", + "qprog = synthesize(qmod)\n", + "show(qprog)\n", + "#16 qbits" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "pIBHrEOxOPP6" + }, + "source": [ + "#### Bonus: Use a Single Arithmetic Expression\n", + "\n", + "What happens when we don't manually decompose this expression?\n", + "\n", + "Use Classiq’s arithmetic engine to calculate `res |= x + y + z + w` and optimize for width.\n", + "Look at the resulting quantum program - can you identify the computation and uncomputation blocks? What else did you notice?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ep-Efm_oOPP8", + "outputId": "258d0b91-cb7a-4a25-b80d-0492e6557fe1" + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "@qfunc\n", + "def q_add(res: Output[QNum], a:QNum, b:QNum) -> None:\n", + " res |= a + b\n", + "\n", + "@qfunc\n", + "def main(res: Output[QNum], x: Output[QNum],\n", + " y: Output[QNum], z: Output[QNum], w: Output[QNum]) -> None:\n", + " prepare_int(3, x)\n", + " prepare_int(5, y)\n", + " prepare_int(2, z)\n", + " prepare_int(4, w)\n", + " res |= x + y + z + w\n", + "\n", + "qmod = create_model(main)\n", + "qmod = set_constraints(qmod,\n", + " Constraints(optimization_parameter='width'))\n", + "qprog = synthesize(qmod)\n", + "show(qprog)\n", + "#15 qbits" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ZV9OGqqROPP-" + }, + "source": [ + "### Exercise 9 - In-place Arithmetics\n", + "\n", + "For the following exercise we will use numeric quantum variables that represent fixed-point reals.\n", + "\n", + "Arithmetic expressions can be calculated in-place into a target variable, without allocating new qubits to store the result. This is done using the in-place-xor operator.\n", + "\n", + "See also Numeric assignment(docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/numeric-assignment/#semantics).\n", + "\n", + "In-place assignment is often used to nest arithmetic expressions under quantum operators. Note that out-of-place assignment requires its left-value variable to be un-initialized, and therefore cannot be used under an operator if the variable is declared outside its scope. Applying operators to arithmetic expressions is required in many algorithms. One example is the piecewise evaluation of mathematical functions - calculating different expressions over `x` depending on the subdomain where `x` falls.\n", + "\n", + "For this exercise, replace the missing parts in the code snippet below to evaluate the result of:\n", + "\n", + "$$\n", + "f(x) = \\begin{cases}\n", + " 2x + 1 & \\text{ if } 0 \\leq x < 0.5 \\\\\n", + " x + 0.5 & \\text{ if } 0.5 \\leq x < 1\n", + " \\end{cases}\n", + "$$\n", + "\n", + "Notes:\n", + "- We cannot use `x` directly as the control variable in a `constrol` operator, because it also occurs in the nested scope. to determine if `x` is in the lower or higher half of the domain we duplicate the most significant bit onto a separate variable called `label`.\n", + "- In Python assignment operators cannot be used in lambda expressions, so the computation of the function needs to be factored out to a named Python function (but not necessarily a Qmod function).\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "P1AsWxksOPQA", + "outputId": "c56c759d-fb58-45d7-b8b6-fc801c611f11" + }, + "outputs": [], + "source": [ + "\n", + "from classiq import *\n", + "\n", + "\n", + "def linear_func(a: float, b: float, x: QNum, res: QNum) -> None:\n", + " res = (a * x) + b\n", + "\n", + "\n", + "@qfunc\n", + "def dup_msb(qba: QArray[QBit], msb: QBit) -> None:\n", + " CX(qba[qba.len - 1], msb)\n", + "\n", + "\n", + "@qfunc\n", + "def main(x: Output[QNum[3, False, 3]], res: Output[QNum[5, False, 3]]) -> None:\n", + " allocate(5, res)\n", + " allocate(3, x)\n", + " hadamard_transform(x)\n", + "\n", + " label = QArray(\"label\")\n", + " allocate(1, label)\n", + "\n", + " dup_msb(x, label)\n", + " control(label, lambda: linear_func(1.0, 0.5, x, res)) # 0.5 <= x < 1.0\n", + " X(label)\n", + " control(label, lambda: linear_func(2.0, 1.0, x, res)) # 0.0 <= x < 0.5\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "OOvAn02QOPQC" + }, + "source": [ + "### Exercise 10 - State-preparation Algorithm using Quantum-if\n", + "\n", + "#### Binding\n", + "The `bind` operation allows to convert smoothly between different quantum types and split or slice bits when necessary. Here’s an example:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "JCX6UMqROPQD", + "outputId": "6d35d8f5-4341-4560-b708-d70d443dab84" + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "\n", + "\n", + "from classiq import *\n", + "from math import pi\n", + "\n", + "\n", + "@qfunc\n", + "def main(res: Output[QArray[QBit]]) -> None:\n", + " x: QArray[QBit] = QArray(\"x\")\n", + " allocate(3, x)\n", + " hadamard_transform(x)\n", + "\n", + " lsb = QBit(\"lsb\")\n", + " msb = QNum(\"msb\", 2, False, 0)\n", + " bind(x, [lsb, msb])\n", + "\n", + " control(msb == 1, lambda: RY(pi / 3, lsb))\n", + " # msb==1 <==> bit1 bit2 == 01 (binary of decimal 1)\n", + "\n", + " bind([lsb, msb], res)\n", + "\n", + "model = create_model(main)\n", + "qprog = synthesize(model)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "fc5-bUyKOPQF" + }, + "source": [ + "The first `bind` operation splits the 3-qubit register `x` into the 2-qubit and single-qubit registers `lsb` and `msb`, respectively.\n", + "\n", + "After the `bind` operation:\n", + "1. The registers `lsb` and `msb` can be operated on as separated registers.\n", + "2. The register`x` is consumed and can no longer be used.\n", + "\n", + "The second `bind` operation concatenates the registers to the output register `res`.\n", + "\n", + "For this exercise, fill in the missing code parts in the above snippet and use the `control` statement to manually generate the following lovely 3-qubit probability distribution: `[1/8, 1/8, 1/8, -sqrt(3)/16, 1/8 + sqrt(3)/16, 1/8, 1/8, 1/8, 1/8]`.\n", + "\n", + "The following series of gates generate it:\n", + "\n", + "Perform the Hadamard transform on all three qubits.\n", + "\n", + "Apply a rotation on the LSB (least-significant bit) conditioned by the MSB being |0> and the second to last MSB being |1>. How would you write this condition using a QNum?\n", + "\n", + "The following series of gates generate it:\n", + "1. Perform the Hadamard transform on all three qubits.\n", + "2. Apply a `pi/3` rotation on the LSB (least-significant bit) conditioned by the MSB being |0> and the second to last MSB being |1>. How would you write this condition using a QNum?\n", + "\n", + "If you want to validate your results without looking at the full solution, compare them to running using Classiq’s built-in `prepare_state` function.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "nSjVMfP8OPQG", + "outputId": "5ca3382b-fcf8-4901-bf77-72eb916118a0" + }, + "outputs": [], + "source": [ + "#version 1 with msb, lsb, H, RY\n", + "from classiq import *\n", + "from classiq.qmod.symbolic import sqrt\n", + "from math import pi\n", + "\n", + "prob_list= [\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8 - sqrt(3) / 16,\n", + " 1 / 8 + sqrt(3) / 16,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " ]\n", + "@qfunc\n", + "def pre_prepared_state(q: QArray[QBit]) -> None:\n", + " prepare_state(\n", + " [\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8 - sqrt(3) / 16,\n", + " 1 / 8 + sqrt(3) / 16,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " ],\n", + " 0.0,\n", + " q,\n", + " )\n", + "\n", + "@qfunc\n", + "def main(res: Output[QArray[QBit]]) -> None:\n", + " x: QArray[QBit] = QArray(\"x\")\n", + " allocate(3, x)\n", + " hadamard_transform(x)\n", + "\n", + " lsb = QBit(\"lsb\")\n", + " msb = QNum(\"msb\", 2, False, 0)\n", + " bind(x, [lsb, msb])\n", + "\n", + " control(msb == 1, lambda: RY(pi / 3, lsb))\n", + " # msb==1 <==> bit1 bit2 == 01 (binary of decimal 1)\n", + " bind([lsb, msb], res)\n", + "\n", + " #prepare_state(probabilities=prob_list, bound=0.0, out=res)\n", + "\n", + "model = create_model(main)\n", + "qprog = synthesize(model)\n", + "show(qprog)\n", + "\n", + "# Your code here:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "mp0cnm12XKjo", + "outputId": "c97473fc-1b10-4bc0-b9ec-2db111726a00" + }, + "outputs": [], + "source": [ + "#version 2 with prepare_state\n", + "from classiq import *\n", + "from classiq.qmod.symbolic import sqrt\n", + "from math import pi\n", + "\n", + "prob_list= [\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8 - sqrt(3) / 16,\n", + " 1 / 8 + sqrt(3) / 16,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " ]\n", + "@qfunc\n", + "def pre_prepared_state(q: Output[QArray[QBit]]) -> None:\n", + " prepare_state(\n", + " [\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8 - sqrt(3) / 16,\n", + " 1 / 8 + sqrt(3) / 16,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " ],\n", + " 0.0,\n", + " q,\n", + " )\n", + "\n", + "@qfunc\n", + "def main(res: Output[QArray[QBit]]) -> None:\n", + " prepare_state(probabilities=prob_list, bound=0.0, out=res)\n", + "\n", + "model = create_model(main)\n", + "qprog = synthesize(model)\n", + "show(qprog)\n", + "\n", + "# Your code here:" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "-TDAFwWbXVeT" + }, + "source": [] + } + ], + "metadata": { + "colab": { + "include_colab_link": true, + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 [Default]", + "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.9" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/community/QClass_2024/Submissions/HW3/Yasir_Mansour_HW3_VQE.ipynb b/community/QClass_2024/Submissions/HW3/Yasir_Mansour_HW3_VQE.ipynb index 274c8e70..2aab6f2a 100644 --- a/community/QClass_2024/Submissions/HW3/Yasir_Mansour_HW3_VQE.ipynb +++ b/community/QClass_2024/Submissions/HW3/Yasir_Mansour_HW3_VQE.ipynb @@ -1,5 +1,16 @@ { "cells": [ + { + "cell_type": "markdown", + "id": "820da28e", + "metadata": { + "colab_type": "text", + "id": "view-in-github" + }, + "source": [ + "\"Open" + ] + }, { "cell_type": "markdown", "id": "fc72d98f-8993-4bd4-a545-23d122f3df71", @@ -10,8 +21,8 @@ "# H₂ Molecule Homework Assignment\n", "### Quantum Software Development Journey: From Theory to Application with Classiq - Part 3\n", "\n", - "- Similarly to what we have done in class, in this exercise we will implement the VQE on H2 molecule.\n", - "- This time instead of using the built-in methods and functions (such as `Molecule` and `MoleculeProblem`) to difne and solve the problem, you will be provided with a two qubits Hamiltonian." + "##- Similarly to what we have done in class, in this exercise we will implement the VQE on H2 molecule.\n", + "##- This time instead of using the built-in methods and functions (such as `Molecule` and `MoleculeProblem`) to difne and solve the problem, you will be provided with a two qubits Hamiltonian." ] }, { @@ -22,20 +33,23 @@ }, "source": [ "## Submission\n", - "- Submit the completed Jupyter notebook and report via GitHub. Ensure all files are correctly named and organized.\n", - "- Use the Typeform link provided in the submission folder to confirm your submission.\n", + "##- Submit the completed Jupyter notebook and report via GitHub. Ensure all files are correctly named and organized.\n", + "##- Use the Typeform link provided in the submission folder to confirm your submission.\n", "\n", "## Additional Resources\n", - "- [Classiq Documentation](https://docs.classiq.io/latest/)\n", - "- The notebook from live session #3\n", + + "##- Classiq Documentation(docs.classiq.io/latest/)\n", + "##- [Classiq Documentation](https://docs.classiq.io/latest/)\n", + + "##- The notebook from live session #3\n", "\n", "## Important Dates\n", - "- **Assignment Release:** 22.5.2024\n", - "- **Submission Deadline:** 3.6.2024 (7 A.M GMT+3)\n", + "##- **Assignment Release:** 22.5.2024\n", + "##- **Submission Deadline:** 3.6.2024 (7 A.M GMT+3)\n", "\n", - "---\n", + "##---\n", "\n", - "Happy coding and good luck!" + "##Happy coding and good luck!" ] }, { @@ -81,7 +95,8 @@ ] }, { - "cell_type": "code", + "cell_type": "c + "execution_count": 2, "execution_count": 1, "id": "DQOxbZxjrN5r", "metadata": { @@ -93,7 +108,7 @@ }, "outputs": [], "source": [ - "# !pip install classiq" + "## !pip install classiq" ] }, { @@ -119,6 +134,17 @@ "outputs": [], "source": [ "from typing import List, cast\n", + "from classiq import *\n", + "from classiq import Pauli, PauliTerm\n", + "\n", + "#TODO: Complete Hamiltonian\n", + "HAMILTONIAN = QConstant(\"HAMILTONIAN\", List[PauliTerm], [\n", + " PauliTerm([Pauli.I, Pauli.I], -1.0523),\n", + " PauliTerm([Pauli.I, Pauli.Z], 0.3979),\n", + " PauliTerm([Pauli.Z, Pauli.I], -0.3979),\n", + " PauliTerm([Pauli.Z, Pauli.Z], -0.0112),\n", + " PauliTerm([Pauli.X, Pauli.X], 0.1809),\n", + "])" "\n", "from classiq import *\n", "from classiq import Pauli, PauliTerm\n", @@ -138,7 +164,8 @@ ] }, { - "cell_type": "code", + "cell_type": "code" + "execution_count": 3, "execution_count": 4, "id": "0bb68899-2076-45c0-8868-131f38aa3b78", "metadata": { @@ -154,7 +181,8 @@ " allocate(2, q)\n", " U(angles[0], angles[1], angles[2], 0, q[0])\n", " U(angles[0], angles[1], angles[2], 0, q[1])\n", - " # CX(q[0], q[1])\n", + " ##CX(q[0], q[1])\n", + " ##CX(q[0], q[1])\n", "\n", "\n", "@cfunc\n", @@ -172,9 +200,12 @@ " )\n", " save({\"result\": res})\n", "\n", + "qmod = create_model(main, classical_execution_function=cmain)\n", + "##TODO: complete the line, use classical_execution_function\n", "\n", "qmod = create_model(main, classical_execution_function=cmain)\n", - "# TODO: complete the line, use classical_execution_function\n", + "##TODO: complete the line, use classical_execution_function\n", + "qprog = synthesize(qmod)\n", "# show(qprog)" ] @@ -192,7 +223,8 @@ "res = execution.result()\n", "# execution.open_in_ide()\n", "vqe_result = res[0].value\n", - "# TODO: complete the line" + "##TODO: complete the line" + "##TODO: complete the line" ] }, { @@ -212,9 +244,12 @@ "name": "stdout", "output_type": "stream", "text": [ + "Optimal energy: -1.0681201171874999\n", + "Optimal parameters: {'angles_0': -3.429491869883728, 'angles_1': -4.962285285210174, 'angles_2': 6.007229196693071}\n", + "Eigenstate: {'10': (0.13621559198564606+0j), '01': (0.13621559198564606+0j), '11': (0.9812699042567239+0j)}\n" "Optimal energy: -1.0754688476562502\n", "Optimal parameters: {'angles_0': 0.7985412460405645, 'angles_1': 4.821416635411074, 'angles_2': -2.4351340720501597}\n", - "Eigenstate: {'11': (0.14986973510352247+0j), '10': (0.33874192794810626+0j), '00': (0.8600849340326803+0j), '01': (0.350780380010057+0j)}\n" + "Eigenstate: {'11': (0.14986973510352247+0j), '10': (0.33874192794810626+0j), '00': (0.8600849340326803+0j), '01': (0.350780380010057+0j)}" ] } ], @@ -290,14 +325,18 @@ " U(angles[0], angles[1], angles[2], 0, q[0])\n", " U(angles[0], angles[1], angles[2], 0, q[1])\n", " CX(q[0], q[1])\n", - " # H(q[0])\n", - " # X(q[1])\n", - " # CX(q[0], q[1])\n", + " ##H(q[0])\n", + " ##X(q[1])\n", + " ##CX(q[0], q[1])\n", + " ##H(q[0])\n", + " ##X(q[1])\n", + " ##CX(q[0], q[1])\n", "\n", "\n", "@cfunc\n", "def cmain() -> None:\n", " res = vqe(\n", + " HAMILTONIAN, # TODO: complete the missing argument\n", " HAMILTONIAN, # TODO: complete the missing argument\n", " False,\n", " [],\n", @@ -310,9 +349,11 @@ " )\n", " save({\"result\": res})\n", "\n", + "qmod = create_model(main, classical_execution_function=cmain)\n", + "##TODO: complete the line, use classical_execution_function\n", "\n", "qmod = create_model(main, classical_execution_function=cmain)\n", - "# TODO: complete the line, use classical_execution_function\n", + "##TODO: complete the line, use classical_execution_function\n" "qprog = synthesize(qmod)\n", "# show(qprog)" ] @@ -330,7 +371,8 @@ "res = execution.result()\n", "# execution.open_in_ide()\n", "vqe_result = res[0].value\n", - "# TODO: complete the line" + "##TODO: complete the line" + "##TODO: complete the line" ] }, { @@ -349,9 +391,12 @@ "name": "stdout", "output_type": "stream", "text": [ + "Optimal energy: -1.83589755859375\n", + "Optimal parameters: {'angles_0': -3.1968121237616858, 'angles_1': 4.415682206108902, 'angles_2': 5.319096413899962}\n", + "Eigenstate: {'11': (0.02209708691207961+0j), '10': (0.038273277230987154+0j), '01': (0.9990229601966113+0j)}\n "Optimal energy: -1.8512822265625002\n", "Optimal parameters: {'angles_0': -2.953247896519252, 'angles_1': 6.104234752928836, 'angles_2': 4.463845345952442}\n", - "Eigenstate: {'10': (0.08838834764831845+0j), '11': (0.0855816496101822+0j), '01': (0.992402781762526+0j)}\n" + "Eigenstate: {'10': (0.08838834764831845+0j), '11': (0.0855816496101822+0j), '01': (0.992402781762526+0j)}" ] } ], @@ -399,7 +444,8 @@ "provenance": [] }, "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3 [Default]" + "display_name": "Python 3 (ipykernel) "language": "python", "name": "python3" }, diff --git a/community/QClass_2024/Submissions/HW4/Yasir_Mansour_HW4_molecule_eigensolver_ipynb_txt.ipynb b/community/QClass_2024/Submissions/HW4/Yasir_Mansour_HW4_molecule_eigensolver_ipynb_txt.ipynb new file mode 100644 index 00000000..3a40ab6d --- /dev/null +++ b/community/QClass_2024/Submissions/HW4/Yasir_Mansour_HW4_molecule_eigensolver_ipynb_txt.ipynb @@ -0,0 +1,684 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "726d2386", + "metadata": { + "colab_type": "text", + "id": "view-in-github" + }, + "source": [ + "\"Open" + ] + }, + { + "cell_type": "markdown", + "id": "4fbae0f9", + "metadata": { + "id": "4fbae0f9" + }, + "source": [ + "# Molecule Eigensolver (VQE method)\n", + "\n", + "Evaluating the ground state of a molecular Hamiltonian allows us to understand the chemical properties of the molecule. In this demo, we demonstrate the usage of Variational Quantum Eigensolver (VQE) for finding the ground states and energies of several molecules: 𝐻2 , 𝐻2𝑂 and 𝐿𝑖𝐻 .\n", + "\n", + "VQE is a leading method for finding approximate values of ground state wavefuncions and energies for complicated quantum systems, and as such can give solutions for complex molecular structures. The overview of the VQE method is as following: a problem (i.e. a molecule) is defined by a Hamiltonian which ground state is sought. Then, a choice of a parameterized ansatz is made. Using a hybrid quantum-classical algorithm, a solution for the defined parameters which minimize the expectation value for the energy is found. A clever ansatz will lead to an estimated ground state solution.\n", + "\n", + "Within the scope of Classiq's VQE algorithm, the user defines a Molecule which is being translated to a concise Hamiltonian. Then, a choice between several types of well studied ansatz is given, which can be carefully picked to fit your Molecule type. In the last stage, the Hamiltonian and ansatz are sent to a classical optimizer. During this tutorial we will demonstrate the steps and user options in Classiq's VQE algorithm. Furthermore, the demonstration will present the optimization strength Classiq's VQE algorithm holds, and it's state of the art results in term of efficient quantum circuit - with ultimate combination of low depth and high accuracy, while minimizing the number of CX gates." + ] + }, + { + "cell_type": "markdown", + "id": "TWGNYMkUKh6C", + "metadata": { + "id": "TWGNYMkUKh6C" + }, + "source": [ + "` **RESULTS**\n", + "\n", + "Comparison of different molecules in terms of width and depth. The more atoms in a molecule, the more qubits/circuit depth are necessary. System overload when more than 3 atoms.\n", + "\n", + "## **h2**\n", + "\n", + "hw-eff ansatz: width 4/depth34\n", + "\n", + "ucc ansatz: ,\n", + "width 1/depth 6, width 4, depth 3\n", + "\n", + "total en -1.1342995783232035,\n", + "exact result: -1.8572750302023786,\n", + "vqe result: -1.854268572772183\n" + ] + }, + { + "cell_type": "markdown", + "id": "XcbH8UHbKrIU", + "metadata": { + "id": "XcbH8UHbKrIU" + }, + "source": [ + "## **h2o**\n", + "\n", + "hw-eff. ansatz: width 12/depth 375,\n", + "(conn map 0-1..10-11, reps 11)\n", + "\n", + "ucc ansatz: width 8/depth 1218, width 12/depth 1048\n", + "\n", + "total energy -71.7605079203085,\n", + "exact result: -23.544497240443615,\n", + "vqe result: -80.95442108093192" + ] + }, + { + "cell_type": "markdown", + "id": "Br0-chtAKv6D", + "metadata": { + "id": "Br0-chtAKv6D" + }, + "source": [ + "##**co2**\n", + "\n", + "hw-eff ansatz: width 24/depth 175\n", + "\n", + "ucc ansatz: width 20/depth 19767, width 24/depth 16968\n", + "\n", + "Error number 90001 occurred. The resources needed to execute this request are insufficient.\n", + " This may be due to computational limitations, or high load on Classiq's servers." + ] + }, + { + "cell_type": "markdown", + "id": "54d09062-1b3b-4e4b-8351-5e05a633e269", + "metadata": { + "id": "54d09062-1b3b-4e4b-8351-5e05a633e269" + }, + "source": [ + "## 0. Pre-requirments\n", + "\n", + "The model is using several Classiq's libraries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fc04368f-475c-4e00-9b26-f51dd94a15f0", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import *" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c6bbe65f-1e6a-475c-a43f-cb4cc04bbdfa", + "metadata": { + "id": "c6bbe65f-1e6a-475c-a43f-cb4cc04bbdfa", + "tags": [] + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "from classiq import QuantumProgram, construct_chemistry_model, execute, show, synthesize\n", + "from classiq.applications.chemistry import (\n", + " ChemistryExecutionParameters,\n", + " HEAParameters,\n", + " Molecule,\n", + " MoleculeProblem,\n", + " UCCParameters,\n", + ")\n", + "from classiq.execution import (\n", + " ClassiqBackendPreferences,\n", + " ClassiqSimulatorBackendNames,\n", + " ExecutionPreferences,\n", + " OptimizerType,\n", + ")\n", + "from classiq.synthesis import set_execution_preferences" + ] + }, + { + "cell_type": "markdown", + "id": "faa3c10f", + "metadata": { + "id": "faa3c10f" + }, + "source": [ + "## 1. Generate Qubit Hamiltonian\n", + "\n", + "The first step is to define the molecule we wish to simulate. We hereby declare the class Molecule and insert a list of atoms and their spacial positions. The algorithm will automatically regard relevant attributes such as the atom's mass, charge and spin.\n", + "\n", + "As mentioned above, during this tutorial, we demonstrate how to define and find the ground state and energies for 3 molecules:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "VN6XdfYfLApS", + "metadata": { + "id": "VN6XdfYfLApS", + "tags": [] + }, + "outputs": [], + "source": [ + "#hydrogen\n", + "molecule_H2 = Molecule(atoms=[(\"H\", (0.0, 0.0, 0)), (\"H\", (0.0, 0.0, 0.735))])\n", + "\n", + "#oxygen\n", + "molecule_O2 = Molecule(atoms=[(\"O\", (0.0, 0.0, 0)), (\"O\", (0.0, 0.0, 1.16))])\n", + "\n", + "#lithium hydride\n", + "molecule_LiH = Molecule(atoms=[(\"H\", (0.0, 0.0, 0.0)), (\"Li\", (0.0, 0.0, 1.596))])\n", + "\n", + "#water\n", + "molecule_H2O = Molecule(\n", + " atoms=[(\"O\", (0.0, 0.0, 0.0)), (\"H\", (0, 0.586, 0.757)), (\"H\", (0, 0.586, -0.757))]\n", + ")\n", + "#beryllium hydride\n", + "molecule_BeH2 = Molecule(\n", + " atoms=[(\"Be\", (0.0, 0.0, 0.0)), (\"H\", (0, 0, 1.334)), (\"H\", (0, 0, -1.334))]\n", + ")\n", + "#carbon dioxide\n", + "molecule_CO2 = Molecule(atoms=[(\"C\", (0.0, 0.0, 0.0)),\n", + " (\"O\", (0, 0, 1.1693)), (\"O\", (0, 0, -1.1693))])\n", + "\n", + "#ethyne, acetylene\n", + "molecule_C2H2 = Molecule(atoms=[(\"C\", (0, 0, -0.5977)), (\"C\", (0, 0, 0.5977)),\n", + " (\"H\", (0, 0, -1.6692)), (\"H\", (0, 0, 1.6692))])\n", + "\n", + "#chloroform\n", + "molecule_CH3Cl = Molecule(atoms=[(\"C\", (0, 0, -1.1401)), (\"Cl\", (0, 0, 0.6645)),\n", + " (\"H\", (0, 1.0343, -1.4855)),\n", + " (\"H\", (0.8957, -0.5171, -1.4855)), (\"H\", (-0.8957, -0.5171, -1.4855))])\n", + "\n", + "#ethylene\n", + "molecule_C2H4 = Molecule(atoms=[(\"C\", (0, 0, 0.6673)), (\"C\", (0, 0, -0.6673)),\n", + " (\"H\", (0, 0.9239, 1.2411)), (\"H\", (0, -0.9239, 1.2411)),\n", + " (\"H\", (0, -0.9239, -1.2411)), (\"H\", (0, 0.9239, -1.2411))])\n" + ] + }, + { + "cell_type": "markdown", + "id": "ab162f48", + "metadata": { + "id": "ab162f48" + }, + "source": [ + "Similarly, the user is able to construct any valid essambly of atoms. The distances are recived in Å ($10^{-10} m$). We will continue this demonstration with a specific molecule. The user can change the `molecule` below to study other cases." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e77678f", + "metadata": { + "id": "2e77678f", + "tags": [] + }, + "outputs": [], + "source": [ + "molecule = molecule_H2O" + ] + }, + { + "cell_type": "markdown", + "id": "c4a541a5", + "metadata": { + "id": "c4a541a5" + }, + "source": [ + "Next, we define the parameters of the Hamiltonian generation program. The user has a choice over the following options:\n", + "- mapping (str): the mapping between the fermionic Hamiltonian and an qubits Hamiltonian. Supported types:\n", + " - \"jordan_wigner\"\n", + " - \"parity\"\n", + " - \"bravyi_kitaev\"\n", + " - \"fast_bravyi_kitaev\"\n", + "- freeze_core (bool): remove the \"core\" orbitals of the atoms defining the molecule.\n", + "- z2_symmetries (bool): whether to perform z2 symmetries reduction. If symmetries in the molecules exist, this option will decrease the number of qubits used and will efficient the Hamiltonian and thus the calculations.\n", + "\n", + "Finally, the Hamiltonian is generated from `MoleculeProblem`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e0426d5", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "2e0426d5", + "outputId": "205584a3-ca38-4d54-ca52-dbc3f88b8bbf", + "tags": [] + }, + "outputs": [], + "source": [ + "chemistry_problem = MoleculeProblem(\n", + " molecule=molecule,\n", + " mapping=\"jordan_wigner\", #'bravyi_kitaev'\n", + " z2_symmetries=True,\n", + " freeze_core=True,\n", + ")\n", + "\n", + "operator = chemistry_problem.generate_hamiltonian()\n", + "gs_problem = chemistry_problem.update_problem(operator.num_qubits)\n", + "print(\"Your Hamiltonian is\", operator.show(), sep=\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "67a124c2-33fc-420c-8cb3-0002f18f4e77", + "metadata": { + "id": "67a124c2-33fc-420c-8cb3-0002f18f4e77" + }, + "source": [ + "The output of the above code lines is the Hamiltonian presented as a superposition of Pauli matrices multiplication.\n", + "One can easily confirm that using z2*symmetries=True, the number of qubits are reduced (compered to z2_symmetries=False): for $H_2$ - from 4 to 1, for $LiH$ from 12 to 8, and for $H*{2}O$ from 14 to 10." + ] + }, + { + "cell_type": "markdown", + "id": "8abe3e3d-1b01-4fab-b86a-feaab3851950", + "metadata": { + "id": "8abe3e3d-1b01-4fab-b86a-feaab3851950" + }, + "source": [ + "## 2. Constructing and Synthesizing a Ground State Solver\n", + "\n", + "A ground state solver model consists of a parameterized eigenfunction (\"the ansatz\"), on which we run a VQE. In addition, a post-process of the result allows to return the total energy (combining the ground state energy of the Hamiltonian, the nuclear repulsion and the static nuclear energy).\n", + "\n", + "Once we've specified an Hamiltonian and a desired Ansatz, we send them to the VQE algorithm in order to find the Hamiltonian's ground state. In the process, the algorithm will send requests to a classical server, which task is to minimize the energy expectation value and return the optimized parameters. The simulator and optimizing parameters are defined as part of the VQE part of the model. The user should control the `max_iteration` value in a manner so the solution has reached a stable convergence. In addition, the value `num_shots` sets the number of measurements performed after each iteration, thus influence the accuracy of the solutions.\n", + "\n", + "We demonstrate two different proposal for the wavefunction solution ansatz: (1) Hardware (HW) efficient, and (2) Unitary Coupled Cluster (UCC). For groundstate solvers it is typical to initialize the Ansatz with the Hartree-Fock state." + ] + }, + { + "cell_type": "markdown", + "id": "07ed8f8e-485b-4f0f-93b7-78e7fd6fbe39", + "metadata": { + "id": "07ed8f8e-485b-4f0f-93b7-78e7fd6fbe39" + }, + "source": [ + "### 2.1 HW-Efficient Ansatz\n", + "\n", + "Hardware-efficient ansatz is a suggested solution that is generated to fit a specific hardware [1]. The ansatz creates a state with given number of parameters by user choice (number of qubits, that should fit the Hamiltonian), and creates entanglement between the qubits by the inputed connectivity map. In this example, a 4 qubit map is given, which is specifically made of $H_2$ with z2_symmetries=False.\n", + "\n", + "After constructing the model, we can synthesize it and view the outputted circuit, in charged on creating the state with an interactive interface." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90b20061-8dbd-4136-adba-28ddacb1f583", + "metadata": { + "id": "90b20061-8dbd-4136-adba-28ddacb1f583", + "tags": [] + }, + "outputs": [], + "source": [ + "chemistry_problem = MoleculeProblem(\n", + " molecule=molecule,\n", + " mapping=\"jordan_wigner\", #'bravyi_kitaev'\n", + " z2_symmetries=False,\n", + " freeze_core=True,\n", + ")\n", + "\n", + "hwea_params = HEAParameters(\n", + " num_qubits=12,\n", + " connectivity_map=[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8),\n", + " (8, 9), (9, 10)],\n", + " reps=3,\n", + " one_qubit_gates=[\"x\", \"ry\"],\n", + " two_qubit_gates=[\"cx\"],\n", + ")\n", + "\n", + "qmod = construct_chemistry_model(\n", + " chemistry_problem=chemistry_problem,\n", + " use_hartree_fock=True,\n", + " ansatz_parameters=hwea_params,\n", + " execution_parameters=ChemistryExecutionParameters(\n", + " optimizer=OptimizerType.COBYLA,\n", + " max_iteration=30,\n", + " initial_point=None,\n", + " ),\n", + ")\n", + "\n", + "backend_preferences = ClassiqBackendPreferences(\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR\n", + ")\n", + "\n", + "qmod = set_execution_preferences(\n", + " qmod,\n", + " execution_preferences=ExecutionPreferences(\n", + " num_shots=1000, backend_preferences=backend_preferences\n", + " ),\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f13599d2-e8e7-4165-aa26-8ae8d4bdafaa", + "metadata": { + "id": "f13599d2-e8e7-4165-aa26-8ae8d4bdafaa", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import write_qmod\n", + "\n", + "write_qmod(qmod, name=\"molecule_eigensolver\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22cd12d1-2c87-400a-a983-b2f24e40fa45", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "22cd12d1-2c87-400a-a983-b2f24e40fa45", + "outputId": "d48d0740-4851-4943-f54b-325303b4838a", + "tags": [] + }, + "outputs": [], + "source": [ + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "id": "7fb92cdc", + "metadata": { + "id": "7fb92cdc" + }, + "source": [ + "### 2.2. UCC Ansatz\n", + "\n", + "Next, we show how to create the commonly used chemistry-inspired UCC ansatz, which is a unitary version of the classical coupled cluster (CC) method [2] .\n", + "\n", + "The parameter that defines the UCC ansatz is:\n", + "- excitations (List[int] or List[str]): list of desired excitations. Allowed excitations:\n", + " - 1 for singles\n", + " - 2 for doubles\n", + " - 3 for triples\n", + " - 4 for quadruples\n", + "\n", + "Once again, after the code lines bellow run, the user is able to view the outputted circuit, in charged on creating the state with an interactive interface. In addition, the depth of the circuit is printed.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f520673", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "1f520673", + "outputId": "fd4a3467-c48b-483c-b156-0a0cde9e2189", + "tags": [] + }, + "outputs": [], + "source": [ + "chemistry_problem = MoleculeProblem(\n", + " molecule=molecule,\n", + " mapping=\"jordan_wigner\", #'bravyi_kitaev'\n", + " z2_symmetries=True,\n", + " freeze_core=True,\n", + ")\n", + "\n", + "serialized_chemistry_model = construct_chemistry_model(\n", + " chemistry_problem=chemistry_problem,\n", + " use_hartree_fock=True,\n", + " ansatz_parameters=UCCParameters(excitations=[1, 2]),\n", + " execution_parameters=ChemistryExecutionParameters(\n", + " optimizer=OptimizerType.COBYLA,\n", + " max_iteration=30,\n", + " initial_point=None,\n", + " ),\n", + ")\n", + "\n", + "backend_preferences = ClassiqBackendPreferences(\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR\n", + ")\n", + "\n", + "serialized_chemistry_model = set_execution_preferences(\n", + " serialized_chemistry_model,\n", + " execution_preferences=ExecutionPreferences(\n", + " num_shots=1000, backend_preferences=backend_preferences\n", + " ),\n", + ")\n", + "\n", + "qprog = synthesize(serialized_chemistry_model)\n", + "show(qprog)\n", + "\n", + "circuit = QuantumProgram.from_qprog(qprog)\n", + "print(f\"circuit depth: {circuit.transpiled_circuit.depth}\")" + ] + }, + { + "cell_type": "markdown", + "id": "f12c9a32-f271-4892-8515-bd9e6b9fcf8b", + "metadata": { + "id": "f12c9a32-f271-4892-8515-bd9e6b9fcf8b" + }, + "source": [ + "Classiq's UCC algorithm provides an highly efficient solution in aspects of circuit depth and number of CX gates. Those ultimately reduce the gate's time and amount of resources needed for its operation." + ] + }, + { + "cell_type": "markdown", + "id": "ef36661f", + "metadata": { + "id": "ef36661f" + }, + "source": [ + "## 3. Execute to Find Ground State\n", + "\n", + "Once we've synthesized the model we can execute it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1a66d377", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 477 + }, + "id": "1a66d377", + "outputId": "1c93e68e-1300-4fde-ec56-e6e2d377a96e", + "tags": [] + }, + "outputs": [], + "source": [ + "result = execute(qprog).result()\n", + "chemistry_result_dict = result[1].value" + ] + }, + { + "cell_type": "markdown", + "id": "f72ceeb5-bc71-46d8-a390-31ec874700f3", + "metadata": { + "id": "f72ceeb5-bc71-46d8-a390-31ec874700f3" + }, + "source": [ + "Execution of the quantum program returns several useful outputs:\n", + "- energy : the output of the VQE algorithm - the electronic energy simulated.\n", + "- nuclear_repulsion : the electrostatic energy generated by the atom's nuclei.\n", + "- hartree_fock_energy : the Hartree Fock energy.\n", + "- total_energy : this is the ground state energy of the Hamiltonian (combining the energy, the nuclear repulsion and the static nuclear energy).\n", + "\n", + "It also contains the full VQE result from which we can get, for example:\n", + "- optimal_parameters : gives the results for the anzats parameters minimizing that expectation value.\n", + "- eigenstate : gives the ground state wave function.\n", + "\n", + "Note the all energy are presented in units of Hartree." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "437b3211", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "437b3211", + "outputId": "dbe14152-d540-4cd0-f294-b17824883a4c", + "tags": [] + }, + "outputs": [], + "source": [ + "chemistry_result_dict[\"total_energy\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a537d3c", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "9a537d3c", + "outputId": "bbb38543-5586-41d0-80a4-32ce72e3fa1b" + }, + "outputs": [], + "source": [ + "chemistry_result_dict[\"vqe_result\"][\"optimal_parameters\"]" + ] + }, + { + "cell_type": "markdown", + "id": "2375f3c3", + "metadata": { + "id": "2375f3c3" + }, + "source": [ + "Finally, we can compare the VQE solution to the classical solution by employing exact diagonalization:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c896576", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "5c896576", + "outputId": "f6ada73d-6bd4-440d-98c1-d17e70b57cde", + "tags": [] + }, + "outputs": [], + "source": [ + "mat = operator.to_matrix()\n", + "w, v = np.linalg.eig(mat)\n", + "print(\"exact result:\", np.real(min(w)))\n", + "print(\"vqe result:\", chemistry_result_dict[\"energy\"])" + ] + }, + { + "cell_type": "markdown", + "id": "TXF-IJT59B7j", + "metadata": { + "id": "TXF-IJT59B7j" + }, + "source": [ + "## **h2**\n", + "\n", + "hw-eff: width 4/depth34\n", + "\n", + "ucc: width 1/depth 6, width 4, depth 3\n", + "\n", + "total en -1.1342995783232035,\n", + "exact result: -1.8572750302023786,\n", + "vqe result: -1.854268572772183\n" + ] + }, + { + "cell_type": "markdown", + "id": "2qTUaxbEX5IF", + "metadata": { + "id": "2qTUaxbEX5IF" + }, + "source": [ + "## **h2o**\n", + "\n", + "hw-eff.: width 12/depth 375,\n", + "(conn map 0-1..10-11, reps 11)\n", + "\n", + "ucc: width 8/depth 1218, width 12/depth 1048\n", + "\n", + "total energy -71.7605079203085,\n", + "exact result: -23.544497240443615,\n", + "vqe result: -80.95442108093192" + ] + }, + { + "cell_type": "markdown", + "id": "bxRq_3-Jb4_0", + "metadata": { + "id": "bxRq_3-Jb4_0" + }, + "source": [ + "##**co2**\n", + "\n", + "hw-eff: width 24/depth 175\n", + "\n", + "ucc: width 20/depth 19767, width 24/depth 16968\n", + "\n", + "Error number 90001 occurred. The resources needed to execute this request are insufficient.\n", + " This may be due to computational limitations, or high load on Classiq's servers." + ] + }, + { + "cell_type": "markdown", + "id": "b998e321", + "metadata": { + "id": "b998e321" + }, + "source": [ + "[1] Abhinav Kandala, Antonio Mezzacapo, Kristan Temme, Maika Takita, Markus Brink, Jerry M. Chow, Jay M. Gambetta Hardware-efficient variational quantum eigensolver for small molecules and quantum magnets. Nature 549, 242 (2017)\n", + "\n", + "[2] Panagiotis Kl. Barkoutsos, Jerome F. Gonthier, Igor Sokolov, Nikolaj Moll, Gian Salis, Andreas Fuhrer, Marc Ganzhorn, Daniel J. Egger, Matthias Troyer, Antonio Mezzacapo, Stefan Filipp, and Ivano Tavernelli Quantum algorithms for electronic structure calculations: Particle-hole Hamiltonian and optimized wave-function expansions Phys. Rev. A 98, 022322 (2018)\n" + ] + } + ], + "metadata": { + "colab": { + "include_colab_link": true, + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 [Default]", + "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.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/community/womanium/assignments/Yasir_Mansour_hw4.ipynb b/community/womanium/assignments/Yasir_Mansour_hw4.ipynb new file mode 100644 index 00000000..dbe50b3f --- /dev/null +++ b/community/womanium/assignments/Yasir_Mansour_hw4.ipynb @@ -0,0 +1,1012 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "b7f74e3a-7dae-4939-a2ef-0ff82d8eadd0", + "metadata": {}, + "source": [ + "\n", + "# Assignment 6.12 - womanium 2024\n" + ] + }, + { + "cell_type": "markdown", + "id": "adc17ffc-b892-4a94-bebb-4ba74d208a9e", + "metadata": { + "tags": [] + }, + "source": [ + "## Advanced Algorithms Design\n", + "## _Quantum random walk_" + ] + }, + { + "cell_type": "markdown", + "id": "64b142e7-efbf-4205-bc87-112f21c69c09", + "metadata": { + "tags": [] + }, + "source": [ + "**Instructions - Final assignment**\n", + "\n", + "Follow the example from Bootcamp 4 for creating the quantum walk operator for the case of a circle with 4 nodes, and design the quantum walk operator for the case of a line with 16 nodes:\n" + ] + }, + { + "cell_type": "markdown", + "id": "7a7e4b5d-12fb-482f-9b59-b8bc4949854b", + "metadata": { + "tags": [] + }, + "source": [ + "**Tasks:**\n", + "\n", + "A.\n", + "\n", + "Create a well-detailed Python Jupyter notebook that explains your algorithm, including the code parts covered in class, and pictures/figures where relevant. \n", + "\n", + "Utilize the Python code from class: quantum_walk_circle_example.py. It can be found directly also in the Classiq Git Library in the community/womanium/assignments folder. \n", + "\n", + "Feel free to extend the example beyond the requirements here and what was covered in class.\n", + "\n", + "B.\n", + "\n", + "Contribute your notebook to the Classiq Git Library to the folder community/womanium/assignments. \n", + "\n", + "Follow the contribution guidelines in order to contribute - NO need to open an issue for this, you can directly open a PR.\n", + "\n", + "The PR title should be: Womanium Final Assignment . \n", + "The file name should be in the following format: __hw4.ipynb." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "fd9eebc7-b78b-4aa7-8614-fbd7dc07f452", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n", + "qiskit-ibm-runtime 0.25.0 requires pydantic>=2.5.0, but you have pydantic 1.10.17 which is incompatible.\n", + "qc-grader 0.19.7 requires networkx==3.2.1, but you have networkx 2.8.8 which is incompatible.\u001b[0m\u001b[31m\n", + "\u001b[0mNote: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install -U -q classiq" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "202628d6-3fe3-47fa-8a15-04b7fd9716f4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *" + ] + }, + { + "cell_type": "markdown", + "id": "9f608bac-c3eb-495e-9015-3e6396c7543c", + "metadata": { + "tags": [] + }, + "source": [ + "# Implementation\n", + "\n", + "Implementation of a quantum random walk on a circle/one-dimensional line graph with size num_nodes. The core components are:\n", + "\n", + "1. **Initialization**:\n", + " - Setting the number of nodes and the size of the register.\n", + "\n", + "2. **Quantum State Preparation**:\n", + " - The prepare_minus function prepares a quantum state by applying an X gate (bit-flip) followed by a Hadamard gate (superposition) to a qubit x.\n", + " - The diffuzer_oracle function modifies an auxiliary qubit based on whether x is non-zero.\n", + " - The zero_diffuzer function allocates an auxiliary qubit, prepares it in the minus state, and applies the diffuzer_oracle.\n", + "\n", + "3. **W Operator**:\n", + " - The W_iteration function computes probabilities for transitioning between adjacent vertices in a graph.\n", + "\n", + "4. **Edge Oracle**:\n", + " - The edge_oracle function checks whether vertices and adjacent_vertices are adjacent and sets the result in the output qubit res.\n", + "\n", + "5. **Bitwise Swap**:\n", + " - The bitwise_swap function swaps corresponding qubits between two arrays x and y.\n", + "\n", + "6. **S Operator**:\n", + " - The S_operator function applies the edge oracle and swaps qubits if the result is 1.\n", + "\n", + "7. **Main Function**:\n", + " - The main function allocates qubits for vertices and adjacent_vertices.\n", + " - It applies the W operator and S operator sequentially.\n", + "\n", + "In summary, this program simulates a quantum random walk on a graph, where the walker's position is represented by quantum states. \n", + "\n", + "The W operator updates the probabilities for transitioning between adjacent vertices, and the S operator performs a random step by applying an edge oracle to ensure vertex adjacency and swaps qubits accordingly.\n" + ] + }, + { + "cell_type": "markdown", + "id": "bbe3dfa3-2265-44af-b708-9a0ad189f5bf", + "metadata": {}, + "source": [ + "\n", + "## Common functions for circles or lines\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "425c8fd2-f8f5-409b-a569-d923819437c4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Prepares the minus state (aux qubit) for the diffuzer oracle\n", + "@qfunc\n", + "def prepare_minus(x: QBit):\n", + " X(x)\n", + " H(x)\n", + "\n", + "# x: current node\n", + "@qfunc\n", + "def diffuzer_oracle(aux: Output[QNum],x:QNum):\n", + " aux^=(x!=0)\n", + "\n", + "# Zero diffuser using Grover's algorithm technique\n", + "# x: current node \n", + "@qfunc\n", + "def zero_diffuzer(x: QNum):\n", + " aux = QNum('aux')\n", + " allocate(1,aux)\n", + " within_apply(compute=lambda: prepare_minus(aux),\n", + " action=lambda: diffuzer_oracle)\n", + "\n", + "# non-zero probabilities for allowable transitions\n", + "# @qfunc\n", + "# def W_iteration\n", + "\n", + "# Iterates over all possible positions and applies \n", + "# the W_iteration for each position.\n", + "@qfunc \n", + "def W_operator(vertices:QNum, adjacent_vertices: QNum):\n", + " for i in range(num_nodes):\n", + " W_iteration(i,vertices,adjacent_vertices)\n", + "\n", + "# Edge oracle for checking adjacency of 2 vertices\n", + "#\n", + "#@qfunc\n", + "#def edge_oracle\n", + "\n", + "# Swaps the contents of two quantum registers: moves the walker\n", + "@qfunc \n", + "def bitwise_swap(x: QArray[QBit], y:QArray[QBit]):\n", + " repeat(count= x.len,\n", + " iteration= lambda i: SWAP(x[i],y[i]))\n", + "\n", + "# shift operator moving the walker if vertices adjacent\n", + "@qfunc \n", + "def S_operator(vertices:QNum, adjacent_vertices: QNum):\n", + " res = QNum('res')\n", + " edge_oracle(res,vertices,adjacent_vertices)\n", + " control(ctrl= res==1,\n", + " operand= lambda: bitwise_swap(vertices,adjacent_vertices))\n" + ] + }, + { + "cell_type": "markdown", + "id": "9761696b-cefe-4ea0-9c91-ebd33af62e22", + "metadata": {}, + "source": [ + "## Circle-specific functions\n", + "\n", + "Here we have the function W_iteration with the probability of 0.5 going in either direction.\n", + "\n", + "What is special about a random walk on a circle is that the node (0) and the node (num_nodes-1) are adjacent. This fact is taken care of in the function edge_oracle." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "5ab73e30-56fd-4028-bb13-e2f883a4e3ae", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "\n", + "# non-zero probabilities for allowable transitions\n", + "def W_iteration(i:int,vertices: QNum, adjacent_vertices:QNum):\n", + " prob = [0] * num_nodes\n", + " prob[(i+1)% num_nodes]=0.5\n", + " prob[(i-1)% num_nodes]=0.5\n", + " print(f'State={i}, prob vec ={prob}')\n", + " \n", + " control(ctrl=vertices==i,\n", + " operand=lambda: within_apply(\n", + " compute= lambda: \n", + " inplace_prepare_state(probabilities=prob, bound=0.01, target=adjacent_vertices),\n", + " action= lambda: \n", + " zero_diffuzer(adjacent_vertices)))\n", + " \n", + "# Edge oracle for checking adjacency of two vertices \n", + "@qfunc\n", + "def edge_oracle(res:Output[QBit], vertices: QNum, adjacent_vertices: QNum):\n", + " diff = vertices - adjacent_vertices\n", + " mod = diff%num_nodes\n", + " res |= (mod == 1) | (mod == num_nodes-1)\n" + ] + }, + { + "cell_type": "markdown", + "id": "423cf377-1bc7-4637-855c-b82ced39cca9", + "metadata": {}, + "source": [ + "## Circle with 4 nodes" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "e39e695c-cc7d-4983-ba7b-2d076262a66b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Circle with 4 Nodes \n", + "\n", + "# Size of the register required for the number of nodes\n", + "size = 2\n", + "num_nodes = 2**size\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a863aa31-dc65-4ad4-9985-4fca062ab269", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Main quantum walk operator function\n", + "# applies the W and S operators after initializing\n", + "# vertices\n", + "@qfunc \n", + "def main(vertices:Output[QNum], adjacent_vertices:Output[QNum]):\n", + "\n", + " allocate(size,vertices)\n", + " hadamard_transform(vertices)\n", + " allocate(size,adjacent_vertices)\n", + "\n", + " W_operator(vertices,adjacent_vertices)\n", + " S_operator(vertices,adjacent_vertices)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "1427b784-9701-4338-aec2-5cb5566a6d32", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "State=0, prob vec =[0, 0.5, 0, 0.5]\n", + "State=1, prob vec =[0.5, 0, 0.5, 0]\n", + "State=2, prob vec =[0, 0.5, 0, 0.5]\n", + "State=3, prob vec =[0.5, 0, 0.5, 0]\n" + ] + } + ], + "source": [ + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "#show(qprog)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "22cec3d3-aef0-46c6-9de2-74ee40d81b96", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "write_qmod(qmod,\"random4\")" + ] + }, + { + "cell_type": "markdown", + "id": "0c9a5e9c-ed50-44d1-b9ed-665f96274a92", + "metadata": { + "tags": [] + }, + "source": [ + "## Circle with 8 nodes" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "a5063b48-425c-4d73-8d6e-8b575cc61be3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Circle with 8 Nodes \n", + "\n", + "# Size of the register required for the number of nodes\n", + "size = 3\n", + "num_nodes = 8\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "d137cf61-e92b-46d4-870e-4d1fc021650c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Main quantum walk operator function\n", + "@qfunc \n", + "def main(vertices:Output[QNum], adjacent_vertices:Output[QNum]):\n", + "\n", + " allocate(size,vertices)\n", + " hadamard_transform(vertices)\n", + " allocate(size,adjacent_vertices)\n", + "\n", + " W_operator(vertices,adjacent_vertices)\n", + " S_operator(vertices,adjacent_vertices)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "94168a88-cdb4-411c-a162-52adf0c622bb", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "State=0, prob vec =[0, 0.5, 0, 0, 0, 0, 0, 0.5]\n", + "State=1, prob vec =[0.5, 0, 0.5, 0, 0, 0, 0, 0]\n", + "State=2, prob vec =[0, 0.5, 0, 0.5, 0, 0, 0, 0]\n", + "State=3, prob vec =[0, 0, 0.5, 0, 0.5, 0, 0, 0]\n", + "State=4, prob vec =[0, 0, 0, 0.5, 0, 0.5, 0, 0]\n", + "State=5, prob vec =[0, 0, 0, 0, 0.5, 0, 0.5, 0]\n", + "State=6, prob vec =[0, 0, 0, 0, 0, 0.5, 0, 0.5]\n", + "State=7, prob vec =[0.5, 0, 0, 0, 0, 0, 0.5, 0]\n" + ] + } + ], + "source": [ + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "#show(qprog)" + ] + }, + { + "cell_type": "markdown", + "id": "7458e3ac-0e87-49e2-9139-59ee31fc27f4", + "metadata": {}, + "source": [ + "## Circle with 16 nodes" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "7e7ad59c-80ca-4452-af10-883711c9b104", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Circle with 16 Nodes \n", + "\n", + "# Size of the register required for the number of nodes\n", + "size = 4\n", + "num_nodes = 16\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "d3444344-5117-4021-9d15-1476582bf61d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Main quantum walk function\n", + "@qfunc \n", + "def main(vertices:Output[QNum], adjacent_vertices:Output[QNum]):\n", + "\n", + " allocate(size,vertices)\n", + " hadamard_transform(vertices)\n", + " allocate(size,adjacent_vertices)\n", + "\n", + " W_operator(vertices,adjacent_vertices)\n", + " S_operator(vertices,adjacent_vertices)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "d30601d3-5b4f-4b23-af9d-f93d0a4f6777", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "State=0, prob vec =[0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5]\n", + "State=1, prob vec =[0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=2, prob vec =[0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=3, prob vec =[0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=4, prob vec =[0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=5, prob vec =[0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=6, prob vec =[0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=7, prob vec =[0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0]\n", + "State=8, prob vec =[0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0]\n", + "State=9, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0]\n", + "State=10, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0]\n", + "State=11, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0]\n", + "State=12, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0]\n", + "State=13, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0]\n", + "State=14, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5]\n", + "State=15, prob vec =[0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0]\n" + ] + } + ], + "source": [ + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "#show(qprog)" + ] + }, + { + "cell_type": "markdown", + "id": "ccfdf941-9d91-402f-a200-ccc266f73e99", + "metadata": {}, + "source": [ + "## Line-specific functions\n", + "The function W_iteration defines the transition probabilities for a line. At the beginning and at the end of the line the walker can go only in one direction (probability = 1). For all other nodes the probability going in either direction is 0.5.\n", + "\n", + "Here the function edge_oracle just has to check whether the vertices are adjacent (distance = 1)." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "47e777d7-6527-4901-a034-951c624037e4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "\n", + "# non-zero probabilities for allowable probabilities\n", + "def W_iteration(i:int,vertices: QNum, adjacent_vertices:QNum):\n", + " prob = [0] * (num_nodes)\n", + " if i == 0:\n", + " prob[i + 1] = 1.0\n", + " elif i == (num_nodes) -1:\n", + " prob[i - 1] = 1.0\n", + " else:\n", + " prob[i - 1] = 0.5\n", + " prob[i + 1] = 0.5\n", + " print(f'State={i}, prob vec ={prob}')\n", + " \n", + " control(ctrl=vertices==i,\n", + " operand=lambda: within_apply(\n", + " compute= lambda: \n", + " inplace_prepare_state(probabilities=prob, bound=0.01, target=adjacent_vertices),\n", + " action= lambda: \n", + " zero_diffuzer(adjacent_vertices)))\n", + "\n", + "\n", + "# Edge oracle for checking adjacency of two vertices\n", + "@qfunc\n", + "def edge_oracle(res:Output[QBit], vertices: QNum, adjacent_vertices: QNum):\n", + " diff = vertices - adjacent_vertices\n", + " res |= (diff == 1) | (diff == -1)\n" + ] + }, + { + "cell_type": "markdown", + "id": "07488d17-7cac-4e36-8335-e3303cff8efe", + "metadata": {}, + "source": [ + "## Line with 4 nodes" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "92d3f78c-ee23-45bf-acba-6d0ff0608847", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Line with 4 Nodes\n", + "\n", + "# Register size to accomodate the number of vertices\n", + "size = 2\n", + "num_nodes = 2**size\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "613c61cc-10ea-4950-a262-3dd572c8701c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Main quantum walk function\n", + "@qfunc \n", + "def main(vertices:Output[QNum], adjacent_vertices:Output[QNum]):\n", + "\n", + " allocate(size,vertices)\n", + " hadamard_transform(vertices)\n", + " allocate(size,adjacent_vertices)\n", + "\n", + " W_operator(vertices,adjacent_vertices)\n", + " S_operator(vertices,adjacent_vertices)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "46fca7f3-3106-416d-a3f8-379f7095f8fa", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "State=0, prob vec =[0, 1.0, 0, 0]\n", + "State=1, prob vec =[0.5, 0, 0.5, 0]\n", + "State=2, prob vec =[0, 0.5, 0, 0.5]\n", + "State=3, prob vec =[0, 0, 1.0, 0]\n" + ] + } + ], + "source": [ + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "#show(qprog)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "9dd17d8c-83dd-463d-b155-9b8c949f97d1", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "write_qmod(qmod,\"random4\")" + ] + }, + { + "cell_type": "markdown", + "id": "cfbc239f-2bfb-496a-a752-1a84f657ac3f", + "metadata": { + "tags": [] + }, + "source": [ + "## Line with 8 nodes" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "08283335-a49f-4d6e-a702-fb76ab01724b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Line with 8 Nodes\n", + "\n", + "# Register size to accomodate the number of vertices\n", + "size = 3\n", + "num_nodes = 2**size\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "07a57ceb-c1da-47d7-8d6b-45e18667d747", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Main quantum walk function\n", + "@qfunc \n", + "def main(vertices:Output[QNum], adjacent_vertices:Output[QNum]):\n", + "\n", + " allocate(size,vertices)\n", + " hadamard_transform(vertices)\n", + " allocate(size,adjacent_vertices)\n", + "\n", + " W_operator(vertices,adjacent_vertices)\n", + " S_operator(vertices,adjacent_vertices)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "fb711141-eadd-4ac5-bb1d-fbd31bb71f8f", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "State=0, prob vec =[0, 1.0, 0, 0, 0, 0, 0, 0]\n", + "State=1, prob vec =[0.5, 0, 0.5, 0, 0, 0, 0, 0]\n", + "State=2, prob vec =[0, 0.5, 0, 0.5, 0, 0, 0, 0]\n", + "State=3, prob vec =[0, 0, 0.5, 0, 0.5, 0, 0, 0]\n", + "State=4, prob vec =[0, 0, 0, 0.5, 0, 0.5, 0, 0]\n", + "State=5, prob vec =[0, 0, 0, 0, 0.5, 0, 0.5, 0]\n", + "State=6, prob vec =[0, 0, 0, 0, 0, 0.5, 0, 0.5]\n", + "State=7, prob vec =[0, 0, 0, 0, 0, 0, 1.0, 0]\n" + ] + } + ], + "source": [ + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "#show(qprog)" + ] + }, + { + "cell_type": "markdown", + "id": "7b486184-7850-4c58-baac-9e89a942e059", + "metadata": { + "tags": [] + }, + "source": [ + "## Line with 16 nodes" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "52ccbff2-f15f-4fe2-86fd-6e1d0128f428", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Line with 16 Nodes\n", + "\n", + "# Register size to accomodate the number of vertices\n", + "size = 4\n", + "num_nodes = 2**size\n" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "e773bbb1-e532-477e-8891-c47f8f4f1f8d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Main quantum walk function\n", + "@qfunc \n", + "def main(vertices:Output[QNum], adjacent_vertices:Output[QNum]):\n", + "\n", + " allocate(size,vertices)\n", + " hadamard_transform(vertices)\n", + " allocate(size,adjacent_vertices)\n", + "\n", + " W_operator(vertices,adjacent_vertices)\n", + " S_operator(vertices,adjacent_vertices)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "c3833a55-49af-4214-be22-5b52eaa22ba6", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "State=0, prob vec =[0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=1, prob vec =[0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=2, prob vec =[0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=3, prob vec =[0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=4, prob vec =[0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=5, prob vec =[0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=6, prob vec =[0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0]\n", + "State=7, prob vec =[0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0, 0]\n", + "State=8, prob vec =[0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0, 0]\n", + "State=9, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0, 0]\n", + "State=10, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0, 0]\n", + "State=11, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0, 0]\n", + "State=12, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0]\n", + "State=13, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 0]\n", + "State=14, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0.5]\n", + "State=15, prob vec =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0]\n" + ] + } + ], + "source": [ + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "#show(qprog)" + ] + }, + { + "cell_type": "markdown", + "id": "4b28d548-febf-43b3-9271-6cab28fd2cbb", + "metadata": {}, + "source": [ + "# Results" + ] + }, + { + "cell_type": "markdown", + "id": "b7d6c2a8-063f-4ffe-bf3c-18212aa1d57f", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "## Number of qubits vs. nodes\n", + "\n", + "| random walk | num_nodes | transpiled qubits |\n", + "| :- | :-: | :-: |\n", + "| circle | 4 | 13 |\n", + "| circle | 8 | 22|\n", + "| circle | 16 | 33 |\n", + "| line | 4 | 17 |\n", + "| line | 8 | 25 |\n", + "| line | 16 | 37 |\n", + "\n", + "Here we see that the more nodes we have, the more transpiled qubits are going to be used. Lines need more qubits than circles." + ] + }, + { + "cell_type": "markdown", + "id": "2d8f26a8-18aa-4dda-a3ed-a3974e0184b9", + "metadata": {}, + "source": [ + "## Circle 4 nodes" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "335019e0-e185-41d5-b894-6116ada649d6", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import matplotlib.image as mpimg\n", + "\n", + "img = mpimg.imread('circle4.png')\n", + "plt.imshow(img)\n", + "plt.axis('off') # Turn off axis numbers\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "6bd34621-0458-4a1b-ac69-62892bcba54c", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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zWj37t2EQiFqa2t56KGHeOqppxgZGWHVqlX5c9xisRjJZNJ3J4tffHJ+Z2cnTz75ZP53yHYrtLW18dxzzzE+Pp4/ipZMJn0XAoXr43kee/fuZdmyZRhjuPPOO3nzzTfp6OggFouxevVqXnrpJaLRKK7r5mdc8evnk0gk+O///m8aGxtpbGxk06ZNPPHEE4yNjbF+/XpSqRTpdDq/rZXLAaj5oDCbgcLxV57nYa2lvr6eM2fOMD4+TltbG3fffTfvv/8+Dz/8MI7jcP78eV5++WVSqZSvdhhgUk0rk8kQCoW46667sNbS2NjICy+8QDwe56abbuLGG28kk8lw8OBBDh065LtAK+R5HqdOnaKqqoqqqio6OzupqanhN3/zNzlx4gQ33ngjzc3NZDIZXn31Vfr6/DcxZKFkMkl3dzcbN26kp6eHeDzO2rVrueOOO/jggw947LHHMMbQ39/Pq6++mp/9wm/b23xTM3OGck1NyIZAT08P0WiUxx57jNtvv50PPviAbdu28f777/PEE08QiURoaWkpcamnVth0huyRtIMHD7J582b27dtHPB7PDwd49tlneeGFF7j55pvznex+U7g+uSmHTpw4wUMPPcSjjz6aH+ycSCR44oknOHjwIDfffDPg3yZnYSB1dnayYMECvvOd77Bjxw7279/Ptm3beOedd/j5z39ObW0tixcvLmFpS0s1szmKx+M8//zzVFdXk0wmefTRR3njjTc4fvw4NTU11NfXMzo6WjbfkqdPn+bnP/851dXVtLa2sn79ep566inGx8fZtGkT4+PjZdGUyYXTO++8Q21tLalUiq1bt+bPEgBoa2vj9OnTpSzmtBljGB8f57nnniMWi5FKpXjsscd49dVX6ejoYMGCBfkplqZ7PdmgUc1sDnIBlU6nGRwcJBqNYq2lvb09P4L78OHDDA4OltXGdfbsWdrb21m5ciWffvop8XictrY2brvtNt54442yCLPC2ubQ0FB+Hfbv348xhltvvZWamhoOHTpU4pJOT277SSaT+W0tnU7T1dWVb0Lv378/EPOrzZZqZrN08fRDxhhGRkZIJBLcfffdtLS0cPTo0fxIbb+bqubY0dHBHXfcwaJFi2hububFF1/0ff9SoYvnumtvb+f2228nHA6TyWTYvXt32Ux8efE0PSMjI2QyGe6++26WLFnCwYMH+fjjj6d8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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import matplotlib.image as mpimg\n", + "\n", + "img = mpimg.imread('circle4hist.jpg')\n", + "plt.imshow(img)\n", + "plt.axis('off') # Turn off axis numbers\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "5216c457-12f6-451e-92a8-d43c5a15e98f", + "metadata": {}, + "source": [ + "## Line 8 nodes" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "c6ebdc89-ba16-41c4-b623-7862a0ae29af", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import matplotlib.image as mpimg\n", + "\n", + "img = mpimg.imread('line8.png')\n", + "plt.imshow(img)\n", + "plt.axis('off') # Turn off axis numbers\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "6dffee97-669a-4c03-a506-55c8ebbe0be1", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import matplotlib.image as mpimg\n", + "\n", + "img = mpimg.imread('line8hist.jpg')\n", + "plt.imshow(img)\n", + "plt.axis('off') # Turn off axis numbers\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "8cb5df08-342e-4cfd-b65e-42a8528b6969", + "metadata": {}, + "source": [ + "## Line 16 nodes\n", + "![alt text](line16.png)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "62827e5d-82f4-433e-80ea-7eecf1dedbfb", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import matplotlib.image as mpimg\n", + "\n", + "img = mpimg.imread('line16.png')\n", + "plt.imshow(img)\n", + "plt.axis('off') # Turn off axis numbers\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "a29b9882-972f-4f52-b4d2-0eb4d4ee866e", + "metadata": {}, + "source": [ + "eof" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 [Default]", + "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.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}