From 5debc66747a288d375264e99a766d983dc1d5f24 Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Tue, 21 May 2024 23:42:34 +0200 Subject: [PATCH 01/18] Add files via upload --- .../HW1/Hisham_Mansour_HW1_QClass2024.ipynb | 805 ++++++++++++++++++ 1 file changed, 805 insertions(+) create mode 100644 community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb diff --git a/community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb b/community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb new file mode 100644 index 00000000..55323c62 --- /dev/null +++ b/community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb @@ -0,0 +1,805 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "XtC66r2Y5_eT" + }, + "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](https://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](https://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](https://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", + "source": [ + "!pip install -U classiq" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "collapsed": true, + "id": "156317w1BFqw", + "outputId": "3dda7746-c565-421d-ec6f-f18a4e7d0047" + }, + "execution_count": 1, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Collecting classiq\n", + " Downloading classiq-0.41.1-py3-none-any.whl (398 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m398.1/398.1 kB\u001b[0m \u001b[31m4.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting ConfigArgParse<2.0.0,>=1.5.3 (from classiq)\n", + " Downloading ConfigArgParse-1.7-py3-none-any.whl (25 kB)\n", + "Collecting Pyomo<6.6,>=6.5 (from classiq)\n", + " Downloading Pyomo-6.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (10.7 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m10.7/10.7 MB\u001b[0m \u001b[31m19.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting black<25.0,>=24.0 (from classiq)\n", + " Downloading black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.8/1.8 MB\u001b[0m \u001b[31m29.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting httpx<1,>=0.23.0 (from classiq)\n", + " Downloading httpx-0.27.0-py3-none-any.whl (75 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.6/75.6 kB\u001b[0m \u001b[31m6.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: keyring<24.0.0,>=23.5.0 in /usr/lib/python3/dist-packages (from classiq) (23.5.0)\n", + "Requirement already satisfied: matplotlib<4.0.0,>=3.4.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (3.7.1)\n", + "Collecting networkx<3.0.0,>=2.5.1 (from classiq)\n", + " Downloading networkx-2.8.8-py3-none-any.whl (2.0 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m31.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: numexpr<3.0.0,>=2.7.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.10.0)\n", + "Requirement already satisfied: numpy<2.0.0,>=1.20.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.25.2)\n", + "Collecting packaging<23.0,>=22.0 (from classiq)\n", + " Downloading packaging-22.0-py3-none-any.whl (42 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m42.6/42.6 kB\u001b[0m \u001b[31m2.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: pandas<3.0.0,>=1.4.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.0.3)\n", + "Requirement already satisfied: plotly<6.0.0,>=5.7.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (5.15.0)\n", + "Collecting pydantic<2.0.0,>=1.9.1 (from classiq)\n", + " Downloading pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.1/3.1 MB\u001b[0m \u001b[31m34.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: scipy<2.0.0,>=1.10.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.11.4)\n", + "Collecting sympy<1.11.0,>=1.9.0 (from classiq)\n", + " Downloading sympy-1.10.1-py3-none-any.whl (6.4 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.4/6.4 MB\u001b[0m \u001b[31m55.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: tabulate<1,>=0.8.9 in /usr/local/lib/python3.10/dist-packages (from classiq) (0.9.0)\n", + "Requirement already satisfied: click>=8.0.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (8.1.7)\n", + "Collecting mypy-extensions>=0.4.3 (from black<25.0,>=24.0->classiq)\n", + " Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n", + "Collecting pathspec>=0.9.0 (from black<25.0,>=24.0->classiq)\n", + " Downloading pathspec-0.12.1-py3-none-any.whl (31 kB)\n", + "Requirement already satisfied: platformdirs>=2 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.2.2)\n", + "Requirement already satisfied: tomli>=1.1.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (2.0.1)\n", + "Requirement already satisfied: typing-extensions>=4.0.1 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.11.0)\n", + "Requirement already satisfied: anyio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7.1)\n", + "Requirement already satisfied: certifi in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (2024.2.2)\n", + "Collecting httpcore==1.* (from httpx<1,>=0.23.0->classiq)\n", + " Downloading httpcore-1.0.5-py3-none-any.whl (77 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.9/77.9 kB\u001b[0m \u001b[31m3.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: idna in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7)\n", + "Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (1.3.1)\n", + "Collecting h11<0.15,>=0.13 (from httpcore==1.*->httpx<1,>=0.23.0->classiq)\n", + " Downloading h11-0.14.0-py3-none-any.whl (58 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m6.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.2.1)\n", + "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (0.12.1)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (4.51.0)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.4.5)\n", + "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (9.4.0)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (3.1.2)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (2.8.2)\n", + "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2023.4)\n", + "Requirement already satisfied: tzdata>=2022.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2024.1)\n", + "Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from plotly<6.0.0,>=5.7.0->classiq) (8.3.0)\n", + "Collecting ply (from Pyomo<6.6,>=6.5->classiq)\n", + " Downloading ply-3.11-py2.py3-none-any.whl (49 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.6/49.6 kB\u001b[0m \u001b[31m4.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy<1.11.0,>=1.9.0->classiq) (1.3.0)\n", + "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.7->matplotlib<4.0.0,>=3.4.3->classiq) (1.16.0)\n", + "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio->httpx<1,>=0.23.0->classiq) (1.2.1)\n", + "Installing collected packages: ply, sympy, Pyomo, pydantic, pathspec, packaging, networkx, mypy-extensions, h11, ConfigArgParse, httpcore, black, httpx, classiq\n", + " Attempting uninstall: sympy\n", + " Found existing installation: sympy 1.12\n", + " Uninstalling sympy-1.12:\n", + " Successfully uninstalled sympy-1.12\n", + " Attempting uninstall: pydantic\n", + " Found existing installation: pydantic 2.7.1\n", + " Uninstalling pydantic-2.7.1:\n", + " Successfully uninstalled pydantic-2.7.1\n", + " Attempting uninstall: packaging\n", + " Found existing installation: packaging 24.0\n", + " Uninstalling packaging-24.0:\n", + " Successfully uninstalled packaging-24.0\n", + " Attempting uninstall: networkx\n", + " Found existing installation: networkx 3.3\n", + " Uninstalling networkx-3.3:\n", + " Successfully uninstalled networkx-3.3\n", + "\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", + "torch 2.3.0+cu121 requires nvidia-cublas-cu12==12.1.3.1; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cuda-cupti-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cuda-nvrtc-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cuda-runtime-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cudnn-cu12==8.9.2.26; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cufft-cu12==11.0.2.54; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-curand-cu12==10.3.2.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cusolver-cu12==11.4.5.107; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cusparse-cu12==12.1.0.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-nccl-cu12==2.20.5; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-nvtx-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\u001b[0m\u001b[31m\n", + "\u001b[0mSuccessfully installed ConfigArgParse-1.7 Pyomo-6.5.0 black-24.4.2 classiq-0.41.1 h11-0.14.0 httpcore-1.0.5 httpx-0.27.0 mypy-extensions-1.0.0 networkx-2.8.8 packaging-22.0 pathspec-0.12.1 ply-3.11 pydantic-1.10.15 sympy-1.10.1\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "import classiq\n", + "classiq.authenticate()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "EaDN5EkVC58C", + "outputId": "46134709-44e6-4049-f543-92e6f6641454" + }, + "execution_count": 2, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Your user code: PMKD-TJLQ\n", + "If a browser doesn't automatically open, please visit this URL from any trusted device: https://auth.classiq.io/activate?user_code=PMKD-TJLQ\n" + ] + } + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "id": "DpF2vKUh5_e7" + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "\n", + "# Define a quantum function using the @qfunc decorator\n", + "@qfunc\n", + "def foo(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", + " foo(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": 4, + "metadata": { + "id": "UB612BIP5_fE", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "8a173bc3-d74f-44a6-9d0e-403601e3a6bb" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/e76daf18-d5ae-43e2-85bc-44087b930754?version=0.41.1\n" + ] + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "execute(qprog)\n", + "show(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](https://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](https://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](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/functions#syntax)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "id": "fNOTP83I5_fJ", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "6cb4b516-dc5c-4800-dc96-bcd778c7691f" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/765b971e-b440-4a96-87bb-74df82556089?version=0.41.1\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "ExecutionJob(id='5b958421-8492-4402-9ebb-888191d857f0')" + ] + }, + "metadata": {}, + "execution_count": 7 + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Define a quantum function using the @qfunc decorator\n", + "@qfunc\n", + "def bell_pair(q_1: QBit, q_2: QBit) -> None:\n", + " H(target=q_1)\n", + " CX(control=q_1,target=q_2)\n", + "\n", + "# Define a main function\n", + "@qfunc\n", + "def main(out_1: Output[QBit], out_2: Output[QBit]) -> None:\n", + " allocate(1, out_1)\n", + " allocate(1, out_2)\n", + " bell_pair(q_1=out_1,q_2=out_2)\n", + "# Your code here:\n", + "\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": 9, + "metadata": { + "id": "Y-c9r6OT5_fO", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "3ab1dc27-a011-4fbe-f435-6e1315fe2ded" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/f7e18847-8cd6-4273-af93-1777965f19ef?version=0.41.1\n" + ] + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "# Define a quantum function using the @qfunc decorator\n", + "@qfunc\n", + "def bell_pair(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(out: Output[QArray]) -> None:\n", + " allocate(2, out)\n", + " bell_pair(out)\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "execute(qprog)\n", + "show(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](https://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": 11, + "metadata": { + "id": "vFrcPTqi5_fS", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "ebc0c3c4-671a-4c21-feb2-10dbdeaa4df3" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/7c5128dc-3e49-42da-ad3d-ddc9d7414221?version=0.41.1\n" + ] + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "@qfunc\n", + "def h_transform(q: QArray) -> None:\n", + " repeat(count=q.len, iteration=lambda i: H(target=q[i]))\n", + " #repeat(q.len, lambda i: H(q[i]))\n", + "\n", + "# Define a main function\n", + "@qfunc\n", + "def main(out: Output[QArray]) -> None:\n", + " allocate(10, out)\n", + " h_transform(out)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "execute(qprog)\n", + "show(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](https://en.wikipedia.org/wiki/Closure_(computer_programming)) in classical languages.\n", + "\n", + "See also [Capturing context variables and parameters](https://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](https://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": 12, + "metadata": { + "id": "tD_aBHoU5_fW" + }, + "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" + }, + "outputs": [], + "source": [ + "def unitary(\n", + " elements: CArray[CArray[CReal]],\n", + " target: QArray[QBit],\n", + ") -> None:\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "id": "6Js8fNbl5_fa", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "e806c96c-489b-41ab-f46f-ea435840ee79" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/350d1e48-e4ce-4745-a207-d1b8535c4690?version=0.41.1\n" + ] + } + ], + "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", + "execute(qprog)\n", + "show(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](https://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": 16, + "metadata": { + "id": "vvMbP91D5_fc", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "d92aadd8-4a5b-41a7-f565-5d0660569da6" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/520223e2-7846-41d9-ba66-1dcb838cf17b?version=0.41.1\n" + ] + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "'''\n", + "@qfunc\n", + "def h_transform(q: QArray) -> None:\n", + " #repeat(count=res.len, iteration=lambda i: H(target=res[i]))\n", + " apply_to_all(H, q)\n", + "# Define a main function\n", + "@qfunc\n", + "def main(out: Output[QArray]) -> None:\n", + " allocate(10, out)\n", + " h_transform(out)\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", + "\n", + "@qfunc\n", + "def h_transform(q: QArray[QBit]) -> None:\n", + " my_apply_to_all(lambda t: H(t), q)\n", + "\n", + "\n", + "@qfunc\n", + "def main(q: Output[QArray[QBit]]) -> None:\n", + " allocate(10, q)\n", + " h_transform(q)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "execute(qprog)\n", + "show(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](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/quantum-operators/#syntax).\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "id": "00trO6SJ5_ff", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "02ef558f-f0ae-47b9-c949-c8e855f537ff" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/45b7fcda-53bb-4980-82d5-0421f1000d4c?version=0.41.1\n" + ] + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "from classiq.qmod.symbolic import pi\n", + "\n", + "\n", + "@qfunc\n", + "def my_ctry(control_bit: QBit, target_bit: QBit) -> None:\n", + " control(control_bit, lambda: RY(pi / 2, target_bit))\n", + "\n", + "\n", + "@qfunc\n", + "def main(control_bit: Output[QBit], target_bit: Output[QBit]) -> None:\n", + " allocate(1, control_bit)\n", + " allocate(1, target_bit)\n", + " my_ctry(control_bit, target_bit)\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "execute(qprog)\n", + "show(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](https://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](https://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": 19, + "metadata": { + "id": "IohNdRCA5_fi", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "d64d356d-f4dd-4882-9291-1eab312604a7" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/c34fb3f7-8aa9-4f9d-bda7-84416f49c600?version=0.41.1\n" + ] + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "@qfunc\n", + "def main(x: Output[QNum], target: Output[QBit]) -> None:\n", + " prepare_int(7, x)\n", + " allocate(1, target)\n", + " control(x == 7, lambda: X(target))\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + }, + "colab": { + "provenance": [] + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file From 215b05c1a176077afc1d0d863c20f15061e47aec Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Wed, 29 May 2024 01:07:46 +0200 Subject: [PATCH 02/18] Add files via upload --- ...am_Mansour_HW2_QClass2024.ipynb - Colab.pdf | Bin 0 -> 119117 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb - Colab.pdf diff --git a/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb - Colab.pdf b/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb - Colab.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4ca7ee3a8ae9c2e70c1d2bf102f99bc7025ac1b9 GIT binary patch literal 119117 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¨Nea~Ly@@0ccXY-Cb6Ql6 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%0DR_y*BydlLo{o6D3(67vj^%2)W*3DYNr zrx{0j3II+yM%G!tq7Nbhl(HI#Nj>U!kJAmZ*H{b({>@xCxI!PCqhe@Vgk6R& zFoFA!EeBELA$d2Lv(j1 zx$lP?8~JuS$H_s^8#WfL>bWXu2bdi(j*KcB!q*~2tgxZ!&JU^u)hCmoqYr4@CDynet^wj}pQM8Zf)pt=a?2z zQs>t^ZTr~qA9}yTH8>G5kxx6N0u@brkcSL>P%olb&^|*b8(J5v9N_1iFz1zP9TaQt z%YQfSEI{f2fqD&9*#0)!)^ZO*m%#I=Mr>T>>t>VRO>B3tQpn{u0UcVKk>oB@UwMZFKn^UETYi@1KxM8tkRr2xV%ieFUCb}0eB)a5&+`aNOZz;fx6~_+%YaH`y z6e2ADAw>MBF8VRH|60$X!~DDLvqw2Pq@_Gd2UpTK%~54u5Gsu%96S76C<1EH#C#3R7TRbJ)R?Z@0?ubQT2Rt7zSb{Pmi4=nSRNb zR(a00b~-x4A2o4k4|q}8sUVTbwZEdw6_aR*?_IT&l-v+I(Z)w1JXDVIw<&4_-;NcG zigELlZ*pge>wNSiBM?3SNB-)24jgShm3S))-*e;Rt@~CNf43S3=__rKc;XFc^wZnL z-28R3uBk0*;p_FmTFyIb?38FSVgjf%Tu-W zvZICbm>S?_EW7UbsE^GJw9u%95LkNh`CDgsNACQSrSmAKcFsn2-i*^u{H;pa z=E{>DY}~P8fDcyyErieyu&?qXF@Ik{{VS7`;Ac_ulds1SkDlQlJWK!IDwxu$$r@M~ z8~!f5sxh;DmK*=5>hgSU|2KsM_Wz`i`d5M|0dpruIb#PwTWdR8o6l9_vC#_JTG=`% z+UXk_Yto7f3jSu>GWry0|Kl#&w0~2f6f-tAHFLsapl4#El`^(5buz=FXJ?~Tl-75& z#AE)G3+z8=zy6>m`*ULdSO=}DxzXoa7})-b@4o1v2Lu2B=*_;DwT9x&{@nfl(dL%~ z*nJ5A`1fD6ztUL!m)8HJFmo|CG!}KxcmFr7&PM;=H?#k5yY^*2DQ<0pDE~J3|7`pD z<@D!&vSOBhkCKXko#kIBsV1~!ZM9lpx~7VzYpAQCgvH}QKmgMtG8Dh2VVG4xyT&!z zHEuXT-|eB!XOUW*qjRsIXG3Cj?H~$==l5rkNi(g+e~`&#`%Lc|iWTE@;`nf*38sdU zWg|qJMJ@&6B!KRcnl3bbidMV_JRkf#>#+#H0ib(a;|+uL>E8af5ccIeefWpZbMa_j z6Kx19ZpHJ>6>u>ceaUuuSQR0!@@-gn(oV*}#UJFXcwDj{n+cH)n>J9%zmpBD!= zUtc%Jqj-Ghk0-tGv%^=(4T}(2-fo5{;9e_U*H38iE1OUB2>~Nt-eMNj80B91o)@eQ}J2a+Q z444`pF+61(kTtBqd)5Jge%XmYYHr>-+CU$OQY<6!RdGj;!3NlzdLAB5fow-9mvpmq zTIuej>8074^{`^1f)}~ohYZ=D@11gU!^j5=Z@Aqz@F0{91@PzH?oT4+1vJQ@3&G%g zyAL`RxJxnPA}ACPvU%$EHos#*Q;Fp(LbJB9R22Figa(ud>ve}8C~!BU`VLnfq*lxl zG|M!wZ+L;kO=3K4Q6D8mA+#qg-)(`4z^*&IjepqK(+U?3G@4EM^((kwAs5e0p2!W! zz-oBJ0|ZL!d3c4u=CeFS4j3@Y7YqaoA%d%YHHZdA*bsh13n0XDrms1$QPVKNMDsI2 z+q-5?0vTEYXZZoi$qL~*t+7`2%#14t0MQ{i=07n;eqeCG=y)QUE8)3e4+oca7h2)L zz~#l}LFL19kIaD2PO2%kuyTUVg2-vupupq@+?vq&;9+AUpY+Q5J2}8FY)g@lxInyc z7-eDs;_oM;_RMIElC8GJ!;|)p9j`Mb*tbWD2e+ejrQ@U(>v0=X!m}%EGzweZR6jbDBpZNX#EkoIBN;?ukq zRNWYO*MX%iYq|eXunfV$ZY$k1bv?d3!S+xtR0>ob5qI*sYG;!~&O+HhSW~dvdnDx1 zXyU;!o@)-7(LG1G!q$voVG@6-juS=ON58Busgm2cv-RXyTAOMxaBy6XlPz!Ab`9lg z18f7vhSKr)%ywId;WGj!|hN3l1Lgg2Hqs)kB&^&Xn%fA?=-UGh|C>u%Xc#P~Oh# zF*acU8WfFz02ri93Yuf(fB>Z&AY={SPDZ^~?tAXZU$mEx!%x6F)0uoY2 z>6D)d=M*IPe@y@(H!(mXoATlqNkV}Vj^KplQ9tpsfMPdm|JbM}%48s?V8;jt9UIYC z9FIpJ#Qjl&FX!UjMblHTMIv_mXT~} zjqx~XvYt02@%rWNYBJmMYI6E5m*;48?w~)$RORPvz936~>V^y>u8zjIved|-g$7ej z(sCvt2>=NO@(w~xB4XSKad&fa`ANDh~SF6gjZo!NENid26TjGJ1hyP z@hZ(QB*2ahxGa}`9g8R{Y3g8RO>CJOv}X>vC-~Fb0S(MPve9vz`-b%Z1q|(zI4_U+ zsJO2j%%-jhu<^BW@bdB}XIdLZX%lw0kp@_8&}BJ5C2K)f3Ltz53e=03jvnuqb_NCr zERpzzK5uP5sA_8W-o!?$fVFHd>hRRHr)>laRhL7}rH4ML@5%iD42)03%~< zNTj~#W82rb(2dZ95Njrx=MV*C(5Y|29M@{2dQ56J0#;fEJ(1`UkAqjJ^tDTBLEQ2a zpgO5K5`LROlH$4j$w{d2tDKS>QjAHy?f4we6d@X&p9t>-XpG?M=WVcPtAi-l4J?A} zIeqldaV1uCnqPt&R=q~#5RE-P4r^h{1l+l^^&%+MvemrBjETUmPnvTfHj7~U-z+7) zzi?cFy#gd+$$Nxn(*zoKqXxr(rsCdJW5Z@=e&8P zMaJe_P}Xsw@g8~dlWo4N7GAR6a(?8m-_0k@oH%UG9mw?TfsF-L#*tmbWZxz~aw=RV z?sDSdcI-PQdGMBUU5WM3t-3b098&P7U}S)fwH&z=2d(w2yLTCEpWd(qhM8H4V}b{S z)mdqdLB;K8NO(YWu3**pLywa_q+AQll2S3=8OP0q$s7r<+$FcUv#~|2n#M0bT~{XR zTpsRRLfntkGu`H70qL z)LJov;x4*A9#3Ee(C!xCiqfDS%!_H}#SsmwqV&4!d>G1;^Kj*YVsG2C->BurDWFu{ zl|N>W7WF)sP)4mrh<-p$qs0IG059Gr5^i5uRB4-5Nc09w0#wRa&Ja+o8tE^p(Y2q> z%c0e3&^vbTq{OtU(Jy#;Z>z7U%t+_YHzrsx@qGow>CUH-yC|tHH?FBUcqUj(e6lUU zC$S~kI*Q<)(!DovxxY>yHH13sZ#|hpf+6iR>MeNoJ{01NDvD<-UBT3I0=CQNx@f0A zADVZP6MnSD!UmxxIdPm##zw_BYqA79&Gv3^{Tz**elpejW-88}bH=p>=Iqiw1g)wL z&vBcH5lN4qm+5~^ES&14;+ETO1#JOzlJf>l!Sp2(N@|4`wPK0I7ye4F@ScFtC zgUY`J=K#e$cgYZB!s>?>HOL6vmTu0-LZueg`70$dhNMVV@U|7rZPK?%Br^r*9mgL% znLPJcX$^&2Yh&%*u0v}BK5eFvU*5HP`WMdjE;?O0bsLbQ!l~XdAbq)H|-cmrBwa> zv%ntMA7qiZ`x9st zfpBa?CX)x>f~URQdlJCdqdR`n%bk2eh>z{#gszv;kgo~$JNWu3T+81EG%SDDhRyOP z9{8{5W5(a(KB<)d_XpGeea!J+LueKTywAt)sr^j|P5;SI{mE1PiH$Zj{wp8#AMf}l zX!pO2;{JEU&@6ufuK)YN-T$F6^dI*4x2*qvObq=m5dY82k0PzIg7}}`O@2csb6cC= z$7E(sPIitQw6y;v_??|upP7+~nVQ{@S^rbjl8u4dfSsL%+Qg8B&X|pn&X|S%f1+y1 z%*6bgt(uvQ4v(4nH*xj91%7AwE2#f(QcM3#C$Ta!{53l?p{8j`%!=T1rJHlqJwLCE z3IQl0 zx##4e?xP#Z@JUj=!vv!~j8|u$t3m-+R>=F_@Vb|FcXsnaz-JXYoa5@5isS{yWUj~D zhA#2`F?KW$?)%#A^-6VeH2j?1tK4@GW|iFqNS6&eY@BHwa!G?jCk#edIyg2N3c$Ccz z>k^?axbbsn@#0%;<4MxhV|>-G^CqtKeL-qY+{zKwaZw)1+_qC5&r<2ZTkppY1=vL{ z5Zy;ja?q-;0pMp-cjo<~TiF?doyZSFay*Qr; zRT-5QY?tmK3e5G1`|f}>cvm~EV4XAP;}(dgkjFh`k!}U?!sew^Sl(YGlS;G>F3viM zyz(EcORwD-gh#zw+R;6bymo`%t&|I^GV=i3J!}O64C)B;)Ny1j zfZEe)243H#3ZYWZC>>d2`Yl5mY6Ps6HrAE%5X%G8A&>jV9f8`q5b~IZ!`XMaG`mKn zD*aL|Gf0I6cN(fI;Q~QcbTm8s@yrqVEenLYon;l2hBp>z8mtd6Dt6{zlnp_s@~kEk zt6~`yTW?(@CnJNJR@&clW*(MOg%0w9wU)BZ%xmr?G4C323bj+vJYyDDxG9?lD;e-2 zM_0-_$%7vglt7VI&z8w9*F*+2dg4dht(E*8+^5iN*PWX14bYck<_e3@0V(Xylj-+6 zy=1(rtzmiJ868_cF3y91S}x`t0%jrD4=@UcpUoV;<(M>35Ifn(Ce{BMRHm><^?ez< zhiQHi0b_>cVTaVaG|f&5f+)WO2UI9nw4mrdjA2ida$raMNVi_QygBI~on(c}L9szt?zzm0Q*+>io6Fgv2{ti>sfIu=cQ%W9 zk-?$PqJuPyl$TV@m>F|~Z0?t-1X$P!M2mMzRc)7aMybYlwAc*#oqa}4d3VbePW+2J zkn~$i#pP*nS!^=jn_}+>-WDIykz;yvE4+)oP3|KW6ZKcQ7$D! zk5>6qRbRX&h1lYEJkbTw%Z4xG^@cc(H9U_n6FT6?27(a?k`F9t%r4!jDpJ#9*aQlJD(u8;))N?=iwgMhRayN; z=%+q7jJEN5y-uul+U{E2_Ngu?reO5-P!W%yEjloFRkD9<9W#BG&G)S)PZjxju=Nv@ zCYYwg{X=D(){||d`L*>8?BvF05TT-t7oD_t`IT2@sC_m1m)MK-jAd;r6J&k3 z#_U+^N)oWA?#A{J_IZb05GgVE&;0!}yaQiMGxB$C(?##>0ScyhRePCZq^a^?s)~|BB${x45_FvIqE`3_x$oBf#FB7lr*JmmiIIv&c+q=#j zA(~#=ldJYRJvw-uQi8=?Lz!%}UaPhOV(;mB?jCtu6CkbDc?Z2t)YdIGBeNK)84eSD zSWhN650CG(p1tu`*1JD|%k3mY{@%U*YkQcWt@9rx8cB1bPnnfJz1GjV%OBn=9>edE z3V3)7e^y-Z82@bd!}~)4{PR51pFTO>AG}Gw>&3aN*}-bA%)BxKV2+$AzMQwb0;ffyiZ|r<3H#4{}}x{sQAki{u(U(=l%{W+h^eM zr|(0LN6+}l$n;n5XTbwnO=)5E!?waZ1-+87?+aM~T_1#5IPjMwAz|(z$y4zOO}!mr z`93_jt3s2K(9j$ei-Q7=jqXuyM=D{->p&HiU>EjP`nlRFOk-y%>16ILbxQ!#7>~}| zx2&TNF5JAc+Q;*Ttw-&vgU3!wK7c?&VvzVK^eeHnt-eKom@} zzY9i`$)*Pn{yJd1DS%|UGAEbo+_E_r;8ae)o7MA^TZtTD5I+?=Air8ixPqIA@~kAT&L1;ocM46V>AJry4u{{4Mb(e z5%`usv!{>}#*=yM#zPtS7J-ZeuI~m4?jo{*Ls9(hH%|r_BMoXHAZP*ll{6S^JDboz z0Zw`@lM*MWyge2hngFkv{UQJWgHYzrgxQj@EaW1^r2P6#`Ox_I+XTVWwEg-Tn?I&`h<_qd8?cb_`b#q+y8jP!|(l9nZP_0#|yJmjo<$OKkCD^0Ut#jj< zEigL*oc3?zaYuB~Bc`Z9!_5WAqer)-hxud}eA#1ezJ|j9NS-&Rn<3Rhwt_&Z(??+C zqa~*s(bglG>cLwgl;QzSsUiQ~jHX?!-4q+GDT_~1tJ*1Hl# zIa(A#ydFz99imD^cSo{6PqhJExEu)OU;{66^puGKPLV0TNiKkQe2fm1N00PfJ*qt> z#D(w!daWV?m4}(9K5k2aE^Zp+s?LkqB{l2gHlhA{)*K?iidedX<%f>;irDBm_7-z` zl%!-n9D>Z4M&7 zEKtlRf=&#WLHDwf;q=w=zdngeHh$GT*93Sg^;mydyi?G_Zf&m~gL~{YW0>MjV1BF{ zgqJ>S8>%i0WL_v=>BFG4+|3;Udg%Yh!_|$-Gm$w-4G~rHu&t=JFqQeLZg4EszsAVF zEsz=ZtgGwO6S(!VVCk5fGT@4IeLCV45OKIZea$C@tX!6H0AlJj|N&CiocS(aX@M66B5WAo=U=Cu(2X{oI`|Yqy*cn^k<|C(r4i zE5R3dLP8M{sgI9W^;_^PTmm1ujiT&FGGSJhCE;N~_m?o&$lBI4Nm8kd*z%Z7m9yzy ze5jPf^65>emXXAAh>nUrBz*nlW-ZUmhFJ~v-0WG7agWD4AYrNPw`Q%E@lmc2<(^;b z0%hMITUdrZ~nqik$t~z5G81lB)mkh_0m&*j-*<6^95l-fT@BD}KXNg$DxR*EKlv_{QN4~Xb!B(OE>wItr5vA+P|L@v0d73BtpQRr zFe{;ml}Kc~zwj*Ie5i6U{C7FRi9Q8$S_?CVhX!6&3}y#ti{(#x6BG&jcG|;7Si^F+ zFC_|4rEYpB;efHBox6~M--qZ+2z`59LSI`($WW5!`^otq!6z} zke?tihgmoK4A59&vZ}QS^*Y$Vm3Kwfd$P)Um7bwWg(wSWv8Tg=is2^vNT832wfJRs ztc9RdW5y01Y0sag3=TgkcyG`Y-dU%@9tooEZ$gg0{x8Pf0w}I#=^w@=xVr==_yUVV za0u@19^BpCJy?+7?(Xiv-Q6X)!?$@}`QKZ0->Q$T;_RHA)6>)4d-}}Iue-yKi>HJY zNxz05e})^;Fu!hreS zS*lZZ_q4v<5jt4gCG@c}=vwxdhno8Ee$rf4zdi;cw;^djv@vSNRNrhi(705f7*=9f z^h@!VU&OKb+MZ%FZa-#4f5Wscu?EYQO`C zB_WOdmN6H-$BJ66V4E8|`p^wVl*AlLR$Emdo>)$k_6grx#5jqHCA?DOdKWT01Lb5m zBpd;Kk=`QLh@V<60lx3YkJ9549E^FalYtcrNAXT+DrSn*;ti2H?s7?KL6O8Hi>P4< z6f#MT_~{^1hDQtMnO#_miru>Eo} zJYw>9v!`+qFf;oozkQRh(q6R~+vjbh(>JCD)iLAzP1VwF7x6fXc(=w-wjj`DabS;1 zF~y1hO)nUX9P`8uZRXwS+m{-XCG+ByU@w{7M!++Nhwo_l zC~+OHlSn(p>@x91r`lSfP>YK0-M$zfMNhC9i70yH^64(%O2<#skJGapY0q*T4mfW5 zy2=)7>AXz^I;}rDTS94;6Dt!)z}V}44jlP?0((+3b@_gE#dYU28;rsfkb|9LmhT-G zf1W4ppsqa=J&F)c8*^j_zeww#D^I#g$W8G-$Ik;>^?zAK>-X=^Ij5 zFYe}wN9aJoWpg9lXspS~5%#UZnTkh;)S;_zm6{O#`T-4}uYp{Gpo0WVir;e9#`;K5 z6*+Kv84#t-kg3j9bzQ?v_S3yc@=Z|Z+eb@C;aZoa;qn2Iiml$;@Eyt>$#-J7Lbr^d z&3qV&9ext;Um&5>M|V~tN0!m;68+M_6SQmIgdK6cgh)Gesh(Dj15heoCcGUX?oWVu zsO4t=BtvhJah<1QiTlf^sJ)Q z9$9wEYy0!@zLP6b&HdMeVh3zvIgPLROW$cQo2ITGWo6ytME-Y_w{Ymj5xC2{)SDlJ?S`;0&&-Y`g*av;5@_S%7 zO9BGbk{v;1nGgYy7e*@k*GtfU2B}P)4mNw*1Y6#+$oUoS*INnH z9h2x5nWWy-$64LfgAVtjNKmM+vexjq@oPzm+#p|vvHKm>NP}>@he3nKQy;>~q;a(w z=d$#73OS4A{Lh|~7rstXL^tqF5QYKyUqk9JGCm_mMlwHBdi&Mn%&R-~Pqas+Zn@uI zvQ-sGax$ztSa;2t5R{?2XY@1MumEp`{B51<`gQ984e+YZ*!zp->Q11awsM60s9{;c#0 zm(VtdzQ|?UxPL$1U9IF-W)Q2&)T^~wZ}}pR>DJM!GGXDmw!O=`WMB{7bcMHF-Asm? zEd-^+f!$8}MuM*Z>!G)yWd+B>zSKiA6r4&g?Azi4fy2~%ao2Ie3#d%x6{OUaAjLTJ- zr3r>ur^nTnQ7rM5hr-2MFlMB19NcadDL!t8T97;aNn@FlldSHyFI6!~d4imDF#%B$ z0^O*;l?xT(38h5=VQI#2*pqy{`9Cx@C4+>&Kbbnq@X?65`=VigLpp*W7(A52F$`$NGuC$h9dZUBk8ZIg=1U_ zPh3tVZ9iOYxxhVtgOK4rX-U>@{r01zjBnlt$CBDVVhT3@N(uQJkd#Bu&Bpny==_Iu)4s+^vD_>coB2fi0^R!B6Wj+U8&Ti zx=8^!nk_G&b}IQAQK2$_A}VQ7oZXO@Qek7#=dQWi((Xe$&D)u4ZqEXT4YJ=^MMy*D zb_|5?;#fT%lxecwGIQ)(T9o zIi)A784^=jRgx*i1!{9#gIzES%%cDq#l>id6KuO+39^abhcQAW9(0UTJPNl1 zcMmJQZff$|bBKL;K7u@6xxV0KEMg?O?x>&(rrohSsnZy9<=i!0Bt~T$TnUhnCH;|opCKDuPibQN zTM5kLc-rSSo=08zcus;HDWn;ML)>-p1cuHV(y-{)Q2|u zYA%OnUOTpH?8^yod8mFIw6#9XCX+_qKVGoW3ZrPH z>s+T6mmGU=aH00Z1FKzC8TU=WvTH7MY-T!^c;9$%&OScUc5R6H%uCeg!L4}EwM}>e zu;)Pn1}e=EU-d68&N_-8DP@%;?6`;hs99f!jT7ayJ-dg6|ExDAi9Nq4^({lTU*Z$R z?JH#FpT(f0IjF{SSwLv37LahcMp)77ba=N}ZR`|E2RhC{2T|A&tD;=WhyEBD#p$#`b#|dE$F_g^P7jV z;EBZ^NQ3Q>L6JEJ2D!8HDhIY;iz8CZ52h1AG+hwhc*6D&mplEl-w}YMW@+>zf3;Xw zMOWF^JJp7&hw0*T4*?1XvDaPxAHj8hS7^9j0Wz-DU%Bnog#2dZBuxx!3&Kqk&25nc zB!PB-5+>G8lLv^`me^T6}c?rmGX5U^Uj19WrEtZP&lLf`mQ0-ctxHB3B)ND}IM49J0<#^HvE<=uVL&O={EGhzi>Sx>{38ovjQ z(_Rx!5^wU=u#ZW}N+1lxY^XH^*FswXn!$Xe~=D8&2zV1?|QB=Az=a&{6cE8e>6G`FMMwIZ2=Z0X|Rzr z!2qMFv;(DVWQTsl?HqQbIZ?7~bd_S^+oveptsi94=QE$|=)qekn#>L=dLbI*#5lvn z6MBxzG>vilHFG^CxtU6Ej(??OKc7k^%%J-Ubrco_`7r*pm0W8%+|TS45M&06>pEoH zb2fwlXC(iM=8kB7L$VEevij-C{yFRkWqC39nvpVD!~~5xd^AG;4~wKQZpu(J45@ZIP*s|S*5aM|q01Zm3My9e!70EA z!cfug!SSL^FiDGg4F5W&>nt^EcVShMCyBsGeEQMTT#r?lK{1j z%(Z~p?1%tkX>8eQCuxz&A@sK3%Fyf(hMetvyXfS!l9gT`_*G8+*T^|pn*G}~ut=}| zs|OY{p`T7v8u#J&%2hC#1tinHjY)2dQ=A4ETE6I{jQbltxHj6gbzukCJvAL-mkF%#Pq*pbvmJ&@T)P7f7iUBD1uh zNWoj{O!r_V)7!LT-k%Hmqb1K{qyJZ@ZcU>{BTeW47S{T5R>L7ITg1?i{swIiGUYdt zI9l95_d-&bgPk6a6h1I*3aY1>KNoM6I8AOa*e1-PY3>u>n`(m^LivyUyZD}nKX0C8 z3b=|r`MZnb5WmVxD+k(c+HB@`a&B^0z9!$X!&1v;t1-VeR6H-TUnE^N-F=#Z4|xNbduRCOSl`f*JSGH1Pu~*U7I$I9r7gKmBpm93&falPO1{h#OhN8!QzI ziBhe(L6o=Y{BivW$A(aYCWI|Dr=jKno#dO?zuQxjEH(oKRTIGdzp$!GH zz2P6I#od;rzeV$m$i-$F&K-JY1o?*N8HjOUwlru@Nc+WCxb(nBU6_BG*3>l$b2;N9 zeDh)ZeVID-R4{r0x9Qs8p=RvoUE8XoH86-Rr9OyCndqirGRADw>_`>hK6==)n za%G$Bs=|4wT5R^M3D2Uuu~)=OU`SxUM72wWuZiE?=`7np?$gl6v)xh%b*k?X%G7Qx zp6R$#sJK|eDbiv8N!7{pdrv-jtn?8D>cnF~Nx3Zk^rJ1b(Nig3-^i(jLb^z$M7iek z{KY!#cUUAu2V?2Z)3U0d^?6Dr5`fh-)`p7eIsgrGc22T)5~MUy*QB;x4D__99Xz<6 zXeb9QtBgPW6LZ|#He*Es3hl(W1CCAIP?OdN9BExA*u^SW9N$%b%yyp!NotILhea*a z*I2x>Txk-INk01S!_%tKHU+|32jkS~#t<+8Ca%ShGzFd#Etj@cW(|2CPaE zZ>XkqCFH+ZZjR{eg;LA1B!RwAxrX#J5)?c4dZYajltV#rhw zoS%Bu!i4q{hY^w-ddP-r(i-Djd~d=CR=BfsZ)e4cgB*;vtKf0{G{adnA|`$68Uy>E z%_l^sv0nyO)*4lDVrvreZL0De=ySzTT-voC)2L(Dl_?Wc3-cZObjhG~AR`yGnS*a( z(njA2O#(GLDOCJ;k*M?4{4r*I=arb5)#%6#6Mr?NgkzqeOY^NF*ul)|P9ng|Txu&> zM|OzjZVdc*;r3?_ng(7P$EJ1?ttm&W{3d`u_wB~*iZuL`Z%Q1`pcYlwm=p@(^;)s4 zD>32%4pd?*-ZuKjz^&kcRaC$6c#op;j{V#YSPVJMCPUN4L{jKT;-1E}P>c2knE-Xy z7m~!lYb8baO`tF~EazVLYildsUL(Q@(cUiWUJB*OcRU6qoOpjw;lomZargv`+*Ik>aqlv9Oa`&}Z2tZ|6VnV<%)_N*{&X9WG<@Le$F>YzpJOLY6 zg!(!PM86|%6H_|&&2$Z223&k^(CY;4Lz^U}am2|9u@Rj^`<*QL6k`8Wfx9AxgA2+b zN>HbH8umb}hlMAD+Vqepx9Q~j3@QmH+C0J%~>gw2(JJ02PA63K!gZ~Uz~01LW;TN={FQMFQq1< z-*rug{5qY9R34I(un|?1iuNp$*3-m~cC75GzI(I!tty1k@`$dH2HWTO<1&>>V^*;! zJ>U(RO^i#f?_%iQR0EWRqD>n~&nH{09lb=8W`l6C=2?Hfj_Y>PMroi3+rkb^w|~pI zDMN>{@`&o&iP%n#!OgsEmVvi64z+py`t+ERYsz84AJ=fYBw#gf+H5U)oNfmZ-(?vv%&0n ztLL+pwAPp7%J02C7`ofm=o1mkQ+1AHfh^Tx7+=+kwnK{`I(I!+@Bk89Uqe*LQcby$ zTz-j9kEG~+cDD8AESGILd~b@K@tB;_bNz(&d+4h^WDukw(0J`EL~ONXy!pg=JauhL zpjA>*W@|`M_8J4;T}P);Q0LX7j=B0NbyDd8A|IvSDo8(FYsW1w@ecBqw;O_6ZW47| zCwA{NAVBL_{|*UTDieDLQyjQZBHmQo%d6JW30{4Wo)QdhV%#? zZfL*?swtBL26ccAKhtz*kq%#wm*BG-FRlKr@piSdJ{JZY)ORXV z*J3-TxuFl8VDbz`3-=$gw`W*0O*R#%t^AD<9rm%$ta!bX*ks*jQ(cAG3Eyx_@ve{Z zPA0EE-=AZ$Bp{}MGg#SFFc#~mTBA-NZQAm^`T(%Ri0Q_0?&FUQ_ZU!Y)*khHGIGw; z?0Y?VZBHWDZ7QlXbLQz3qCXVg=LQVyom;?xb&~lY(|z@wEXOV7>GXVfsYs&$^BHS9b*SW+Cq6k_&g3)$4P3dNI&b0 zXa_rdZ6txuPzsI3f7V*K8@u8!vA10 z1s#q4#*%UYKtMoNHYQ;MyZ??6feBS`f6?&d$oj`mfZOL4mv=3d*+Pk|Ht&c1-_s z5tE1-i0Oalkn|t1gHY8<&W28Zfy$r@|MvKcylOF%|0c2-g#GczMQh%7r7CnJ!RRR@$18zeb)5Fh`@njIuVE;bO*6*OyR z5X6QZ!1@m%c92j&5v-s#7b6EJ`#%EwJLmuH2bw7e*71*ofE++l0El}I4pMezkdd>3 znjpdbJtaxT-Q^9S2O0#$Ld2T#0^cQelqBctL9=ao|J>$4keiv&Y$eR;dHY2N& z(WH*5yhY;$0TNe^Ys9fMhrHa&^4yaL%tWxU1Piz7t-U4bH{Gsh6dw3&kanm}X6+>ne zO%k~ZWDt0H3Q;vs(K|#5us?alt{-WzCC*p{*Re;G*USdCf9Q39e%*?_J|M&;xu80; zSxyK3;bq`i5pD4Da?+W*=L7dBGy~^0N{%F~3hdn4Q!6wGuhtb5oJdx9eIFI!Lr)^;F`_EJOSNPli zZDbt4f3-2bs2(IgW<4=PXkEj{BU<@_a9{J-ILteHqF!OCiINE3ehGhZZ`71 z57Bo`j4&sEl*ysl&AN3+bi$oJg!FfMAr)#clm0VL{|brwzj*@udqx8t`LXYP%&6_B zboZ%*0ak}ok*JtO;6%?k-}%4(Scu8dh1cMJyo^*%6hdiZZeu+gzt+{kd_sIBhc093 zI~t+X?oFrf^-H8)aM^1A%~QHQK?T?-i`@7TRhP@c{2A<#TGnU8BCxLx0g@QcR}ML` z2p+jfmjrLoGHR2P+{8RJY0J*I-Ix99_c&bpsO;!xlkBG1ibdb3Dh4tqtfnp-E4yY9 zBNn{$xbVVw(n__FxV5hJN?b8dj_~jc$pAO5ro++oB2kqDzOyBE%6#ozHH7_UYA-LE z5Ow7OAFvN|8>Ig%tbc>~{qKVS7ZBvi{>A72^m z@WPy5ez^JRcu<>iHgU$F0dc`7g}$3$Q`^Vz#S}WBJO{NhWGf;1E8=%>cwJQY9>q}^ zgfMMosEGC?vYoHih&Xf-^Nn6;#fqz%!R@*hH6mr$lsqqY<2ImVD2a&`#1IV*@#vws^ z#09g3^b=%YU`@9|+7kvNgaCWf>=d~4$MS>;1zSP@d+cj7le2WlM&^b4`UA4Ns&n(U zoA6r8K>$n}%5ST@@N)8K-fU|K?A8>_DvhIlh=k!HHie38hw;o==?v#wx({!4ujNYmv1fA%=Ss z17Q5rOeSwB*me)W`l&RF$KedxFOy@-o9$oi!h}&9!@>I?1(G^rFJZx(u7N;B^IdHg zo`ki`EJAADZhaQ8TNr4XrO$|qy>P|;8C#~QP)a#yroDlGP_4#{rSU24_~yPsi1nBk zhf=Wh=qxWtAAVeOU6Z&yuJ3+t#>dykyPxoe*>%#6tlEX1Nl}h3+53F`spV_vboPvI zb-Wdhr(ClPC+Vx`W28ExERHYLuX>q@l*5s(IDuq=h9r$q`dJ1o2CWKk%Z7%P=lVMo zVD>rj>g5^u3+_wbz1&&$-tS@0)nA+;+#%c-PQ2SwM6F78F^>EvUg9lcX=MQ(fzLUh zmnV+n`mx90U1i(&TbySX&o17%#>rEnYuV&^#^LJe>ZvEg3pf}&KBssZG?=Eo*#-Xg z7xk<*sx3cQ$3;w-uQC_uI@98Q?^ATH3_?}DqwjF32z3Tj(xF#VP<1(2HvY@Z2&R1$ zso;*kuuRkUNtL@FatKF1!!`AFFk@VV9GhB0o7<7s_p+se*Xg&qtD%mPx(<;1)UPafHJ@z58+}aIY{r&)F+18HbV_c z<=W_(A_){ckM%j>$OWoax{o}S~XVOpL`-d^~);{v?TT!=dMOM^{b_W4tLha zIqgPY@GmHb{85X%)X!bbw~8ZIjqH}_+|9iJo>>mrSdFaS%dJmy>c>|OnPp5=o$lOy zaK`TQvtYzR`~AX@2vwg5)sUz<%DKDm_2=n>=*9RckK^L2`(b5qb~pFe$xM`5WVa;e zudJtj!9PtaH@gYnOc(q!9B+2^m&?g#ouMljTI{Qae>*$IEC3h4s}7z!esgazpZcvj z+*P!^s8%Bp_@+Fyyx#w^|4Ok8ZK0PYBz6mreq3RlR~Y z-(juxcVG07iIBU$-JH-a!Iy3Oq&||o{0`EnhKbqw8LN`N=otiG9U0kUf%=b2E`wQR1ML&&5w9qkHRY`)(e@BL>#R12kuhx zppRr5+9w$4kGDG1sx-uA=>CV;En3|U1#B& zGj9F+mYrdT?=e@R`l{jY^(lSArOdO(Hx1x<;RJT92d&i69(425y3Oi5p>uIe^+-v) zbD;TOyGhK&!{{_kcks^F!!IqIa5O#R$+n>S^D?Ws z^?UOPa?B@mknY{jZOZjeUZ5V4@x+_|+w>b-=jL(c(=or7PrE?%1DCJuU`fPW=7^90r~ThF-%|k#$tf_E&@K1Z}|DY-`SH zf5c@!oztuRJ6vtOPX11xt7rDprV1Pq-*FOkjtvq!{tzk4H-9xfA$U}mTqtXrb84q6 z!6bd8Z&x~dot|(0?#}ODEi(m}dA3o;OYdMk40=SmcrfDBK_!%>b7=Qb#wE6I#m2RJ z5mM~lDa%{g4$x^q0YCDr2N{F5roO_P>DN7&fC52yWnj*dU#^y;3}&3HF@EMze&iAK zx5>gQY5bvuC&-D5lr}l1>|;~54QsXUHllQ^1fBTT`)@`CeW)YdX^?GkR#En8hRSoxw>neG0R2? zk+HG1&cqoZURqkg4`*u>%1_oa9y`#pq)TOwhZ7@14HwZQ(9&XosECJaOc$qEq+E@m ziiT@6^Lxx=82BH?JX89&mpA!ffW6tR}M3)}9qiBel**+J&oQlWVAA|4j+l)%tJ5@=#Kfh9dn@Z>FUisUIiq3E8BepjZ>J>B zWYd~URsfq3;PKn_<)|lVnc;Cg>#8tk_ShxnGa@fiCK}sOk#LuPx;XVU-X}l*w3ZdIR1{jov94M*TR39!rZxlG zolZIaF2aNqJ0(T(nv+xRdxzNJ>n74bysa!A-S+xZVUr)-`IiJdteOuzcVTaK)`yLZ zQl%KZVkeZ321cc1g|-F;@~!{ck%Axl z)f$Gj?`z*bdtWU*TXDfP;ar5eu>mxwX*V45iw1b&o9HhrTD&~J5Pmro`0n-gEfZ^< zjZd3TDYokS49;dHY{tc&6q>5jkXrDsKi^XD%cEq0FEGxUPP4aZf;uz{qCShs97pA; zo3)B82r*T)MREvgC*|tS&~$x0qclZIM3u7p?-!P|Q#hN%^ruzSWXlEF@>N6PP-S;+ zN;c7@56R+Xee*K3L`tmUsbfXreU46YZcF=jdwr!@T%8;3l&%>Uc$LE6H7^+XH2DGq zxYRoU>|{JpvUI$S?_lO>buTbb2)>m)V5z(TuJ=e)ix&2GqtC~`JxEnJbx;b^1Mh-A z^YLp86^?8_<0ZD_1Y>pFS{a0qB#u3w8b1a-E9~~=4Fcy-Mvy30yGLqrPkcXPR5Fbx zOb3(cFeU`v<;Te`XvF6ti1y%TVg-llRMnB`d`WOFk(eH^V!)XA+CCY`sDcTMv{!Yepl8T>2gD8V+5?lK&VkX+N76`I~18JFCw&~oQi3sCN zOeDEfm7gil+6RGm+j!d}+dp!MtI7@?ch6W_ej0_0+^lKJJjxz_GEKf){LJ>fcOSy6 zP#1%?J)y;;LZee#`c>*ihVOSzvV+^)WAaZoPH|KxMW;k$?Vw%ZIU%K&7XDDn^j<+q z^~CwZ7)ID_w_HyNf^kT4z%KCfAxy{b{e_k@RVP}aeS1QWSFI; z+=-G6fOKUYb-a0QqvT|)ecVF)Xm`HtPDt1|qMHWR2YStVxTfj=DRNc5>)|h80p3Tl zrH6yB9d5QRLcP}LG4b*NqzpxtN5IkIFs)kQ54Mo$y=ikm8n32844bqtn{;@?ZHZ!S zCFtKThILWQcj#VL;YJzrKq0uVp6v}yXEnT*&Rj%5Q|HTjW+(wVRF}xkvS$hDao(()*=L`jv|qzQF;*Isi#y7YmX*l+TZ)-QC) zvg{vi0#vXi2T0S^8NPjx?5=M5!xake^X<3}p+}W&DOdB&L)5sJ(ORs}v3hH6$Ro|p zyVd5s>F}3@e7G?Lmovd)FQ1GcF19zZQq}!i6^6R#qFkiG3~|;aH`o_*NV8y9k2F?9 zX$Kg7?q@rMn7PYrbc`E<^`q}HuYa!h4<1XWf%7xZ(*bvnZ`UlWePq`TD*X~g#iPPd zYEi1H5QAU*DMV0Z_(eSWi`SEhQP7kry`0{+k3Ki33<;*4?Ifw_J|{C2la+#D$GrhS zvIzlcM1UJwCy>@LS382ICC7f0>dCRIUl0F^{4v2ES1UX@%&n`2SuDixBc#3d%W% z$?)4l`2uGL+9_@$kg?(8DzdZhA(a>?n$!1Fp4x}k*zsvJf~Vjk0C5S!23&R#oqxfR zDG$8))F|^(`!E3PG5A?R8BD2{H5LY-29@ZG2D0>}6OMoQ;bMiuP45*IYKkQs%ko!v z#fRtw(kgsWvufpvGVIaV#Y8?N?B#chI5Fmzha1$19KjcYLkp0f@b80sL|1k;WE*MG zRfvHU);$wm*e=m&1G^F_OvF`(LB9>>85wj?zzL@r#aYr#O>fXcyrQUU{qH%Q7wC@oc<%k?VYDr1hiHGH0a%THdVMYcj$PvM&U z5{z8!hXXU9<6b8>N^{s|2B~5mrx@-~xYPj+Ut0eup#kevetv`+JuUrAd1DuX;+C=$ zJ)%XqAnYTKnW=5~7G-j`M2?@G>{PW-zRjmX&a*i(IAN8(vxDgWfu13644gZpxzU|o?MFL z9I?)s{RI2dbh~Mo*83iW`1B_P=3ZJ`aD9_r`{B^=D}KxCrv1|=HUYh#nF43y#457)+u#rn4O-q{ z#?WN+a%L}TLUaZ;5L6#&J7n?Qb6=2AMHpPY?vGS;00Pwj0>!|N^b!U47z9OSGe&o2 z+3N21Nv8n>tBD|~FsPd0z*$cBx@iL)u1PIskZ!mbQ%sszvRi9m4xnvj7(#4CK>}4-mxYl8y znHhECahkX=+}%mXH%{C)gn2s%Ws80rHb9j7TjxMRM$VO%0#_oQe1>>4hS|UFBA&D5 z`4q&50q{#`NPZf9*DL8Kx(+!aWf*KH#=dAX`%O|kvBdr~gcLaPe*2WrmhKxm z$LV`~=Ip8H#(@1$O7Sd9e*E<3uFIGcCwu&-S-KrzJ8A%nJ;}8_S*ur_Zet!F{e2b^ zqm%vHt@|f*#%bS6G6YR}@RbN++NqOUvmuL7@I(Dt*86kPX)VGFsp20x*60@q+M(;( zP$E@BMFTL?YL*0(E}G}jwnUx}b-TWR8Dj+mjT-amtaB;s3hb5aFUGA!`0C}=l!MNDH- z>Jg0@QCzfP-t>8g*&D_)^#SNw#0#OW`1b6bB{@JmiwU_IUso{8Y?h$lGK^JUmj)$A8sNl zf_pS;$mqKCa}q2CdzWk`CA~L36K%Aw$R16y<8HJqo9Khp@Oe9JSk!oRWZ z_bBM@H2MIEV2j7mCQ5Hph?sN?z60_i)a2{o?x%~XRA~_fbX>CFIX4H2IV;{G9jP)wEViYcNsFytEVaqFyfrR_P^ZV7 ztGC`%qqO$U7D+>;4C{~~USw&|ch>hA*! zfQ>+&o}Szhd$_D@QN7LkaDAH-EV96>;IuBuH9Gq45s>vusD;vo%i`CZ5JQJ|7t^l} zUtblt+%tGxqQVt13Vh!<}PmbVU2CLS@5ZJdveeXQMwL4LyM zo=Ejpw~L(&SQTj-?fQOyOFhnluJ{=Ik{!SNU9#KlyFo*v>?_ON~Rd!R!4<;3N_p=ms<+L@`BA@`3;}=1R(Py@gAJ;rzgQ zc;wKpc+ELqR0r~cjVWfr6@KsK{NQW*5^BmsHnKLNqH(;lz}@etKZj~zA5Np-;S;^> zeU|e0&hk2?UR_VIIctg3`CXfu@ZA)u1;dqZj@LRsVQ>>%9j5yNZKWIh$qp+ja%fG7 zS5Y8bB8tmHt_CLa9mbB76H`1Ta1^jLL#tNYe3yG!<+ zbBU9_p3m3n$|l7*&i=mP;}^LZgGUZ!2g`aeBP1&E#80yf8D9mo%V>K!K?sHV{W7Jm zXXxSPu56mPZuliU1ZNIRYa`BCJVCj(`}BHWfWj~-*haG?o@1Og^+v47&o``j*=vt3 zFs=OWJ+_T{p=0(`z^&axU@R~OFB>m&Fylj8d7=$kh+udt=>1C9T?uM_MSn#Ly47z~ zU-EN9;bTI2IE-2JwXT_HOJPW@Tu~{W9z&lbCuT;}P*nDW3|j0q_DU29-XtDD^nlQN z0hTc*UiXL(cy~xT-c^NtHvKMMggA|21{{)~eYtSN8W#-cv9F%3F$@=rU;x2T%-B%- zib@16NKEL-u5^5fHtlR2TFEvQSlUj83A~w%;|TIZnaP-Wh)X+;7FvyQdO-f_*vT$L zu$1#f*Qy6*I8h^z3Jxp_@{CIxHNTshgPWEo-#^5#U7 zg&K(xB@H8cPBs+;zfqcAO_PW|A<-*F!i2O3e3^1w$EoRmBu|bOFt~z1S>4m9?shC0 zNc{a(X4N8evt8Ya#JH+Pi6^#Pl?FOIQuQ_O?q~ArN(5|q^H>C3xq0&WH^WZoQ--6a zocVyU7P`G&n$^s3IXLuz1F1Q53YRzyNH|)9m}+(X0GXO)Ss|P_Q4Rla;ZL|U)k-#r zdWpwx*MKz4vA{h^hq`f^_;cyzfP!T(Aw`)VyGEdbI^XC|=GUHmg|HB&Cf zrco0)f)^ar#uIhWQ~_HdKK61Om?Nj@=%fllVKc+24QOjzGP0(3>RY3h-yI~enczx4 zSx9D6^Ft{|-=rP-T#rvi9rEp6?%57{8RgYXyKUi}MZU2_c+W89Kim|Za8=a$eG=aB zCQ@o1M4z@EfFZRU1`5IFH)>9Q7iCZG6RItdw^^aO9Z(u3oeYw4lP(MDbvqRF`iZ(* zH8_ys+I3%E^T3f0cx#<9m3BKUW3bHX_HrB?JU@ua+zJhc1p^7~nwR~v-vHl$J%@J~ zzYr}$H5Ymks<=T8eN^g5Nb z$wE9iDYZ>8Gr6ylpAKzLU7b<7X0lC}RjzvzNCaMfE%nvk9$sBmNBwc-T;iSuxaF|( zf7$8QMXnzKscS9-8dyJC86Z-EWkRRP5HX-go+l$_5`pXbf}T4$f!DTV%s>tZPFj!2 z!Yoi_tI?cTm2ChFt-)o(sg=f8uvpjiM_)t2lLWy%D-_UgX5y3&_qn-;1JVN1b?;-L;|xi zzxjlm-a2}2<5X?ctEyo^brg}dU_PyFGcjAWv*Qo>Y*9#paNR$CxJ&EtXPP5+cTRkh z{|TYLj)XXZ6T*0rQbR1b|}mWKQ~982tCQ1e2goR?)=;`y950<{-ghA+b}{N zW9fpBX_{u2vn^J=RIbUBAQ!u@l4~i8cGzukIffQnENvC>Ep>3du`wp1t4TO2yXbqW z8afX+V%dSk2H~XjuA5d)1c#EgtxYdLqtA>5YjP&!oH3nzXiUw*-7XQz6G|8bmczs`J_Kn?FaI zyKpdY*WBYCE`0@S>`A)U8+;k59Wbp6fC}h_`$dyWFBL!vK&V^xL(NwWpQPWskPb_b z`|_hWn1?KKz?QZ_ess0+(0Wchl9oL)3HnVvVvY*KpCuBjV$v}-i8@@_SfqMHx>mhJ zBHlEGM?f`svgWGz$AA%NZLF+xLzftTR+Q_N<|V?P`?_jNGj6X%od10o*lxjV&3ljD z`JJsjCeQA6Obk*ZPWM~uNY5=Ty3FQJt)X>Oue(S{QZvTEmwj6J3k=E5D27L{1eks( zLt0fb+OPEfIR0Nf4|XPR=7PqHxDx`&C#CShr4N{W7g!wqLg-1=hiZ8Ak*J~97`M2= zk7J>YXQ41Lf60;t&>(LyK`0qB!qe($XRsxBruks?VenuaYeL^*;;Z4EGp zk|1$;A}2S*7^`< zt^yYuDA?qpu*8a!z?I$T(8VbF>Jx2lMq5!L>oF>rX=_y9S*A1uP4miQ79=qR>Un?h z=sCR^wdY|%%G*5WE8Iic7~l}kK0;;ZpKMk0Pi}Tq^Y4iz>H3*QTz{{8jPHKcmpb4j z`0UXQ-Lbvmwi(b5Ej}nnsP>D#)zbeYN&a@egug{CQ^w%y6HV9eWW$=#a&X2^QoL@r z5`>1oZ6fWC#-Tz)f9f-7u27A+cD!Yv2t40~FQ{b5v%KHW#i~}I^9^3tSi0gCMKeWB zMstifUy=-DHt*Y^eAnqO3?Lx8^75O$8KKl<{Yycx;z|n0>`LB$58z5##RI>`&9M zmC>PmTg5tgHcH|6f2g~mPXE8&zB;bTW&4{3K~h1wk&aF5y#Wbn1f)Z{TT(&<=>{n! zq(SL!5D=t6QlvqpOIkweeYWRZkAUa?&i#Dud->zYSxh`@X4cGFYu0>M&N7nL(`51H zcYLdk-&nK?@;b=2@tJ3FP(WPm?uD*tdASDNqHvDpzRN8;0@+aZnRv76>Ozd-3FAlU zRv(6(gxb(12E9!t$+5m*=%sep-uonE$xT?jIj2;~?U+J0rlQb{TDg6;;rH1O4u`?c z0KqyWoS`Z$e5|Bz1-&L{-a*keSv1`Uc|2~K&OU)eT0nY40JOm?TEtT9`V>R+{Q@gG zV>+eGBTpKm>Cz>a#{JjZ^p6_P)#@fGMZ?+VltseuA+{v`xHktwe8buM{7MmUz=$O% zAUNHeU_H#pxVTNKN|lU!e+&d%BsLlM^7t?2(tFSse1VwP%u+@kyk4k+9;Jj25h+)i zzs^-%Op#P1K#P`r-a%qWZge-%{(4}e-Rc+Q*Q_oqIUTR}%w6yW_?Vyb)j{g(4)#U} zo@sKEkdM625)oR)_SLt)!zZjNEhJ-0z>wQ4;T)i&Pt-n!qgAZyy~Fg0P%ks$yL;5j zHg6v9hw#Lo)p8@urIFmq8^z~nSDw5!`cB|(YptuRM+ctJk!rF)p;9H4Rg;w+zur`q zXe_D9>ZbCTooJ4uj$q+EXAC7f$U&kcMzvW{*n@{MwUm$pb%V+=b5qKx%U2v%9P8oDQ_L_VV zIQG=|tJbK*=1XPuz4fpvb%B)@3Z26fkCwBE8Ln@lwKfmu0D}TmrAAP9s-L$>I!#SI zB1gH=pDOK0uHl9@GrwXbor=DDV6BEX3 zWJ`98yaDgy6QAnr5tj122^+Tvm)XvTlf6Mk>5Ea}YKz*H|Du2?d0r&0XRgmNT&+HK z5S-1CVq5CjO(x6|8n9$m{^(g?=xs_}ZjM*zGXqW3oacRcojUjDHeIhPPe&LuEXO~2 zXtFl7N51K^VVP2c_-+!;`bBM~r`}Y%OB=H|Q)uS|m)RVIAw>)`u{Fp)4Y^byL~2y} zxwM~>BHE6?9jZ2ejZ)v&1O<%Dr4wG#l(_ky>F%?&6?NZJ&F>}_-$13gv-f2MGrlh+ z(D6=Xd&-@}*$k7KRe=`qg6wcTM{F*=-y>$Nn<6lV{+4X3`<<;TU;y{)zH8pbZ$SJ38WkbBT7mj z!JLSGw}x5ws~*#w2WMZTeRP=bf@VTzWj@OxrRQ_>N-Lj9A4wm2-}gkV`g##cBT+bCFY?1(B}IGM=x zhD`A-(qqumR{HK!fN1}3yw+CJVn$fsQi8smj zcAaN_ZEN@7#Pf!OLmIH$&wY^QWeb9l<7VYc@dNCa z{cY+b1-U0Cfwls<$LQF6dTiRGrqyQC3=}#ezC%?VZ_ij$*gOu)=;dr1*F|tm;0VAb zuc&ov0s<@95>-fEMA<%{pyeY-4ryadxQq2k2Anyeu|Y?Wdx&nZFgf)l1eq&ke00A? zzVY#9#<50QUm0S5wi9>jbY z@~VO?cA*D-@c990V+Zd3{FY(O=62@sfX8v8<8FWb_lfe+>O!bc=GR_T&!f|}kmQ&u z_4`4e>YOKbvL%Y-S;*WzgjW~5ebQ3yRT2^*8;@xdPfB5}ZiyU<^IRc1L*zw?lm=@O zP9GXI8Uq@6aZ7XN*-})7`lDx6+hT*NsN5t9=2>%K8unc${~q!?fhqY@9&gGwnIBgW zem!gUZAY1tshH-xF&P#m8BL;wQkue&r0ESmmyEwc*HJ?bxRW`-cq$AL2kj|aJr8q{ zcLk`j=f$+h-jK3e#kCY!Cnfp9yDGddT#xY|NuVI!o$NcG->w1jIKTLiWH zN+i|9b8utsU_9#qVhSbe7Nw@
E<$uk3^j9xREDyjj5)FyHLac(`F0czmtCe#p9 zv!`&_vX{#qp|~xDQn5h9hvyxwHyXjCmqx=(G4A3trVcl|9`>7eO|iXQ++VQrowC8) zcBFBtvC2?>o~7&BB~===@|Z&YYsAx?Al@Na2poT#gbxJ`YE$Zpl~HH&Hr; z*?kr56R|N@32&5 zm~TG_VO3GNgB+|wy#pak!CCoeC{l1sOYF8Cr`p*a_)ui-(9!u?yl5}|8H6O;G~idx zG={O8^xM8m_LEqX7+}je@~WvtsXGggM;tpv1@0!&7|@Vomnt&qF*YGQ*cr>hNzxZJ zys?`ceM7AH+HzVW^Cbrj;bF;gRX_SC8E`;lZKIP-<%2yqi|RLD&m+$M`=>}TEIW4|FXS31P*mGk0tEV#_S?N(XjckUSHUoQ^he0s{f zLvZA!5ViG;Jdwse2AMU4S;(MruPl-{Pd?amE^Z%Xfw?!F?>2PZsXr%uqlyb#tBSd7Re2oK$h_~?oi`U3hi%~T1{=9Y2fw|I(3qFAK9EY`%; zDs(FAovo@_4}5N(!^(u-$J-6mbM0avZaiO+p0goLs9Sq!HQu>5^(@#?moh?|Y5cgp zZbZ=LJBskxxyAby2_Iz3S*-4lvG<0OJYNbYUOT<1v3?CJk%hWbZzy`qyjgmFaQW0Z zl%eZOOpwLw;XqN-{X5f>U2`jv7PJDXcS<9lX>4m8Fv8LL2LvutpBG!$PTg~kNSEq8 z4}IS_+f7E|>Ed|mHt2}^`5ZxZ2v7XCA?g5R{a+7R{>{@hE;c9_@^??ycz(Rh`t#`; z@R;VuGpC$&?+usJj122J~ z+>rnC;TrJf=r8VmK3w~4FaN`LYd^;PpS@e71fKrE9%XUxLNB~Og8usA@b4q~xwtO8 zZqbSEvGL`=5kELXXO9s#-j$`MdWGcEnt}ad5iy8}K?&3e#W-u+xi0;Rt*I`sc2}RJ zjFa8Tw)T)aGp}ic!*A_XGh-)ig4AeQmcM zom%(4gJhf5H^&BJfACsy>VS+EOmHerXRq8s8HkmM&8qi~4PGxynOTFc5uPlv7M`48 zdt;^6K;0O3ttMh3(`ICQ)V*+PE(;O9zNcNjx5q==RmKOJ~!SF4>4w~HSiKc`m; zuwPYqo;hKbV;H>?Z3xzjpIitT?Eq2j*#oaVZRj|#&+T9M!?mtb-EklhAqow!hS=0>|$ zl`DxIjm@owfF=Kg_O9BgUDR7L*1bOJV)DyI0SD%duP-SPi36d|5aC3jB?6fp=EPixj2A z;i0k4sP8C-F4Fr=g!xLR!UkN8NchiuaFca?tX6t%MXt>HWC-u|Dyy9yR>{8{Mz+g_ zuc!{xn)DNWy9zHw?`3H!Rm)Glp6axh2a)rAmgiep#e z71|Mn6&v^h>cztS&e+^5*~Ew07Y$*igt9T^=$IZG{(W*CW{FLWW?FxFk?i-HZCaM3 z(b^}6{zV^GJ{^Xdl(oe}Pw6EY=a#y5zT_j9?vA{O)rA{r1;H`Adjk#1w#R8%_71o^ z75vd$3Xo}$jdVU=woapf6W@dK&k`=?O9smkZekOmlg{GeLNxA z**SmuE_Dw0tZZ3$uX#G?xlDn{q$8xwb?(8~a0QN&0tclC>d4E~*)%UwLr0OqU=eRa z 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 literal 0 HcmV?d00001 From 3101579cc420542f4694234dc0d26af84c1980bd Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Wed, 29 May 2024 01:39:19 +0200 Subject: [PATCH 03/18] Delete community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb - Colab.pdf --- ...am_Mansour_HW2_QClass2024.ipynb - Colab.pdf | Bin 119117 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb - Colab.pdf diff --git a/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb - Colab.pdf b/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb - Colab.pdf deleted file mode 100644 index 4ca7ee3a8ae9c2e70c1d2bf102f99bc7025ac1b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 119117 zcmeFZ2V7Il)-OyG=}o1V&^sXsT{=idn)F@*gcb-L1f_!%snVr4QIH}XM39d34$`F; zX(Ax-1%00L`h54C^PczK_xFAG-rw2TNoLQUnZ4G3)~vm={xe}#mzCoN@$li}Fy~Zt zOyc8!0K5RWg&jVQs3=ed0X27n!JTBy-Joo;B4A!HA1^;x2n^u`fk2$RysXHb{Z}bC zf=w0f19NaN2lDgq0*u&HU{3B{_W@E)RtPxE3IO804^TE@2S_yK?fsbHr4p24)n5(V1qp7O7lPlaEVXB}DHr0@EFn4vm zQIZGd?CoR$;0DOR9n3A*#l`V)piWjlQ33x3kCc-W+|AVx01`rGY61Wt;h*2eKpD7` z8`R0o6{+}@21VCVbpfK1NsBVrxmIDX~{3@jhy%EL|>Wakv zftQ=SmKzdyWLh4?2SDyWTapI}0Fe71X+Z!;@Q*YE0Qs2`7YE8AuaB%I#|QYMk{myP z|5q_N0l*)XHx*6WU1bhVbasw(ln%h97e|^dP`cgCo>Zw`SK`n3E z)&qe6$o;1ndP0C-2#6y$pq3lL-O}xsX08BU;3IEmC{j@y=~85ljZfy6@yXu!G%cj>P=!0e|3}*s z`ZX~AYqlqJgAvkI{7uu}g}FiDe-K9YFC*c`#kf2E9btZ%;eSz>Kb*wh73QX!|0WE~ z%~c(Wkbyfo!<}w?nGn+ZIlvKG&gPa-L!hFJ%nf!o{{N?TNSlEIR~U`lZD=l zI-mj+W@GDy>`femxr&Ia`&>x=Ymo)&uLgM1CZpgcp zBR-B-#_k6YDhdipTlR^XBbI44GI_H-okXE~ih}ynmH%1xPp^J+oqtIqB)lFlOQ<}; z-1}eB1kC@xB0MfI8wF+22In7%{S(wb<^DUs{sAXg7y^6bOsKG*Ywh4tWO=lPb>7-6hiB^1})Q*~h)-kG^tFt>NPs`H{OExTmM65KiyAex@bC4<59+?fv=*` zN#3n_Er3O1_DStKmo@8BUy52D0L`4l)oX}Xst#S?lETA!3cpS08gu8^*HW-Kof+;t zg<;St;vR~3u(_m>--F#Xb$6IoV>(X`o8lft2nXet&9PXvJgpC{tsiCOrDUYc$&&2m zY$_36=;vhp#sx23@d?S)y;Pf{v0rDjUs`Sz(A@U0ReK{EyX~=bMEZhT&o8heZ@~iM zfA9JSN97<&vZJh$LiZzol#ox#&41TWe%|u_L|pp6&-Our;J+Eaz#qnsd`S4|5dOSb z{ma&mdSm^8fa`K61<9M_e{B1hLeBqS2>iU-zogl}HU@sv2rTqp9|WlQNU7VhPt_a= z1ha1xSnNU}8Tv=E|K)MwpY_V`vj6l`j}S;NZjF5WxVh2&a!s-_kN)bI1bP4L8$Nz8 z@4ui6L;(31^QVuwp1NK{AySf4lta1c7*ym7<$4xH289S0j{pychyb5}gqY|KIU6N8 zDJeOKk(q`~1R^FX3=tBPR4{rdDXaTHP)OZTL)X;8#@0q$)y3P{%F769V|m?*f{TSB zhb@eXN{n*-5rqobG8+2N&c6ZdW<$M&hK_-G8+nqR2n7ud{V(TH(KJZz-b2SA21(tb zzn($Cx~VFGa&{(xvE1_^iu~XE|49hM1<~iCvVC4TSoQecEC_7Rc_RG2&ATj&e`u|N zdQv8B!_}C;KIfC0@V~SEjl}M?h1(x9rKcERW z!(`W%%*w`~=3Rbz1v}~3u@L$a92w2Kq516i3YwI$`Tx%THzxl!h<`X5$Op&5x`y@l zd=3<^QNprL0SQp6tA54j)1SA_K(@`tm+$VrAL*qVdS+_vM?SUD*(E0+0;(8}j)`(` zv$V{kqWO2`zXAEb)EKNGSHb?`z1Jx4IZd@ow&wRds!4}WHpAt*)fP9yDp$@OO?Hwu z?~hb8b5i~LL1zfe%W6IHxCAU@&WL-e5E`JrEYi7+1kxr6!m`H_?z-`|aW%Ol|K&PXaq zM(g*`lp+90qCtULz@OnM=Np#L()(B7`)36tL-R*$mtPq84_U+C7{UJ;f)4@!{o>Gm z(RzPSW^%|_*=Fh2`cp#Y$33pd0!t{pi5R;WvP~leAGB7~$ z%0Ov2!U~G`#R}gLY5+cDcUrm`0>J!W9xy+EPXGkq7vcr*2||qj7I;Kb>-K+0aKk|V zMcm(+jQ?C*Pft%C8#vs?0m@?ucLcg493))Ce(J&ukzxkRA$KbzpZS|c$ebJI#?=j( zxY3E*#vNt_MIJaKvv1<4$fS!S-0EjJCmVMp@5_yV{=sr0Gk;-YY3{)7hU8vdkvYs@ z2r^WPq>NqvDImi9Jp2F%a>f7>6_B7150YJl@Pl~x|0P(!H|*1&!R>!cl<-6Ncz-wN zT_eMCnp!7+)A!QP9iMhHFmIt@pnm&Sb2Ju~k2zBtL-TO^T%QaLER9yo9pgmxAc%oF;$ zz;of{)t5V`E1QEw8>sBTPo+J@cSn65`=WJSKRF564)I*bGI>n=`SjXv`5SY9{k@bc z&my3j>D3kHt#K)rTWR*fj`ZOLGPG}*ZLY7ja6PeGF0S0J*N&In5wV}s_a6?0pc7P~ zqnxhoZdMUl;L|tb(TfF3G6%;_Kq=n~`tdYpC}G`|0pQVVUq;VrVkJs=!mm~^62%IP zaO)T6AFqgSkL6qA(SP1OB}zrJ&D6Ly@$I9}pA>nP{H%Zou+a^D)O;$}qF%y#|9t}8 zv%!)=Te%J~+%LB?2b(o5e-!XB92V5Xt`utQbDYN$?Z|oqf}%CGrm@o%IYUS;?PS5_ z6Y_22`RpMmKY$!r*{=7SNlCab5@jOY`P=BhX?f8-$t0sD9WzB*q9K~}Wuc6C^`=u7 zTc7UC+^e#iv`!lmt$8QCqr%5hl92|aN24sH{H){`Fv>hF`ldvn z^u95=)!Zw5a8tDPTX7tn^|vq^X2px*_wU46ykm@?qYCzajPEM>S!90n{qpb# z#K&PTPRB)SPWjr45ag9VB|UE`E~gffz57)>45i$MB8g0<+A_&SH&;#7Gh&1BUDCJH z5S)!W6KFYa$TG{^tM3o#S##Xx2r6$Fw5h7sRl`QOhKMGhAwv8IuKX|jUtfs#oo8Kd zZ_`O!>~wryF}+&fK1zpQp91&ju8wA}FKV+|{7*mKeC!pyzuHXCx;kHxXc(06JS7CG z0ZkIxt4Hv=dGaD(htu!^jyYc6FZo{#vh zhB-?oWqj2W$Q__$9?5DcdC2qwIz%nu!b=pl zJZJqH92mI5$oFF689HG;!26>S&3C3Zkoq0V%r{ipIjMg3Y_`X77xo=cQzf<;%Pqfz za*F%}d7Z`=`6@3Nl(7B!L#8*8##HZR;b!Z6=ngh(uA8svwzrRh9B|qiNJKImcGptrhb{N`>uEJ!EPWBj-xD5b$O;1Oo%jh2P08Qg zqI}qbP)4DZk@y~4Fgk^S)q(0`+x*Sx$@5J8e2KeRQcCa#gF}Gz06sds;$g<)dv!rm zIxns2^aP!IQw-Z#jQR=Ov>!N=KaL`3E|ygOG1uvwu%+#S)dU4AiMPLwNJVRCGvxE^ zJCT;rR@bQzmkYIb%B0Z_Rlq~j+Hmke)%$LJK;Teh5uuq&H$1{yB^1)QW zkH!L3w2!jL2{c|9(BK&Qg*$ZJY3J%)u2SHxe2iVODV{=_6ShjL)}c$!8p-Ja8Py(? z59k#ybrM`?X0YOhxo^DM!i)_WBqhKUkmYg^!4nT<;D1&=<#y>IAOH#2GTiaKt;TR9 zcPCt)N4ZqQTH(bR*#eHzr=G^jw|fU;k5O5Qo>GwaJ-Iua#~bLi*}v(!Tj8~=nXbq~ z6==~IxN?g>Dv`X0wc9~Khy5O+;?{f~db;)1Iz>{B_PSR1r?Y2qt6rZisO}Uv?8cB# zFE2~zRXy>lYnLlOFLL+w`M$9%pu-QDS*E}8f31>V&Ch38BsED6$qo114 z543>t5ODOZkB^etIJ^u(?MTT`OON?+agUL-+fs!y&7!77Q-W{f>jn;u4z_`QJ7RJE zdf*W!=9Y_K%5Z&vMkdk4a}*vL8Ic^8nYdI7ly~_#%+nxh^*ShnFQ0fuWk?pQK8{Jd znIOmK(bd36A-SXA`OwK{Htv~x0}Ok2H&x;%mewDuN}O>mV-1h^+3Kbx&aHS>b$p&6 zD<$z@({X06#I1SJWQKUTR0=c#s!+WDKDkBf-{6di>UvagX#^jN zJ=-Agce^do5JdO+!}GmGdC#x=6Eq)nKH}Rx7VV?g*XyvFjLkd|2>YtlN^(Zcpu9fA z4VFym%Uz!%G);3UTUaQN6Q7J-ry+`D>LmI~-<`QV!>EBbe%!D<_!uvGwureQ^TJP) zTsK7@UJzQ+IVro7+ZHV@^?a{NEt}c8`r<$=GyK%)YfqKI+-r6tLF`W!r7fR}oNJr| zU6xz~_`YcjR8FH598Md5|`9b2Rg>RlLpswH3HJ-TS0LswD~XE2@aTGs40$>81gyBe7t z9jD*h=eJ&Dw2`z>&wnC$bbrq`CTva<{#fkby6h~>(=UN?S1YY0$3av`kVQDmy^8Ym zMDerU^hP!9f-6LKRc%!DK>Ph^41(? zBYXjlozI?)0c+ zF@Sb2^>@QjS#db@jw+Wgm2=$Xwnkd{y3jt}zLjt>ln30|a2#Q#^ew~}w*SiZ& ztzo(&rorkk(tvZH**?@n6+2gmWI&b-QA;-RP_40qKU*{;bwWn}$*5Hv9xYnzr=i@` ziFbMw9~4+qBx}|0DEXF9EL>j1M;z#5d3yKM@(Q!V%s1VgtSY6>tm9)J$rMMuE|ti? zmB`@ZPy00N7gqRQmZl`$Qkt2v<#0Gd^-)a6ulUR)0wYrlVedw7+JTGSB~4R^^+&dZ4b~O z+oW+{XF#?IXoq*&aR_?`lvt5}Ik2t`f0#`>fA`Rssxon)s06)gek@7R$u4QvYioge zd2CcTsbtt=MC+8*ca1XDA)~Yh{J5-XlPq&x+Ssrc~(p>o-9Kibo35GU37YgjRL82@QnPEDaZ~ieIAnx^IW}&5~o)SN9oR zvBuBQpE#@KNJzf$)s$KFOkI1)pFLuoc0qf$)GBz)(l(tb(BV5mXS$#G!!Gyb316Jz z7qT7_sT8TpFZUAM#I#m>#$t-nS&nzsW{>ge*#apjsEM-`SOQO<<%LhmJup+4k*Jn= z85IA6Y5_){M&|1rp(J`BhjRYPsqK(szK_!pOAc+q!4*`-$!Bm}Dqg-CcWZ!t&ZdWi z@KeLe3~olFJ3$Oon;I2hG%%RSms(OMro1M7Di{GSuICzF?J?t0Wf;>Pu|lza*$;2Y zNt`l`mkK5%&EfXuN~-gwcRX39#2?(A>a$bfs;|`qw2V422^h)fvW2^(8TDCgKOo^s zlKYq8l-!d+BS7al07mO-b;oeB&;G1;CzH`ttbcf6ZMWIfCOfZYX0?(Y42BCXFYdJGxx zD#xi{<8=8wOzf(JGdpYQx7R5N23w&P58HDEo7X=&v<_d8+ZHad_ESK6`g&~(Un*Xf z&HM01keQxp;N73@+Zu>6_bc2yB?mz%dE$wog-gm6`33m660YC-Ha=>8+K3scQYsYl z#HX35iyF4w1ykfLSkGHCbK!w;ttWXEAAwFWC7L^u0NC zGU-79yTk@mCvGTn)3M|OnFgWYgF_|5Jr+02jDQA~M!|@<(Tc|av+toRR;X0yV`Pub zrx2VAn9&#fOqv3N(;245`UXd2r(Q?8vZg%yXT6=9_YYw`bH?KRDPPXDFuRIa%5Ajq|CzN!t24O&1>vi0|&A|7jrW!tB8IDhVwf5y{Cr494_V4JBXD3$nhv}Ss(k?lF+xMF!v-fUy*gGpeRA;HOjRp4%z$y&0{ zvcb8sSv`%c_5QJ723bVSK=c_!(u;IMU#{RuJDatEP+RH-ApYJ2t2pdVbcYC*e+E=uk>>;wd+d zv$Cqr(jH4`&kTDK6>W=^=Vul53RN$DAe+UXgk$gEk!8|IeR6S66O5hvjV(xx#r@UR ze!7dgu{64C>!Wcg!K2()0?A7#;~i3hO}VcK8qC?bYi6y)lfKA}g-4M3IzLMYoi5g_ z-KYG)A=SISK)Pcf@~FG-5Rz^`D+oAF`${6g8`ZWQbbdQjS#(3U${k+* zb%2Jd6O64d7prjiQz*&uo%5z*#OQ<=dAF_S82L)E`F@eSAl0+1PW8+W$n(#3iaP}i z6It=?dbRf18aQZ6UVN-o92hdYu8@b=z<0!AR6>PcQ_6F>5@cO=(e`EBfu6cxKv!xa-{(KD=+m64?>FO8*Rh8+ zwg>nI%R7yJD06vq-Mi=PdU?7g<0Ek{-#B}5NN*DPsb-_GLjWqu@KSjS&V>FjGA$ms z4Og6}ZZ72ooz9#+5&g}AR$Y$!3E=_4o69?FY=5g=vd>xv5lDmYaZEd-IRJp%X%M`Z2(i2Y7 zBOk?*ZD2*=n|)VV35f%=&QANF0Q;=RWUeK>klv3Fs}lGb*&W~a zcqihz|6pDy(sYk_pTtSjREV{P%ZGraZ+ zWIpq+9`(294mFK)OsS0TdY7WbsC<4|GsC%Myc=KBJB4^t3Mm0cpI;$Vg zlVw|XdT@KKSED+ep#ORM#`l1F_q#M|OHZ$)#(uDgJlt1a_trRTXQV&Wm0r!xYHHyx z7Hms`JokjVdPeV8d69K6&${4#UW+8Z_5}Lj#;?NtQ1wlyEIzxlQP3YgDA*TYTEMyf z_GR-Lb+O;``tQcu!N0Hl`g3s;_}46C0QeUdfMhd%&Px8vBBwuA&HOJea{7&~xLI<7 zjJ5yM1x(23`M=0&AWLffWl<97SM>b$SyNLY|Z7`gpxl)&%I-v5rUxZW)ObG%tbh$Kmz+#R6^m?ifOv1H?P zlZ(v!r}%*Qga873Jm4F2!2H6<#aTSaaN{O{|?cb zThd3C;;4*It(5(@WHeFz@QkJ-hLt>43KcH)aS_&@*8AU@IN4q1as?jFe8IQ*&QBdL zgQ{Hdgn*`@+{{ZgZbcOoU?tn})2Q|6{+N&S8Pp`hNNIew- zFw8bxI;L!M@`%e|3vYl|kFRUXjr_iUZ(o|`bdmV6^0dqf(UWj__5It|%cb;oK~o0( zM9!#Qjwp{0#qE^o5jpBnu+{jth=}1^2LQz^kGJ&#le?Fw;gOyzgK*P&EwlBj!?mwF zA|i)-YZvI+v-D&%5smc{qViVKcu^a7EW*RDD2Fe~KYubM)D^TDlED~E)Y=#|lR72_ z-Tg>3Q&qj`cAgyWcCrcUVf3P~Nm91~wJl?M96l9a6D4v#fF*7O&#Euje%l;nlU5hb z0x>$7-5q~INB8&(tC2v93E&)8_PI8qbN^UW84+|EYi5MrN4gSVeb_Z9z^V602I7>W67R{TC9-CEucNey_4%uirZ?Tx=c7Xbas!dv$^J`4iP?(?D^GKtt;BjFR=%2z%9f-{?K= z>Phdzr}q&^qB062Rl}CWT6zSKO=6B7lKp63K#RL?{1JiqGa{wD7HXHnN>@9}txi@R zbsVjM%%~A&mRN&x(3A9YBauoQ%A(Lb()Pe{3!FiH>wam7W-)z3b9@+^ zV?m)wymD}ivsl8;5ibPxx-BN(k?lHL79lkP%#t6l>!KNU^aO#u*cNswebcO0npUa{ zdB5OgGJUSs{X|l9S>euC>`afEmnx!=BDnY;5|ma1-Q;#PUgv?DrXVb;UFVbA7mKx)f0rd1ft zT~lKp`2`!ys6*zo4>8b;V^ zyu2MV;G5)e-KqN}>HB7R9kzb=W*P$1B0FhpZj*g6vhr!`Fv@sC&~MT4=`3WR)x9`(Yy5rKiHE9s0?_6rYa>%&OZM29RkrymJ-EBkO^wro(1 zs7>~3!4?tEcGS*hq{8|qQ?yWV>|N~A_ET!aZQhLW`T)4~L`c=L2|+TNlf+x2>Urkf z!(m)KY#VUS1ltHXu#e!?7|ADWXSNW`?gTB0DPr~t&#bf@r>C+Pf=4WJuv3qS~?RmdG3%@exi7nYom@je4>OP z)@&QoIdj8iA3j+SVKlP$s$n5?d(0|rHW zDto2$p>8N{_-XAnWz+p8ErUwWTR0qSr8@Z1w3@Ffo9@3gd6umTRF#+pq1#1J2YPbF zIs}>*&L-3kzD}03l+W+zCSV@tFz6YUEqY*l>%zqi^Kb_sX_>>@Fi)>B#@-k1ukb5&^*bLL7&C?Wwv5nZ8 zDB2}xD(<(-B;~lU0vfIy`2zni+?nHmnw^4?<7F6y?6Y1q7N^5@UmtYo3&n z_q9rfGK_n&-O-@I$1Iqu(edCQifl9vjGvP8m@d$Fs|`boaBILM$I`k~dyeN2h}GaO zav|a~BMN>#!EO^aWLElY6rbNX$XU_DQ=@uZ1_&G@|74R=ms=z1xbXCK|Ka9+3b)j$ zo)w-uYQA5nx$Q>AAW`gQBdyZga|(unrRUuvPWmU-@5D;(&RyI#>EIy_y_i4^$m8cO zd-Imiyqv(jxVA@&&ij3+zaUyOuQO;dsu^>;d!Jx9FU?8EnZR!QG_1P;s&{D+^qJf2 zL1tAO<{bZ2@I{%ymvswvX0gT8%T`Ss3Y_z}JXAhn35&81{*0mF;8)4H8j7-@pz!s$ zqFc_(W&tfYqRZPkdoo>;#Kb3k7lEs-bnl7ky*oxZwIE3;9gGO7{)mkipI! zRE{Cdlx@ybWR_`aXIkULh8<>|^~j`akh=-+X=XZ3Ym%CJd`^9B@|w@gaT8SQ{X|+KgJtZyQC~I~K4Owd>E<3>HZXVGi~kX}^6L=6!v3 zejT);>jHj2lDG`IFICfrr)q_3Jp||@9BO2)MzK-WAcMS?S*P%Sa4k(7Fl$> zx!PI&R`jH$rP2GMJZof5)4Cud*JSJL-Qp8WW}w7x(8`1{%A{^v>4#=c}A!C+a? z%1Vu;Jp1@g3RUBi$DoQIbgo~goBn5=iE$hMz>BixkK5F72H)5F7Lb$oil*KOC6cc@ zT2O0;8>&k{^dmF$AM?^a|t8=Z+`Wi9+yj5K#jz^S_F(C2g0tE&A_Xp$ix~S-bIyXbl=7wXc6gZt zVU7w1vGir@EzK!u!bY@5%7*+e3f~P7*>(B94579udRVw^WT^@w zWsL`9GoghTl;$&1uI#EBT+QGIpMhjt!XyX&9XRp~S1V0Yl=ZAn#bd}N$!{y#`G%!2Yhj+@G_nFj~ zF%Mh6ma8rs7nsR8A=w?Tlj<{hoJW`vJfy1VTy78ot`dDi`=l*d~-~K|(lU>R_ z7P>;Q7ahVSj0}W9)glynofC*%OCdnV{@&2h_R}6xJ_0i;liP2ZSY%LGp5vLZPgYT_ zdZ6*<#uXFBBvElP=i;t)_9}0@s;@}9m@jg*43b2gIXoY7NZXk z?c$0Bn~`p`gY04b^vZI0A^7IxRykMAOj8lMb$B=in0-g$Jm~H^t?>b{x87ug-$Nsb zo3JnluGU_mzURYFLw^r6D-f*_pC!NFdj3_em68x8(t(4PD6-Q|lqv7S{Lq3}aGFdp zC|Jp|z9guXHPp8Lf=HE?VhKUEvA+nck1St#`qUPK$93ITR+XRAKRlU)dytsb3o_iz zvo)|EG2{CXohZ=O$`&8MiEn>mU%WB<)Lg4y}_Qitm~X_j(n@ox%)?<+)Umw zHOiiFGy{+6l(P)96n%B-pz73nd!V%R zvkcV5mkQi3QB%%hQ5REuJ5qHBgJeO#6yil@oBK~xB-a3ILb8;RFo-n+p zY*tyQyd8>D5~bECdb2600JH;I`dh8lGB{6RMK`k0YNDu!=4dytEJhD!TJq)7fC(Zy7Q1$ z&UF-&KJU+{FO+Yg^cB=1-%aRTlU-8}gA`BA5(;{s$m$Vdr7V!KG9IDW_4N3t&Zq4p<#%PD!rjA;{OXZzkdHH>@UkXlk z;riAOQz%NdSqxAAjV1XEB|13Nl3jm z!n^O4i}$!4)g}A{;k~tN?R~sV<@ZFMiOlLg{4$a8I)ndEjXuP9HA_09tLI4}4a;?EVR0C-Ds@+P z7Ay?;F6z!IS&h@hYgiU~cm>%dKZ6_)o!!}e6|gweoka&av_b1kMw)K!JV5UC1SHBK z8a*liX}VlU(=9}r?s4a+F7F+W^e?wzf-k+gP8 zkdd~=Y#V)txQ7356~4I+@7W;VRtNp@;1{7YVD-I=^{t90WnohbO1Z-d(f3!7jC1Nk zxOOhxf!|Onvuz0UTLUafzv86a(sb!Z+Z47ANJ08_`WSs>D1koMqL}t--3RNsnThDh<_r1LoGZL!+2%mA=KFyG!a{)o)8v5x-l)L=^di9lA4Ea}VCbO% zcZ5O%s*rC()X)HQWL};~XsYsiNT`MdYjho*+vkX9`xa9{SjnI4Zkz3AwsH-J*&cR3 z)wK|-SB?1b$@b1%q-}m`jjL>KJOQMRYgl0t-zeSI>K^Pink@6h2N1z<_W-z6DdLCf zn?@;0;^$B0`A|gBGq;PB-+VwRpFj!XJAc44o=usXi3xirS2K)7!#G2{AMVk4KR5mf z9udxPjF)`%5g@u)zR7YXqw480hiiuy>+>j2y%D1a_Ky;Xl1FL`XN9xAftR1+*MmIe zT9Q}tg7FyC<1v}p4nsVPsoU?XX9c9NB`-akEq9o{#PGD`!|}8=!rdFfd-L43tP_{= z+cKqb>uOM$1wyvSfJFWj@;N&_jo@?60@)sp{uJoy;+ikw?C~Xh_quCR;`X~j?vFCr z*BexA{v%aT5sBW@fTK9{7G~oXGLFN2|GF`RDk%7kiG=B^*GK893PIou*}gZL-$`WV zESTSR&tg?YvsX(SU&_J-&mVETs~sz`!e{sJzwc=EHi@gw6CuM;Fp=IwjTorMeWyuM zIuhT)Cx6c%uSr#P%qU&UmhtOdZPl>~l1Oz{Z%R~y7=D2Qjc%=#&ZL9;E|HGTDz#U% zH5%5AG~3vQ+``e-aF9cfNFNQSYx4_?ujlshN*=UYRT;jmQ*J=C&7vdf>q{`vW#T~54Nc^w47FOxPpbl z52E@p2fi}<&3=>~1N%0n?S#i#rn6b(YOu~LSv%q4Z{pqc zHeAUt&=*?wx!M(I#W~^!xn01L1Jp$TJu4;GkQTq`hlX48}fO-9E8w{i9L)6;1vsUIwAVh)-rDK z?1Rl?KNoepm)J)gQlM@u3~y$JjzWrjX+Gt))Z=iu_Od4A$aP$W{d!=RLq4#R+&r+e zQFyOu1A6SDL}enm<@M?+&&j<9PH{41Qz-^o5yAH$$^sfJ>C>Dlp&D!Xj7s-=cif4i zQ%!Q;Z0e^)f~f|Y?o3t|gSuDxZsC1U4*Z}O()Tvo{H^3ZgWjtuGy!~-pp!;b zYpO6-`>*%MvAv4y2QI%iuk!^yj`M5#F{|4Zei|lW1!62ThNAiYSe}zEe9z!Avsd7*{sH~hj;&%L)&54%Zl}V8B zHhhsLy?xK%h3$eZU1E-CZ9tS^P3!rGCMIgr!!DM0qv5>oj>36QZr+BB(k~T6qp)CY z2fPgV-aW`Xd>@z~VAcE8m81j64~S$ZACWG#z%5%PIt{rDc*y52k%W7WZ@5)7!R^nvRA)Mpwr5)4_Nbl zkrFt-P`zf_b=OVI#{NYyOWG&pYHRjg@}dE=YU>hsZjXw*{R<}6w3xAQyM=S1Gs^*H ze!>TQ=P9PHM^X2N9UwMGW2741LW+D;(Xw_ruUL>X;RU|*q^SXj0{pkAgC=G8J`G4k z7MwMOoJQNG?Yq*37p6)rz9<&4Sw_&OS<4#x%QBwME2kAF5@clGDWq}J#o)|uG`@R< z_z<6%wcdQ-f_qA_0il^O)|fpVl`zc@vi;5=ohxlvXT5wLp5Xz8@E{K zk4fVgea7Pj&$D2dmt%Yzw3h?+BC~UdOlo1F#0g*T=GryI{V}bPi!swSn)A#b)@N4_ z8&5u0vL zdE$1L!57(}JVdm)=fp&PTB7EhT+#RN3Hnji;|SLpCy#aS?J=i@xIKxlleT9jSycJ^ z^Wu+0nqROdW;9(+n5;9!#GopTptQAAR6i1IGJ!@V)$*HV9y^^qEaD9EC>Jjdd&pbb z^qQ`bRJ`TNpiw77s6hAdw&Od+zRsL5YgL$*JV5^{nlOFKKT$9E!)<)qmLe9~X7R!v zd0&llboU3Uy=UpqtEF%rs=ut3G=N4wzCLdhOJ}$|;Wd2%{rD#7t$l^K7c`W+yLiYn zf-Z{}Vvwk@UgkNSXf!@HbH`fe;)M{0$@t@=VCbGmh8EVQul6N+a$Z4tgs$|P$@jSQ zk1tZz6MJ>M!M2L0?LoST8S7_LGmsHg>dGY1E50RbC4 z=5Cj3_tx!By&=qyIHG4pbw9uYg1HlfZLe^H4K(lPwle0BrWIakrjm+@eu)Ni=T%zf zsRYcnQ?G5FP=>W#r{mR*s2?q6m;zQrwgkS-_%W?0^&AFyEC9Z|I2SnWK8s2;WN%nK zs7X8un!K0-17SWh&t`2;bC!n5fQ1ALh##iW+wFbApQ`Nl zs*32SG(K8l6FTf>Vv6UhFOEO^*FF4zec~vQ;r9yYDrwpuSie`XPk3A0>;o;W9`CV+ zf0*~$wu=OUFX{kRlwBo$ijT)*ixP1Y>I-US1-jiB)lHwy z*hR9k?f{n)T3q0agwV4yWH!;<00TgE>(7cEgq+vHO{y)& zv%ItTu5-3}kMtd9?}Sr`x`6Ta#4<-JrD}|al8;8!BcA?zOeGc;Kc+)lt&gC($V8h$ zBf~oy3b%~jo^b3FIzBVla7<(Kmk7rw6f)O5O(8{@}(<0FAsM?L+7L8nUYfBLrYUHS>G{OQ9@fXntKPY zV&$o~nlyIH;&I(R5NQ$|0*$;EE99;KaMTZ2WKB|(99aQXk>IlJ7A{-0{Xf*b1#sm| znyzVPW@hGNW-c?AnVHMXjAdqKX67>6Wp+0#=`%gsoOz)k&8?h(ONl7Uw zLivUAL@M=s?<*)!)7Z}0ES8M?oNT)LME~AHAtz8|R^Qc9?#>5`UrkzU#h~Y;^OK9N zb5JK0!x`xA4Tp7lE5Oi7r{EMcvOPuSlI0tu)w8JKkN53CShhsm7Nt2{#>xuHTrbO3 zYbVhm%w%895anjOJ^XN=E{$GTC9^r@cUWb+1gMLT_ZcZ7Py*2dR6Ephfv*U;d!ksU zb1C>uDOI%SmOo^5*j{xbZzo3$E^g-!zEb)3$%Qp5+{1y`+Xq~17QdT3Mc9K0*Z)v6 zi2P>FmC|TtFRpufO4BOBU-x8MnJ2tjNZp|KcHQPfH->GHz?Qq19atRUx;XBoL+7>B z&Ep6^V->;?okz3#6yAd)(k-;vf~0lNhW({Z>+$_AtR^>Bqp3@2AzUz8C*!?(g@Rr` z&4CMks47i~jkq82S|B{fJ-tklOSknQOV^ZTm!pcrcm>j1Kq_;hvDD<$mauWW^o(MJ zw6cFue(Rhly}#;2FboNEZdL5?? zK>pD&ikY8z8v?jGdHMO4V;++1V$+Yy(Bc{}(i?y}exp-TTnep2F-TE1sux^M@5fu+XfU$qJjy z;>^Q04%p$#zP~x8J>NQ{Iq-|ciq$lX{C zcj1=hKqg^9lvE}jf)=}xC?YnxG~zyLPe$%9W-4H1gD`zk0xLl7AVHU6{B0inL|P@8 z$lzDmiXr)_QNFW|+AbNJ#&ZyFiD^Wk0(aSn15Ki#W&J74URFB&l<;^Vg>V76%-xu$gB~E6?-c7IEP79fKYOBO*`2}1OiXrIx+ge z=O1(FBQS~1-u%Q1ok@h}w1CtQozLP%uo0bANeJ@g0_z*bEATgtzDGV_2COj4)_gZ_ z%SFW*11!(TU*JqTJ;XN%vc83aHi*uflrUiAA2m~B5>DTeA_P#BXD{#4=k6}%0x`=)#u z$;krVa3`=pXqo7p%)C+X5SUCZU2og%0b9b$bknctjqkOeMlwMxuig^bV19<(xb z%MiLIKNf9(haSOfKvj_|kQ;9{Mv;}Pl3Sk;C(*2|&m(yf_Q?N^Lz6;wNF~#bQI#%b z=ANNGG3ysPYP{*yRzA`ti;hdzmFMhS^*FdVAPkLA+G7ok(8-XDLieuqo3__QFgI7a zwi88~oIF!SE#Ev@H!S}m1va_ztE--1l=Ja9ta-cKrZ;e>wa}y@u#M)_jjG=ThSvwU zL@D^XZ(h7|`f0a9npITuhj3#bVLZm}V`@*IL!41jk1Hk9dl0|7^PKPU$la7IrT@4m5TmBd&9{mGAGn1XV4 znRpj}VSB>SdB1F~oE!IBARloXVRC)-$YE#lB0ZK`MWa2w9=m5Rr5 zEikN@$98Qt%mqTwMqz@(;g%>J4{?iVR>~1p$4+#P^c@-gvc^7?62GeNvPOj~ejP@I zzX|^;Mk4*=Cj{-JVX@94jjdNpH8iA3^Kc1YjSBlL>3iMyFG)3N59gIMb*cmIv)js| zIPS@GtKLg_0_>04LN3GwbGh%|7+w2y(|1TX_P2%~0zeXD{UM}gdcaM(^q~?9?1EQV zlu`GX-@`_+Kc=uc$grYRpccU48Ch-#0-Crf^%r|s-29{=c?XK1_`$CsE*!`GQraNK zb2c&GHL)|S2Z87!uAG64t!8>32!L|nPBZGow#YEXw^(nM`^~rlXX#pcERtC`W#!)O zM2~DZm!-dyX6XCEs&LicVo&@DYE?d1E zUpX7qhjngDCZE10J_L2zd30rBK7aYgR^ajGvj9!L+ukO~p`P{-pvVskXL{i7J_AS`z3 zAdUcakaiGtO^CxjhyU_J-6VDCq@#@VkEwW8S8Tx3Z4 zN4>q*d}H+ATSJPlvZ1O&=#70adT5S3rp9;$oRyrv`9unzvG*G({2JCV5|s zO*x;?i!PeKQ+o=kG80EytEo(}?x@;y;8inpN{IEV5g5EjU1YKCPa#ZX7UPdc<*Hnjpb}Egen$1s3 zItF-L57&l}k9*dNT>-4!pGfW%y)d`{lVaJJ5V=lp^a|nMX{auO1xm5OX%w>Z(x_Zm zc}8{Z5aItebLFkCF~zi$>xyhWuK`>EQQZ5k!@EUEBYH`R#O{_&1O7UzVwU~7F|-s@ zWv;+EA?~z>?LA&Qz<0^lp>FiNBuxMwYT9lv{st%7un9uanmYnP$W6VbraH@ObFU>x zmLfuq=SAKrN>k7>X%8E^&j~u+)*UWn`g}+`q%W9gRGZ))Dku;mA<8O!R)b+-a~&$m ztLH9AlJ6ewiBF2YBlUgN|0|%nuoYhh{jJnJmQ|4+*_QkB?YnCl=#T1zhVP>4Gh^6R zXaz&bDUSMt17WeKj%>T`T;x(iYnVmmHqqC*etzkSyMpW3J)xH1;l+r(Q)qbMJ;re1 zJXyH8tpY;!)OA-9=eKqW$>D^j9dcPmnL>|T!N45d^ zl`^x~wuaMQgIahTWA53xRKFC>jt+@#z`kh2aIdzn-C}z?O&mFX{E9lTkV)JtZ2(0x z;X1a4{Gt)f%|bOw&5dS3+s{l7cLzXz<0eL?f9H(~bC@tA%YT84mPovzCmVf=6m^>H zMGkZ53Kr$c85EV_DVM93N;$_6C!so$0Ar&;5&GpPIwk&vWUD_8$_;`Hdqj+@kuwWY9GwOO|je`wel(U8C|Asmi48K<z;M{duQx$Pp+)6{6T4iper!oIMKAL@~ z(Eka(@(VnnCMcx8PZ_Du#rnFRyq!#JXgia{gbuzjTrSWG(=CuU*RVvibamk*f_SbE zBeba@dH|o$FMan7@mhrgaBJ)z5EZUZey*ixy%B;dTejusmr{#aPZvCWiY2!n2zbdZ_JQ6~7)WCouAQNlo1ek>#gaN{h3Q3S+mrJ;(IVDIPx(mGJ(?W_ zSzF&^u>nRTAGmXASKSJ-(I# z5Oh*tzKQ<;HoRj#hDVA>Iph%JoJF?rQ=bX@nz9stW?|eXZ7;N8zYYYP9_9hsucXrm zOQc@swTxqxQ8O#TQX62-pozaSZ;44ix~*(HcyX-p@^r!$n@8OcES;n)e*YTn=WEg<4ST!? zOB9oLyyEfJ$Q`d>BPh@l&FPSB9R4B?WQI)k(+-U^U5q5!MRZmOWQ#=6nR6S6CSt*T zXnHnDk2fbp?Ke3iQ15)j#YkAY(_3D#8m@%`KI zk#MgU=#!$$_X?`L;GR;%;A1bb_l{V-#IdQEC3RS`-R93j;1068fPxd7FlRfdk zM05**`D9Om;NSN*jV`6ta@;RHOF&R_4tQL)KJ@(=sT&FW&yJSbWkN`NjHyOVGV@B^ zEDe{v(^_&%Wg-}o8Ivp&hp$_iZG{xm%&2IxV>RA&`J4lX75cElEtiB8qY%E(bD=dE zbJ;M=&0t4pwgrEobQ->|xx;uZP6*6f87i!$Dv-TtcC75rt~(M_6?KF4`6oD@X> zhD1n`!@3NR4{E-8wnZ}~?M%HjfRFeC0u%h{2TLH{`jN_SXGFwY+&<)~>^@m(1er<) zU2QBQ5ZXQY)qHlLlFu&WU5$CEw3zdB!vp&DZjK0O zwgBE*_G=)L`Uy^SWk}%)McKMH`@BnOXT5=xFkS$?yYW(f6@vIIBYBpXg6OORJ7&l)`&4^g_vMRTkrKCR`O))17LHs|QY| z^pi}^F>HT1v~$assyJ`I5;Pra8eSNdSy6XI)Kq_YAv$bJerT6EUV+#uub{`W94XjP z?~+QNH;UTFU%J00JuP~~y*AVh(`Nkm@|0RqfCrDP@Eev#kS!cg$`eSUNFSI?rF~um z`L#CQoLQ52Wx*1wYN{=C!Ll+}hp~7XREGDEnnd)rl-&B3?_)wr1ZOV)C8qVthmmFM>+kcw3nXooiExmK*S^7l`<@c5`6+; zt(?P!c{%;sUSLVzKhLMWA?HE}h>VsK zr^D~61vZI=IGo^2!(B&#=PwT#0Hl?9L`M6CS#e1+9z#vdBN!6M%Epj47+MyiB1H>Hcw zHp=BU;jox5Mtr*kLPhcj4@Ks)48!%7p9>(c9Cg(5IY2Z#*E)=c&|!LMLHwO_FH|{l zPsWhP?@D-}$Ik(xuYli!s{f_(818MG2VQ8yZixj151dfA!LKQ+5SoSx|FRZ^Ge%l}8-H(`irE%uGB;H!UmX;xCiV z3=8Itt2~emv5C%afSC#W3)zWITdo^~midd!mnF-hv6u$&MJQ`84J()9$dwDn( z+9Pj|gX;&s`-!TQJ%p*_BKApNs`Er&pq@!z!SlP1Y_G0PSv48{>6 z)~^plfW|P`KgZ1flhEoP8P-orLYBYh%Cr1OuKZtd^S}Gw{ZEZR|BvO!|JB-)g^B3% z`^S6ipBQ?6nlt`WL(jh|tp2}fjK;zGe;cE5vi#i`jpgsYqyLYM(f*e$AUtC3|3o<2 zjrGRuUwD!I?c)9+BJf`Z;;(|w{{(aYyDQ>f0>JtifWNCS|Jz=0|80}`;S{Ooc{$fQ6om!`OfxV8p@6%n2|u`276uq!zF-{SgBG zBZ$Dl&iuLhZ>9eKt$Y6a?fU;-5#c|j{<~T@nOoS<8+;lkyZ?7d|9=xnW@h5})ItET ze~Kf2%0vME?Wp`!5aFNPkAD{&=V0dgPiC8YI+8KQt@d39HE!aoew^9?LJ&kyhuOzz z35fBywYEQhkhxo%O{yDV*MD>(!;ZMM&Q+YATe!y&Iq$1!8&P5#f7h0HZy2Dr>4rMD zD(K+z<$SwJM1c_PPv&@$NNmwof={*DkP>}re7k*_-TWB8?>mYqK~bs(4APBP+g6w9 zDVzd!CDtTY9=p4rTxJmk-e!*~Y=7O$fB1xJQBY|GHY&=m^%2T-^S?d&Zj~x=Fin4B zLRUbtrv?1H_ZJw+nJiHa|Df_ch~Z-55cG?!E0$%-%|x%@!sz90G*#bmm{e*9wj9C9 zUl>TOrHyB?)RBmV+lf)-FcYna09cHq8cK$}!=^X2#c2%x$d(!OPR z2)qw7aevtcEN`ahft-h%(IH8-&%alUreuPWi|%W{f*Ve*LWaD9NI|zY#AZD(eN7xu zbbw|v!bAeS{Rxsr%xd1syd)e^bbt1w>;NAG4}R|Nkk^*91|oPGsaOi0x|t>{d?G1S zokLuVMC^GxW{v>AS{)2G#t}O1n&kfl;_C(?tw_HgUtSK#B7Bhg<^MZ¨Nea~Ly@@0ccXY-Cb6Ql6 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%0DR_y*BydlLo{o6D3(67vj^%2)W*3DYNr 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
E<$uk3^j9xREDyjj5)FyHLac(`F0czmtCe#p9 zv!`&_vX{#qp|~xDQn5h9hvyxwHyXjCmqx=(G4A3trVcl|9`>7eO|iXQ++VQrowC8) zcBFBtvC2?>o~7&BB~===@|Z&YYsAx?Al@Na2poT#gbxJ`YE$Zpl~HH&Hr; z*?kr56R|N@32&5 zm~TG_VO3GNgB+|wy#pak!CCoeC{l1sOYF8Cr`p*a_)ui-(9!u?yl5}|8H6O;G~idx zG={O8^xM8m_LEqX7+}je@~WvtsXGggM;tpv1@0!&7|@Vomnt&qF*YGQ*cr>hNzxZJ zys?`ceM7AH+HzVW^Cbrj;bF;gRX_SC8E`;lZKIP-<%2yqi|RLD&m+$M`=>}TEIW4|FXS31P*mGk0tEV#_S?N(XjckUSHUoQ^he0s{f zLvZA!5ViG;Jdwse2AMU4S;(MruPl-{Pd?amE^Z%Xfw?!F?>2PZsXr%uqlyb#tBSd7Re2oK$h_~?oi`U3hi%~T1{=9Y2fw|I(3qFAK9EY`%; zDs(FAovo@_4}5N(!^(u-$J-6mbM0avZaiO+p0goLs9Sq!HQu>5^(@#?moh?|Y5cgp zZbZ=LJBskxxyAby2_Iz3S*-4lvG<0OJYNbYUOT<1v3?CJk%hWbZzy`qyjgmFaQW0Z zl%eZOOpwLw;XqN-{X5f>U2`jv7PJDXcS<9lX>4m8Fv8LL2LvutpBG!$PTg~kNSEq8 z4}IS_+f7E|>Ed|mHt2}^`5ZxZ2v7XCA?g5R{a+7R{>{@hE;c9_@^??ycz(Rh`t#`; z@R;VuGpC$&?+usJj122J~ z+>rnC;TrJf=r8VmK3w~4FaN`LYd^;PpS@e71fKrE9%XUxLNB~Og8usA@b4q~xwtO8 zZqbSEvGL`=5kELXXO9s#-j$`MdWGcEnt}ad5iy8}K?&3e#W-u+xi0;Rt*I`sc2}RJ zjFa8Tw)T)aGp}ic!*A_XGh-)ig4AeQmcM zom%(4gJhf5H^&BJfACsy>VS+EOmHerXRq8s8HkmM&8qi~4PGxynOTFc5uPlv7M`48 zdt;^6K;0O3ttMh3(`ICQ)V*+PE(;O9zNcNjx5q==RmKOJ~!SF4>4w~HSiKc`m; zuwPYqo;hKbV;H>?Z3xzjpIitT?Eq2j*#oaVZRj|#&+T9M!?mtb-EklhAqow!hS=0>|$ zl`DxIjm@owfF=Kg_O9BgUDR7L*1bOJV)DyI0SD%duP-SPi36d|5aC3jB?6fp=EPixj2A z;i0k4sP8C-F4Fr=g!xLR!UkN8NchiuaFca?tX6t%MXt>HWC-u|Dyy9yR>{8{Mz+g_ zuc!{xn)DNWy9zHw?`3H!Rm)Glp6axh2a)rAmgiep#e z71|Mn6&v^h>cztS&e+^5*~Ew07Y$*igt9T^=$IZG{(W*CW{FLWW?FxFk?i-HZCaM3 z(b^}6{zV^GJ{^Xdl(oe}Pw6EY=a#y5zT_j9?vA{O)rA{r1;H`Adjk#1w#R8%_71o^ z75vd$3Xo}$jdVU=woapf6W@dK&k`=?O9smkZekOmlg{GeLNxA z**SmuE_Dw0tZZ3$uX#G?xlDn{q$8xwb?(8~a0QN&0tclC>d4E~*)%UwLr0OqU=eRa z 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 From d833f1a533f0c01eb034e173f812f899f85d950b Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Wed, 29 May 2024 01:40:07 +0200 Subject: [PATCH 04/18] Add files via upload --- .../HW2/Hisham_Mansour_HW2_QClass2024.ipynb | 909 ++++++++++++++++++ 1 file changed, 909 insertions(+) create mode 100644 community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb diff --git a/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb b/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb new file mode 100644 index 00000000..f3e3e17b --- /dev/null +++ b/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb @@ -0,0 +1,909 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "RyYX0oEHP7ww" + }, + "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", + "source": [ + "!pip install -U classiq" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "collapsed": true, + "id": "-xGG1F4dQFYM", + "outputId": "0d119fb0-5ddb-4067-ec41-ff1ead7d6e91" + }, + "execution_count": 1, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Collecting classiq\n", + " Downloading classiq-0.41.2-py3-none-any.whl (398 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m398.1/398.1 kB\u001b[0m \u001b[31m2.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting ConfigArgParse<2.0.0,>=1.5.3 (from classiq)\n", + " Downloading ConfigArgParse-1.7-py3-none-any.whl (25 kB)\n", + "Collecting Pyomo<6.6,>=6.5 (from classiq)\n", + " Downloading Pyomo-6.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (10.7 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m10.7/10.7 MB\u001b[0m \u001b[31m38.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting black<25.0,>=24.0 (from classiq)\n", + " Downloading black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.8/1.8 MB\u001b[0m \u001b[31m54.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting httpx<1,>=0.23.0 (from classiq)\n", + " Downloading httpx-0.27.0-py3-none-any.whl (75 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.6/75.6 kB\u001b[0m \u001b[31m5.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: keyring<24.0.0,>=23.5.0 in /usr/lib/python3/dist-packages (from classiq) (23.5.0)\n", + "Requirement already satisfied: matplotlib<4.0.0,>=3.4.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (3.7.1)\n", + "Collecting networkx<3.0.0,>=2.5.1 (from classiq)\n", + " Downloading networkx-2.8.8-py3-none-any.whl (2.0 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m67.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: numexpr<3.0.0,>=2.7.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.10.0)\n", + "Requirement already satisfied: numpy<2.0.0,>=1.20.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.25.2)\n", + "Collecting packaging<23.0,>=22.0 (from classiq)\n", + " Downloading packaging-22.0-py3-none-any.whl (42 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m42.6/42.6 kB\u001b[0m \u001b[31m2.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: pandas<3.0.0,>=1.4.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.0.3)\n", + "Requirement already satisfied: plotly<6.0.0,>=5.7.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (5.15.0)\n", + "Collecting pydantic<2.0.0,>=1.9.1 (from classiq)\n", + " Downloading pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.1/3.1 MB\u001b[0m \u001b[31m23.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: scipy<2.0.0,>=1.10.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.11.4)\n", + "Collecting sympy<1.11.0,>=1.9.0 (from classiq)\n", + " Downloading sympy-1.10.1-py3-none-any.whl (6.4 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.4/6.4 MB\u001b[0m \u001b[31m50.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: tabulate<1,>=0.8.9 in /usr/local/lib/python3.10/dist-packages (from classiq) (0.9.0)\n", + "Requirement already satisfied: click>=8.0.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (8.1.7)\n", + "Collecting mypy-extensions>=0.4.3 (from black<25.0,>=24.0->classiq)\n", + " Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n", + "Collecting pathspec>=0.9.0 (from black<25.0,>=24.0->classiq)\n", + " Downloading pathspec-0.12.1-py3-none-any.whl (31 kB)\n", + "Requirement already satisfied: platformdirs>=2 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.2.2)\n", + "Requirement already satisfied: tomli>=1.1.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (2.0.1)\n", + "Requirement already satisfied: typing-extensions>=4.0.1 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.11.0)\n", + "Requirement already satisfied: anyio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7.1)\n", + "Requirement already satisfied: certifi in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (2024.2.2)\n", + "Collecting httpcore==1.* (from httpx<1,>=0.23.0->classiq)\n", + " Downloading httpcore-1.0.5-py3-none-any.whl (77 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.9/77.9 kB\u001b[0m \u001b[31m8.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: idna in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7)\n", + "Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (1.3.1)\n", + "Collecting h11<0.15,>=0.13 (from httpcore==1.*->httpx<1,>=0.23.0->classiq)\n", + " Downloading h11-0.14.0-py3-none-any.whl (58 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m2.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.2.1)\n", + "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (0.12.1)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (4.51.0)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.4.5)\n", + "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (9.4.0)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (3.1.2)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (2.8.2)\n", + "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2023.4)\n", + "Requirement already satisfied: tzdata>=2022.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2024.1)\n", + "Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from plotly<6.0.0,>=5.7.0->classiq) (8.3.0)\n", + "Collecting ply (from Pyomo<6.6,>=6.5->classiq)\n", + " Downloading ply-3.11-py2.py3-none-any.whl (49 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.6/49.6 kB\u001b[0m \u001b[31m5.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy<1.11.0,>=1.9.0->classiq) (1.3.0)\n", + "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.7->matplotlib<4.0.0,>=3.4.3->classiq) (1.16.0)\n", + "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio->httpx<1,>=0.23.0->classiq) (1.2.1)\n", + "Installing collected packages: ply, sympy, Pyomo, pydantic, pathspec, packaging, networkx, mypy-extensions, h11, ConfigArgParse, httpcore, black, httpx, classiq\n", + " Attempting uninstall: sympy\n", + " Found existing installation: sympy 1.12\n", + " Uninstalling sympy-1.12:\n", + " Successfully uninstalled sympy-1.12\n", + " Attempting uninstall: pydantic\n", + " Found existing installation: pydantic 2.7.1\n", + " Uninstalling pydantic-2.7.1:\n", + " Successfully uninstalled pydantic-2.7.1\n", + " Attempting uninstall: packaging\n", + " Found existing installation: packaging 24.0\n", + " Uninstalling packaging-24.0:\n", + " Successfully uninstalled packaging-24.0\n", + " Attempting uninstall: networkx\n", + " Found existing installation: networkx 3.3\n", + " Uninstalling networkx-3.3:\n", + " Successfully uninstalled networkx-3.3\n", + "\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", + "torch 2.3.0+cu121 requires nvidia-cublas-cu12==12.1.3.1; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cuda-cupti-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cuda-nvrtc-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cuda-runtime-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cudnn-cu12==8.9.2.26; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cufft-cu12==11.0.2.54; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-curand-cu12==10.3.2.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cusolver-cu12==11.4.5.107; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cusparse-cu12==12.1.0.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-nccl-cu12==2.20.5; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-nvtx-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\u001b[0m\u001b[31m\n", + "\u001b[0mSuccessfully installed ConfigArgParse-1.7 Pyomo-6.5.0 black-24.4.2 classiq-0.41.2 h11-0.14.0 httpcore-1.0.5 httpx-0.27.0 mypy-extensions-1.0.0 networkx-2.8.8 packaging-22.0 pathspec-0.12.1 ply-3.11 pydantic-1.10.15 sympy-1.10.1\n" + ] + } + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "id": "30U0hh4OP7w_" + }, + "outputs": [], + "source": [ + "from classiq import *" + ] + }, + { + "cell_type": "code", + "source": [ + "import classiq\n", + "classiq.authenticate()" + ], + "metadata": { + "id": "4PRC6qblRQiF", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "14bd0a31-f7af-412f-a5a8-9f3ec1499b30" + }, + "execution_count": 3, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Your user code: DDHL-KSZZ\n", + "If a browser doesn't automatically open, please visit this URL from any trusted device: https://auth.classiq.io/activate?user_code=DDHL-KSZZ\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "uzy0m10PP7xK" + }, + "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](https://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": 4, + "metadata": { + "id": "026kr-BdP7xN" + }, + "outputs": [], + "source": [ + "@struct\n", + "class PauliTerm:\n", + " pauli: CArray[Pauli]\n", + " coefficient: CReal" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lixhso1AP7xU" + }, + "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": 5, + "metadata": { + "id": "y68mlr9iP7xY" + }, + "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": "wXd_0OOGP7xa" + }, + "source": [ + "Fill in the missing parts of the following code in order to complete this exercise:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "jP-lzZwSP7xc", + "outputId": "95cea767-0b3d-429d-e691-a5cbda601fac" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/885d568e-ba77-4d86-98c5-3f44c1b97337?version=0.41.2\n" + ] + } + ], + "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", + " evolution_coefficient=3,\n", + " repetitions=4,\n", + " order=2,\n", + " qbv=q,\n", + " )\n", + "\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XqDpPGUzP7xj" + }, + "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](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/quantum-types/#syntax).\n", + "See more on quantum expressions under [Numeric assignment](https://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": 7, + "metadata": { + "id": "ZAXVGyKGP7xm", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "24717872-2e6f-42ba-a248-a0092527101a" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/684db799-e58f-47f0-9b03-0f9b96081220?version=0.41.2\n" + ] + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "@qfunc\n", + "def main(x: Output[QNum], y: Output[QNum],z:Output[QNum],out1: Output[QNum],out2:Output[QNum],out3:Output[QNum]) -> None:\n", + "\n", + " prepare_int(2,x)\n", + " prepare_int(7,y)\n", + " prepare_int(1,z)\n", + " out1 |= (x + y)\n", + " out2 |= (x * y)\n", + " out3 |= (x * y -z)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "HKRsE0MBP7xq" + }, + "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": 45, + "metadata": { + "id": "bpYRgiU7P7xt", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "d45029ce-54ca-4eb4-a6ba-b34c7768caab" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/e5b998ac-60d9-47a3-97da-1c78281caaaa?version=0.41.2\n" + ] + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "from classiq import QBit, QArray, CArray, CReal, Output, qfunc\n", + "@qfunc\n", + "def main(res:Output[QNum], x:Output[QNum],y:Output[QNum]) -> None:\n", + "# Declare x to be a 2-qubit variable and y to be 3-qubit variable.\n", + "\n", + " # Prepare x and y\n", + " prepare_state([0.5, 0, 0.5, 0], out=x,bound= 0)\n", + " prepare_state([0, 0.25, 0.25, 0.25, 0, 0, 0.25, 0], out=y, bound=0)\n", + "\n", + " # Compute res = x + y\n", + " res |= x + y\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "fZjArRSgP7xw" + }, + "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](https://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": 46, + "metadata": { + "id": "p1-jN9k_P7xy", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "1e5cb568-6d52-441b-ea55-8006fc66e7ed" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/cfb7dd19-a0b9-4ebb-a6a8-418c89dc7c54?version=0.41.2\n" + ] + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "\n", + "\n", + "@qfunc\n", + "def add_xy(x:QNum, y:QNum, res: Output[QNum]) ->None:\n", + " res |= x + y\n", + "\n", + "\n", + "@qfunc\n", + "def main(res: Output[QNum]) -> None:\n", + " x = QNum('x')\n", + " y = QNum('y')\n", + " z = QNum('z')\n", + " prepare_int(3, x)\n", + " prepare_int(5, y)\n", + " prepare_int(2, z)\n", + "\n", + " temp = QNum('temp')\n", + " within_apply(compute= lambda: add_xy(x, y, temp),\n", + " action= lambda: add_xy(temp, z, res))\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "QlAfKwmFP7x0" + }, + "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](https://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": 47, + "metadata": { + "id": "xVdg75QGP7x4", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "cfb22e39-7a61-4593-f60b-29ff7c011039" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/5902070b-c714-426f-94e3-de96bd709fe4?version=0.41.2\n" + ] + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "qfunc\n", + "def add_ab(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", + " temp1 = QNum('temp1')\n", + " temp2 = QNum('temp2')\n", + " within_apply(compute = lambda: add_ab(temp1, x, y),\n", + " action = lambda: add_ab(temp2, temp1, z),)\n", + " res |= temp2 + 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" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "K1-qAHJwP7x6" + }, + "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": 48, + "metadata": { + "id": "ugVsWlxdP7x8", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "b161cc81-7016-4e34-8bfd-41cd5b4c6374" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/21573046-4b58-445e-b098-c01f61d6ad7f?version=0.41.2\n" + ] + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\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" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "_7sJv6NUP7x_" + }, + "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](https://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": 49, + "metadata": { + "id": "kosXeVgkP7yC", + "outputId": "cbffe019-d397-42b4-b0df-45898902c57b", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/3e37cec3-38bf-44ff-839d-78ca1492254d?version=0.41.2\n" + ] + } + ], + "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": "N7uymloXP7yG" + }, + "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": 50, + "metadata": { + "id": "O4GYaZhhP7yI", + "outputId": "b573b2a3-5337-475e-f720-e5ec59e8a6db", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/85c0ddf4-b334-4146-9e62-22d4700020a9?version=0.41.2\n" + ] + } + ], + "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)) # 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": "Q8Xs_UXuP7yK" + }, + "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": 51, + "metadata": { + "id": "LfhqxNYCP7yN", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "c4c34c5f-4c97-4222-a7d1-35d537c09edb" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/895a5345-9c5a-4282-b996-fc60e830e614?version=0.41.2\n" + ] + } + ], + "source": [ + "from classiq import *\n", + "from classiq.qmod.symbolic import sqrt\n", + "\n", + "prob_list= [\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " -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", + "\n", + "# Your code here:\n", + "\n", + "@qfunc\n", + "def main(res: Output[QArray[QBit]]) -> None:\n", + " '''\n", + " x: QArray[QBit] = QArray(\"x\")\n", + "\n", + " allocate(3, x)\n", + " hadamard_transform(x)\n", + "\n", + " lsb = QBit(\"lsb\")\n", + " msb = QNum(\"msb\", 2, False, 0)\n", + "\n", + " bind(x, [lsb, msb])\n", + "\n", + " control(msb == 0, lambda: RY(pi / 3, lsb))\n", + " # msb==1 <==> bit1 bit2 == 01 (binary of decimal 1)\n", + "\n", + " bind([lsb, msb], res)\n", + " '''\n", + " pre_prepared_state(res)\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + }, + "colab": { + "provenance": [] + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file From 858ca06d813a87ad613bb4cfb20bf4b0f89ad01b Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Mon, 3 Jun 2024 04:27:20 +0200 Subject: [PATCH 05/18] Create HW3 --- community/QClass_2024/Submissions/HW3 | 1 + 1 file changed, 1 insertion(+) create mode 100644 community/QClass_2024/Submissions/HW3 diff --git a/community/QClass_2024/Submissions/HW3 b/community/QClass_2024/Submissions/HW3 new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/community/QClass_2024/Submissions/HW3 @@ -0,0 +1 @@ + From bbb4e906e40611af21e27deed6cf05c2dcb8bb50 Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Mon, 3 Jun 2024 04:28:00 +0200 Subject: [PATCH 06/18] Delete community/QClass_2024/Submissions/HW3 --- community/QClass_2024/Submissions/HW3 | 1 - 1 file changed, 1 deletion(-) delete mode 100644 community/QClass_2024/Submissions/HW3 diff --git a/community/QClass_2024/Submissions/HW3 b/community/QClass_2024/Submissions/HW3 deleted file mode 100644 index 8b137891..00000000 --- a/community/QClass_2024/Submissions/HW3 +++ /dev/null @@ -1 +0,0 @@ - From f9517fd050881f5e9e90e9ff871d0c6f333656da Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Mon, 3 Jun 2024 04:31:31 +0200 Subject: [PATCH 07/18] Create A.txt --- community/QClass_2024/Submissions/HW3/A.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 community/QClass_2024/Submissions/HW3/A.txt diff --git a/community/QClass_2024/Submissions/HW3/A.txt b/community/QClass_2024/Submissions/HW3/A.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/community/QClass_2024/Submissions/HW3/A.txt @@ -0,0 +1 @@ + From 50d698eb13b2a1007a74e715a30b9c9df52fd25f Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Mon, 3 Jun 2024 04:32:16 +0200 Subject: [PATCH 08/18] Add files via upload --- .../HW3/Hisham_Mansour_HW3_VQE.ipynb | 497 ++++++++++++++++++ 1 file changed, 497 insertions(+) create mode 100644 community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb diff --git a/community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb b/community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb new file mode 100644 index 00000000..a904dd5a --- /dev/null +++ b/community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb @@ -0,0 +1,497 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fc72d98f-8993-4bd4-a545-23d122f3df71", + "metadata": { + "id": "fc72d98f-8993-4bd4-a545-23d122f3df71" + }, + "source": [ + "# 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." + ] + }, + { + "cell_type": "markdown", + "id": "56eda6d8-76c4-4862-b914-0c4598d67274", + "metadata": { + "id": "56eda6d8-76c4-4862-b914-0c4598d67274" + }, + "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", + "\n", + "## Additional Resources\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", + "\n", + "---\n", + "\n", + "Happy coding and good luck!" + ] + }, + { + "cell_type": "markdown", + "id": "d41e969d-f6a7-4ff7-9660-19ce6c97ba6b", + "metadata": { + "id": "d41e969d-f6a7-4ff7-9660-19ce6c97ba6b" + }, + "source": [ + "### Part 1" + ] + }, + { + "cell_type": "markdown", + "id": "f710d6f4-d40b-42d5-b524-c6acb8059fe2", + "metadata": { + "id": "f710d6f4-d40b-42d5-b524-c6acb8059fe2" + }, + "source": [ + "Given the following Hamiltonian:" + ] + }, + { + "cell_type": "markdown", + "id": "6ba8a6f1-3259-4492-a1ca-3abde7530cd4", + "metadata": { + "id": "6ba8a6f1-3259-4492-a1ca-3abde7530cd4" + }, + "source": [ + "$$\n", + "\\hat{H} = -1.0523 \\cdot (I \\otimes I) + 0.3979 \\cdot (I \\otimes Z) - 0.3979 \\cdot (Z \\otimes I) - 0.0112 \\cdot (Z \\otimes Z) + 0.1809 \\cdot (X \\otimes X)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "id": "736d275c-9a5a-4c08-b891-3078430dc6c1", + "metadata": { + "id": "736d275c-9a5a-4c08-b891-3078430dc6c1" + }, + "source": [ + "Complete the following code" + ] + }, + { + "cell_type": "code", + "source": [ + "!pip install -U classiq" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "collapsed": true, + "id": "DQOxbZxjrN5r", + "outputId": "ba3dffa0-ff88-4a89-b76f-a0bd6c05f164" + }, + "id": "DQOxbZxjrN5r", + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Collecting classiq\n", + " Downloading classiq-0.42.0-py3-none-any.whl (401 kB)\n", + "\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/401.5 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[91m━━━━━━━━━━━━━━\u001b[0m\u001b[90m╺\u001b[0m\u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m143.4/401.5 kB\u001b[0m \u001b[31m4.2 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m401.5/401.5 kB\u001b[0m \u001b[31m6.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting ConfigArgParse<2.0.0,>=1.5.3 (from classiq)\n", + " Downloading ConfigArgParse-1.7-py3-none-any.whl (25 kB)\n", + "Collecting Pyomo<6.6,>=6.5 (from classiq)\n", + " Downloading Pyomo-6.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (10.7 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m10.7/10.7 MB\u001b[0m \u001b[31m31.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting black<25.0,>=24.0 (from classiq)\n", + " Downloading black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.8/1.8 MB\u001b[0m \u001b[31m22.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting httpx<1,>=0.23.0 (from classiq)\n", + " Downloading httpx-0.27.0-py3-none-any.whl (75 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.6/75.6 kB\u001b[0m \u001b[31m5.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: keyring<24.0.0,>=23.5.0 in /usr/lib/python3/dist-packages (from classiq) (23.5.0)\n", + "Requirement already satisfied: matplotlib<4.0.0,>=3.4.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (3.7.1)\n", + "Collecting networkx<3.0.0,>=2.5.1 (from classiq)\n", + " Downloading networkx-2.8.8-py3-none-any.whl (2.0 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m50.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: numexpr<3.0.0,>=2.7.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.10.0)\n", + "Requirement already satisfied: numpy<2.0.0,>=1.20.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.25.2)\n", + "Collecting packaging<23.0,>=22.0 (from classiq)\n", + " Downloading packaging-22.0-py3-none-any.whl (42 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m42.6/42.6 kB\u001b[0m \u001b[31m2.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: pandas<3.0.0,>=1.4.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.0.3)\n", + "Requirement already satisfied: plotly<6.0.0,>=5.7.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (5.15.0)\n", + "Collecting pydantic<2.0.0,>=1.9.1 (from classiq)\n", + " Downloading pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.1/3.1 MB\u001b[0m \u001b[31m48.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: scipy<2.0.0,>=1.10.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.11.4)\n", + "Collecting sympy<1.11.0,>=1.9.0 (from classiq)\n", + " Downloading sympy-1.10.1-py3-none-any.whl (6.4 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.4/6.4 MB\u001b[0m \u001b[31m54.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: tabulate<1,>=0.8.9 in /usr/local/lib/python3.10/dist-packages (from classiq) (0.9.0)\n", + "Requirement already satisfied: click>=8.0.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (8.1.7)\n", + "Collecting mypy-extensions>=0.4.3 (from black<25.0,>=24.0->classiq)\n", + " Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n", + "Collecting pathspec>=0.9.0 (from black<25.0,>=24.0->classiq)\n", + " Downloading pathspec-0.12.1-py3-none-any.whl (31 kB)\n", + "Requirement already satisfied: platformdirs>=2 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.2.2)\n", + "Requirement already satisfied: tomli>=1.1.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (2.0.1)\n", + "Requirement already satisfied: typing-extensions>=4.0.1 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.11.0)\n", + "Requirement already satisfied: anyio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7.1)\n", + "Requirement already satisfied: certifi in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (2024.2.2)\n", + "Collecting httpcore==1.* (from httpx<1,>=0.23.0->classiq)\n", + " Downloading httpcore-1.0.5-py3-none-any.whl (77 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.9/77.9 kB\u001b[0m \u001b[31m4.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: idna in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7)\n", + "Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (1.3.1)\n", + "Collecting h11<0.15,>=0.13 (from httpcore==1.*->httpx<1,>=0.23.0->classiq)\n", + " Downloading h11-0.14.0-py3-none-any.whl (58 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m3.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.2.1)\n", + "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (0.12.1)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (4.51.0)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.4.5)\n", + "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (9.4.0)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (3.1.2)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (2.8.2)\n", + "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2023.4)\n", + "Requirement already satisfied: tzdata>=2022.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2024.1)\n", + "Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from plotly<6.0.0,>=5.7.0->classiq) (8.3.0)\n", + "Collecting ply (from Pyomo<6.6,>=6.5->classiq)\n", + " Downloading ply-3.11-py2.py3-none-any.whl (49 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.6/49.6 kB\u001b[0m \u001b[31m734.3 kB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy<1.11.0,>=1.9.0->classiq) (1.3.0)\n", + "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.7->matplotlib<4.0.0,>=3.4.3->classiq) (1.16.0)\n", + "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio->httpx<1,>=0.23.0->classiq) (1.2.1)\n", + "Installing collected packages: ply, sympy, Pyomo, pydantic, pathspec, packaging, networkx, mypy-extensions, h11, ConfigArgParse, httpcore, black, httpx, classiq\n", + " Attempting uninstall: sympy\n", + " Found existing installation: sympy 1.12\n", + " Uninstalling sympy-1.12:\n", + " Successfully uninstalled sympy-1.12\n", + " Attempting uninstall: pydantic\n", + " Found existing installation: pydantic 2.7.1\n", + " Uninstalling pydantic-2.7.1:\n", + " Successfully uninstalled pydantic-2.7.1\n", + " Attempting uninstall: packaging\n", + " Found existing installation: packaging 24.0\n", + " Uninstalling packaging-24.0:\n", + " Successfully uninstalled packaging-24.0\n", + " Attempting uninstall: networkx\n", + " Found existing installation: networkx 3.3\n", + " Uninstalling networkx-3.3:\n", + " Successfully uninstalled networkx-3.3\n", + "\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", + "torch 2.3.0+cu121 requires nvidia-cublas-cu12==12.1.3.1; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cuda-cupti-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cuda-nvrtc-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cuda-runtime-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cudnn-cu12==8.9.2.26; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cufft-cu12==11.0.2.54; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-curand-cu12==10.3.2.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cusolver-cu12==11.4.5.107; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cusparse-cu12==12.1.0.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-nccl-cu12==2.20.5; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-nvtx-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\u001b[0m\u001b[31m\n", + "\u001b[0mSuccessfully installed ConfigArgParse-1.7 Pyomo-6.5.0 black-24.4.2 classiq-0.42.0 h11-0.14.0 httpcore-1.0.5 httpx-0.27.0 mypy-extensions-1.0.0 networkx-2.8.8 packaging-22.0 pathspec-0.12.1 ply-3.11 pydantic-1.10.15 sympy-1.10.1\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "import classiq\n", + "classiq.authenticate()" + ], + "metadata": { + "id": "jLanwByIe4eJ", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "dea1c702-533c-492a-f2c7-4406c6fdb7f0" + }, + "id": "jLanwByIe4eJ", + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Your user code: LSSS-MJFD\n", + "If a browser doesn't automatically open, please visit this URL from any trusted device: https://auth.classiq.io/activate?user_code=LSSS-MJFD\n" + ] + } + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "19266c11-6acc-4edb-910f-2d0dfe80a6c8", + "metadata": { + "id": "19266c11-6acc-4edb-910f-2d0dfe80a6c8" + }, + "outputs": [], + "source": [ + "from typing import List\n", + "from classiq import *\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", + "])" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "0bb68899-2076-45c0-8868-131f38aa3b78", + "metadata": { + "id": "0bb68899-2076-45c0-8868-131f38aa3b78" + }, + "outputs": [], + "source": [ + "@qfunc\n", + "def main(q: Output[QArray[QBit]], angles: CArray[CReal, 3]) -> None:\n", + " # TODO: Create an ansatz which allows each qubit to have\n", + " # arbitrary rotation\n", + " allocate(2, q)\n", + "\n", + " U(angles[0], angles[1], angles[2], 0, q[0])\n", + " U(angles[0], angles[1], angles[2], 0, q[1])\n", + "\n", + "@cfunc\n", + "def cmain() -> None:\n", + " res = vqe(\n", + " hamiltonian=HAMILTONIAN,\n", + " maximize=False,\n", + " initial_point=[],\n", + " optimizer=Optimizer.COBYLA,\n", + " max_iteration=1000,\n", + " tolerance=0.001,\n", + " step_size=0,\n", + " skip_compute_variance=False,\n", + " alpha_cvar=1.0,\n", + " )\n", + " save({\"result\": res})\n", + "\n", + "#TODO: complete the line, use classical_execution_function\n", + "qmod = create_model(main, classical_execution_function=cmain)\n", + "\n", + "qprog = synthesize(qmod)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "0563c1a8-7aec-4da9-9105-6b16c5c24382", + "metadata": { + "id": "0563c1a8-7aec-4da9-9105-6b16c5c24382" + }, + "outputs": [], + "source": [ + "execution = execute(qprog)\n", + "res = execution.result()\n", + "# execution.open_in_ide()\n", + "vqe_result = res[0].value\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "de17cfc0-8e64-4493-b4c2-4a97fc9797a0", + "metadata": { + "scrolled": true, + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "de17cfc0-8e64-4493-b4c2-4a97fc9797a0", + "outputId": "5b400695-8faf-4aae-e8b8-bdc477e211e1" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Optimal energy: -1.0546669921875\n", + "Optimal parameters: {'angles_0': 6.279238566143106, 'angles_1': -0.7105268722399182, 'angles_2': 4.394957787844692}\n", + "Eigenstate: {'00': (1+0j)}\n" + ] + } + ], + "source": [ + "print(f\"Optimal energy: {vqe_result.energy}\")\n", + "print(f\"Optimal parameters: {vqe_result.optimal_parameters}\")\n", + "print(f\"Eigenstate: {vqe_result.eigenstate}\")" + ] + }, + { + "cell_type": "markdown", + "id": "5df11dfc-3e3a-4191-bd47-d522ca3dcbfa", + "metadata": { + "id": "5df11dfc-3e3a-4191-bd47-d522ca3dcbfa" + }, + "source": [ + "Does it similar to the `optimal energy` we calculated in class? \\\n", + "Does it similar to the `total energy` we calculated in class?" + ] + }, + { + "cell_type": "markdown", + "id": "4f0e0bea-b12f-43ad-94e8-100fedf2b57f", + "metadata": { + "id": "4f0e0bea-b12f-43ad-94e8-100fedf2b57f" + }, + "source": [ + "### Part 2" + ] + }, + { + "cell_type": "markdown", + "id": "66882248-de08-4a6e-b33c-647f015f7d79", + "metadata": { + "id": "66882248-de08-4a6e-b33c-647f015f7d79" + }, + "source": [ + "**Now, we want to have a more interesting ansatz in our `main`.** \n", + "Add **one** line of code to the `main` function you created in Part 1 that creates **entanglement** between the two qubits. \n", + "Which gate should you use?" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "bb39be9e-4994-44e5-84d8-c99bc8b77145", + "metadata": { + "id": "bb39be9e-4994-44e5-84d8-c99bc8b77145" + }, + "outputs": [], + "source": [ + "@qfunc\n", + "def main(q: Output[QArray[QBit]], angles: CArray[CReal, 3]) -> None:\n", + " # TODO: Create an ansatz which allows each qubit to have\n", + " # arbitrary rotation\n", + " allocate(2, q)\n", + "\n", + " U(angles[0], angles[1], angles[2], 0, q[0])\n", + " U(angles[0], angles[1], angles[2], 0, q[1])\n", + "\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", + " False,\n", + " [],\n", + " optimizer=Optimizer.COBYLA,\n", + " max_iteration=1000,\n", + " tolerance=0.001,\n", + " step_size=0,\n", + " skip_compute_variance=False,\n", + " alpha_cvar=1.0,\n", + " )\n", + " save({\"result\": res})\n", + "\n", + "#TODO: complete the line, use classical_execution_function\n", + "qmod = create_model(main, classical_execution_function=cmain)\n", + "\n", + "qprog = synthesize(qmod)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "112a1590-283c-4f79-8035-72936561102d", + "metadata": { + "id": "112a1590-283c-4f79-8035-72936561102d" + }, + "outputs": [], + "source": [ + "execution = execute(qprog)\n", + "res = execution.result()\n", + "# execution.open_in_ide()\n", + "vqe_result = res[0].value\n" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "06500e4c-a04b-4cfa-a84d-41f96a0c68eb", + "metadata": { + "collapsed": true, + "jupyter": { + "outputs_hidden": true + }, + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "06500e4c-a04b-4cfa-a84d-41f96a0c68eb", + "outputId": "c406023c-627c-468c-d48c-cddf2d234297" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Optimal energy: -1.84395341796875\n", + "Optimal parameters: {'angles_0': 3.220640081190124, 'angles_1': 0.48857020981030813, 'angles_2': 1.69265245066969}\n", + "Eigenstate: {'10': (0.03125+0j), '11': (0.03125+0j), '01': (0.9990229601966113+0j)}\n" + ] + } + ], + "source": [ + "print(f\"Optimal energy: {vqe_result.energy}\")\n", + "print(f\"Optimal parameters: {vqe_result.optimal_parameters}\")\n", + "print(f\"Eigenstate: {vqe_result.eigenstate}\")" + ] + }, + { + "cell_type": "markdown", + "id": "30a635d7-2f15-4c94-a94b-f4270f17aed8", + "metadata": { + "id": "30a635d7-2f15-4c94-a94b-f4270f17aed8" + }, + "source": [ + "Does it similar to the `optimal energy` we calculated in class? \\\n", + "Does it similar to the `total energy` we calculated in class? \\\n", + "What can we learn about the provided form this result Hamiltonian?" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.16" + }, + "colab": { + "provenance": [] + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file From fc3b1c6a6dc0e9f741294d6d7f6a4de8dd553227 Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Mon, 3 Jun 2024 04:33:50 +0200 Subject: [PATCH 09/18] Delete community/QClass_2024/Submissions/HW3/A.txt --- community/QClass_2024/Submissions/HW3/A.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 community/QClass_2024/Submissions/HW3/A.txt diff --git a/community/QClass_2024/Submissions/HW3/A.txt b/community/QClass_2024/Submissions/HW3/A.txt deleted file mode 100644 index 8b137891..00000000 --- a/community/QClass_2024/Submissions/HW3/A.txt +++ /dev/null @@ -1 +0,0 @@ - From 1d4e7d020bf129bca3e33632a4255b538107b28d Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Mon, 10 Jun 2024 05:29:09 +0200 Subject: [PATCH 10/18] Created using Colab --- ...Hisham_Mansour_HW4_qpe_for_molecules.ipynb | 1786 +++++++++++++++++ 1 file changed, 1786 insertions(+) create mode 100644 community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb diff --git a/community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb b/community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb new file mode 100644 index 00000000..81409e9b --- /dev/null +++ b/community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb @@ -0,0 +1,1786 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "view-in-github", + "colab_type": "text" + }, + "source": [ + "\"Open" + ] + }, + { + "cell_type": "markdown", + "id": "75e2c1fe-8a06-4f0b-8fd6-d1b6d10ce82f", + "metadata": { + "id": "75e2c1fe-8a06-4f0b-8fd6-d1b6d10ce82f" + }, + "source": [ + "# Quantum Phase Estimation (QPE) for Solving Molecular Energies\n", + "\n", + "\n", + "Quantum Phase Estimation (QPE) is a key algorithm in quantum computing, allowing one to estimate the phase (or eigenvalue) of an eigenvector of a unitary operation. The algorithm is designed so, that for a given Hamiltonian $H$, and an eigenvalue ${|\\psi\\rangle}$, the output that will be obtained is $\\epsilon$ where\n", + "\n", + "$U{|\\psi\\rangle} = e^{2\\pi i\\epsilon}{|\\psi\\rangle} , U = e^{2\\pi iH}$ .\n", + "\n", + "\n", + "Therefore, by measuring the phase accumulated, the QPE algorithm allows calculating the energies relating to the chosen initial state.\n", + "When using QPE for chemistry problems, it is common to search for the lowest energy of a given molecule. As the molecule can be written in the form of a Hamiltonian (Hermitian matrix which meaning is the energetic forces of the structure), usually symbolized by \"H\", one only need to insert the ground eigenvector in order to obtain the minimal energy value using QPE. However, obtaining the ground state is not a trivial problem. In order to overcome it, it is sufficient to use a state with big overlap with the ground state.\n", + "\n", + "We define a state ${|v\\rangle}$ which will be chosen as the algorithm's initial state. Let us define {$\\psi_i$} to be the set of (unknown) eigenvalues of $H$. Generally, any vector can be rewritten as a superposition of any basis set, thus -\n", + "\n", + "${|v\\rangle} = \\sum_i a_i{|\\psi_i\\rangle}$\n", + "\n", + "and -\n", + "\n", + "$U{|v\\rangle} = \\sum_i a_i e^{2\\pi i\\epsilon_i}{|\\psi_i\\rangle}$.\n", + "\n", + "where ${\\epsilon_i}$ are the eigenvalues of H, i.e. the span of energies relating to the molecule. Using execution with enough shots, one will obtain this set of $\\theta_i$, i.e., a subset of the Hamiltonian's eigenvalues. As we are specifically interested in $\\epsilon_0$, the ground state of H, it is important that there is a large overlap between ${\\psi_0}$ and ${|v\\rangle}$ so the probability to measure ${\\epsilon_0}$ is high, i.e.\n", + "\n", + "$P(\\epsilon_0) = |\\langle v|\\psi_0\\rangle|^2 > \\epsilon $.\n", + "\n", + "How large is $\\epsilon$? After execution, we will obtain a set of ${E_i}$.\n", + "If we have done 1000 shots of execution, and $P(\\epsilon_0)>1$, it should be measured is about 10 times to get a good statistical variance.\n", + "\n", + "A common choice for ${|v\\rangle}$ (the initial state) is the Hartree-Fock (HF) state, which with good probability have a large overlap with the ground state. However, other guesses for the initial state are possibly good or even better fit, and choosing the right initial state is a sort of art and an active field of research.\n", + "\n", + "For further reading about QPE we recommend [[1](#NC)].\n", + "\n", + "\n", + "#### What are the benefits of using QPE algorithm for finding a molecule's ground state?\n", + "\n", + "The two most prominent methods to solve ground energy for molecules are quantum variational algorithm (VQE) and QPE. Those promise better scalability compared to classical counterparts as the molecules becomes more complex, with larger number of electrons manifesting as more degrees of freedom for the problem.\n", + "\n", + "While so, the number of parameters in VQE is closely related to the number of electrons. This may create inherent difficulty achieving high-precision calculations through sampling statistical estimators, and paraphs even not converge for very large systems. While so, the number of parameters in QPE is a flexible value which is directly related to the resolution of the problem, but is not bonded with the number of electrons.\n", + "\n", + "Furthermore, it is known that advanced quantum algorithms based on QPE can perform electronic structure calculations in sub-exponential time with accuracy that rivals exact diagonalization methods. This guarantee of simultaneously achieving high accuracy, efficiency, and generality is a feat that is believed to be impossible for classical algorithms. For those reasons, VQE is applicable in the near term (NISQ) era, while QPE is suited for fault-tolerant design.\n", + "\n", + "#### During this tutorial, we will follow the QPE algorithms steps as following:\n", + "\n", + "a. Define a molecule and convert it into a Hamiltonian H, manifested as a pauli list.\n", + "\n", + "b. Prepare the Hamiltonian for QPE: including normalization and choosing the resolution.\n", + "\n", + "c. Initializing the state for the HF state.\n", + "\n", + "d. Preparing the quantum circuit.\n", + "\n", + "e. Executing the circuit to find the related phases and analyzing the results to find the ground state.\n", + "\n", + "f. Comparing the QPE results with exact solution for the molecule’s ground state." + ] + }, + { + "cell_type": "markdown", + "id": "7cd71faa-1ef3-4d67-8c9a-d66e0a895b9a", + "metadata": { + "id": "7cd71faa-1ef3-4d67-8c9a-d66e0a895b9a" + }, + "source": [ + "## 0. Pre-requirments\n", + "\n", + "The model is using several Classiq's libraries in addition to IBM's simulating tool." + ] + }, + { + "cell_type": "code", + "source": [ + "!pip install -U classiq" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "k3DQRV9GpPSG", + "outputId": "4039a7c0-2b12-4e86-d14a-455090db8a57", + "collapsed": true + }, + "id": "k3DQRV9GpPSG", + "execution_count": 1, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Collecting classiq\n", + " Downloading classiq-0.42.1-py3-none-any.whl (401 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m401.5/401.5 kB\u001b[0m \u001b[31m5.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting ConfigArgParse<2.0.0,>=1.5.3 (from classiq)\n", + " Downloading ConfigArgParse-1.7-py3-none-any.whl (25 kB)\n", + "Collecting Pyomo<6.6,>=6.5 (from classiq)\n", + " Downloading Pyomo-6.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (10.7 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m10.7/10.7 MB\u001b[0m \u001b[31m32.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting black<25.0,>=24.0 (from classiq)\n", + " Downloading black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.8/1.8 MB\u001b[0m \u001b[31m45.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hCollecting httpx<1,>=0.23.0 (from classiq)\n", + " Downloading httpx-0.27.0-py3-none-any.whl (75 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.6/75.6 kB\u001b[0m \u001b[31m7.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: keyring<24.0.0,>=23.5.0 in /usr/lib/python3/dist-packages (from classiq) (23.5.0)\n", + "Requirement already satisfied: matplotlib<4.0.0,>=3.4.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (3.7.1)\n", + "Collecting networkx<3.0.0,>=2.5.1 (from classiq)\n", + " Downloading networkx-2.8.8-py3-none-any.whl (2.0 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m43.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: numexpr<3.0.0,>=2.7.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.10.0)\n", + "Requirement already satisfied: numpy<2.0.0,>=1.20.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.25.2)\n", + "Collecting packaging<23.0,>=22.0 (from classiq)\n", + " Downloading packaging-22.0-py3-none-any.whl (42 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m42.6/42.6 kB\u001b[0m \u001b[31m3.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: pandas<3.0.0,>=1.4.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.0.3)\n", + "Requirement already satisfied: plotly<6.0.0,>=5.7.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (5.15.0)\n", + "Collecting pydantic<2.0.0,>=1.9.1 (from classiq)\n", + " Downloading pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.1/3.1 MB\u001b[0m \u001b[31m33.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: scipy<2.0.0,>=1.10.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.11.4)\n", + "Collecting sympy<1.11.0,>=1.9.0 (from classiq)\n", + " Downloading sympy-1.10.1-py3-none-any.whl (6.4 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.4/6.4 MB\u001b[0m \u001b[31m21.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: tabulate<1,>=0.8.9 in /usr/local/lib/python3.10/dist-packages (from classiq) (0.9.0)\n", + "Requirement already satisfied: click>=8.0.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (8.1.7)\n", + "Collecting mypy-extensions>=0.4.3 (from black<25.0,>=24.0->classiq)\n", + " Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n", + "Collecting pathspec>=0.9.0 (from black<25.0,>=24.0->classiq)\n", + " Downloading pathspec-0.12.1-py3-none-any.whl (31 kB)\n", + "Requirement already satisfied: platformdirs>=2 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.2.2)\n", + "Requirement already satisfied: tomli>=1.1.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (2.0.1)\n", + "Requirement already satisfied: typing-extensions>=4.0.1 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.12.1)\n", + "Requirement already satisfied: anyio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7.1)\n", + "Requirement already satisfied: certifi in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (2024.6.2)\n", + "Collecting httpcore==1.* (from httpx<1,>=0.23.0->classiq)\n", + " Downloading httpcore-1.0.5-py3-none-any.whl (77 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.9/77.9 kB\u001b[0m \u001b[31m3.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: idna in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7)\n", + "Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (1.3.1)\n", + "Collecting h11<0.15,>=0.13 (from httpcore==1.*->httpx<1,>=0.23.0->classiq)\n", + " Downloading h11-0.14.0-py3-none-any.whl (58 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m2.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.2.1)\n", + "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (0.12.1)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (4.53.0)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.4.5)\n", + "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (9.4.0)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (3.1.2)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (2.8.2)\n", + "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2023.4)\n", + "Requirement already satisfied: tzdata>=2022.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2024.1)\n", + "Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from plotly<6.0.0,>=5.7.0->classiq) (8.3.0)\n", + "Collecting ply (from Pyomo<6.6,>=6.5->classiq)\n", + " Downloading ply-3.11-py2.py3-none-any.whl (49 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.6/49.6 kB\u001b[0m \u001b[31m3.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy<1.11.0,>=1.9.0->classiq) (1.3.0)\n", + "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.7->matplotlib<4.0.0,>=3.4.3->classiq) (1.16.0)\n", + "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio->httpx<1,>=0.23.0->classiq) (1.2.1)\n", + "Installing collected packages: ply, sympy, Pyomo, pydantic, pathspec, packaging, networkx, mypy-extensions, h11, ConfigArgParse, httpcore, black, httpx, classiq\n", + " Attempting uninstall: sympy\n", + " Found existing installation: sympy 1.12.1\n", + " Uninstalling sympy-1.12.1:\n", + " Successfully uninstalled sympy-1.12.1\n", + " Attempting uninstall: pydantic\n", + " Found existing installation: pydantic 2.7.3\n", + " Uninstalling pydantic-2.7.3:\n", + " Successfully uninstalled pydantic-2.7.3\n", + " Attempting uninstall: packaging\n", + " Found existing installation: packaging 24.0\n", + " Uninstalling packaging-24.0:\n", + " Successfully uninstalled packaging-24.0\n", + " Attempting uninstall: networkx\n", + " Found existing installation: networkx 3.3\n", + " Uninstalling networkx-3.3:\n", + " Successfully uninstalled networkx-3.3\n", + "\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", + "torch 2.3.0+cu121 requires nvidia-cublas-cu12==12.1.3.1; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cuda-cupti-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cuda-nvrtc-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cuda-runtime-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cudnn-cu12==8.9.2.26; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cufft-cu12==11.0.2.54; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-curand-cu12==10.3.2.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cusolver-cu12==11.4.5.107; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-cusparse-cu12==12.1.0.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-nccl-cu12==2.20.5; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", + "torch 2.3.0+cu121 requires nvidia-nvtx-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\u001b[0m\u001b[31m\n", + "\u001b[0mSuccessfully installed ConfigArgParse-1.7 Pyomo-6.5.0 black-24.4.2 classiq-0.42.1 h11-0.14.0 httpcore-1.0.5 httpx-0.27.0 mypy-extensions-1.0.0 networkx-2.8.8 packaging-22.0 pathspec-0.12.1 ply-3.11 pydantic-1.10.15 sympy-1.10.1\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "import classiq\n", + "classiq.authenticate()" + ], + "metadata": { + "id": "Nsm3pKlqpZpr", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "outputId": "c7a6175b-bfa2-4b6a-f067-36f48d33d94c" + }, + "id": "Nsm3pKlqpZpr", + "execution_count": 2, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Your user code: TJLL-VDWQ\n", + "If a browser doesn't automatically open, please visit this URL from any trusted device: https://auth.classiq.io/activate?user_code=TJLL-VDWQ\n" + ] + } + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "11eaf8f8-c06e-443e-ac74-5aa364f5198c", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:36.283533Z", + "iopub.status.busy": "2024-05-07T15:16:36.283079Z", + "iopub.status.idle": "2024-05-07T15:16:39.275433Z", + "shell.execute_reply": "2024-05-07T15:16:39.274629Z" + }, + "tags": [], + "id": "11eaf8f8-c06e-443e-ac74-5aa364f5198c" + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import scipy\n", + "from numpy import linalg as LA\n", + "\n", + "# for state preperation and phase estimation\n", + "from classiq import Constraints, Preferences\n", + "\n", + "# for chemistry\n", + "from classiq.applications.chemistry import Molecule, MoleculeProblem, PauliOperator" + ] + }, + { + "cell_type": "markdown", + "id": "ac537458-568d-4718-9020-408cc7232641", + "metadata": { + "id": "ac537458-568d-4718-9020-408cc7232641" + }, + "source": [ + "## 1. Create Your Molecule" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### XYZ cartesian coordinates" + ], + "metadata": { + "id": "WC3NKxILHo6H" + }, + "id": "WC3NKxILHo6H" + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2b67b2e1-94c2-4c8f-8ee9-577c79a7234f", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:39.279850Z", + "iopub.status.busy": "2024-05-07T15:16:39.279309Z", + "iopub.status.idle": "2024-05-07T15:16:39.288752Z", + "shell.execute_reply": "2024-05-07T15:16:39.288033Z" + }, + "tags": [], + "id": "2b67b2e1-94c2-4c8f-8ee9-577c79a7234f" + }, + "outputs": [], + "source": [ + "# build your molecule\n", + "\n", + "#hydrogen\n", + "molecule_H2 = Molecule(atoms=[(\"H\", (0.0, 0.0, 0)), (\"H\", (0.0, 0.0, 0.735))])\n", + "#oxygen\n", + "molecule_O2 = Molecule(atoms=[(\"O\", (0.0, 0.0, 0)), (\"O\", (0.0, 0.0, 1.16))])\n", + "#lithium hydride\n", + "molecule_LiH = Molecule(atoms=[(\"H\", (0.0, 0.0, 0.0)), (\"Li\", (0.0, 0.0, 1.596))])\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", + "#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", + "#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", + "#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))])" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "9e37fada-9ecc-4a24-bf2c-0994e9c14149", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:39.293443Z", + "iopub.status.busy": "2024-05-07T15:16:39.292243Z", + "iopub.status.idle": "2024-05-07T15:16:39.297244Z", + "shell.execute_reply": "2024-05-07T15:16:39.296486Z" + }, + "tags": [], + "id": "9e37fada-9ecc-4a24-bf2c-0994e9c14149" + }, + "outputs": [], + "source": [ + "# define your molecule\n", + "#molecule = molecule_H2\n", + "#molecule = molecule_O2\n", + "#molecule = molecule_LiH\n", + "\n", + "molecule = molecule_BeH2\n", + "\n", + "#molecule = molecule_H2O\n", + "\n", + "#molecule = molecule_CO2\n", + "# The exponentiation constraints are not satisfiable.\n", + "# Minimal max_depth is 36476.\n", + "#molecule = molecule_CH3Cl\n", + "# The exponentiation constraints are not satisfiable.\n", + "# Minimal max_depth is 57965.\n", + "#molecule = molecule_C2H2\n", + "# The exponentiation constraints are not satisfiable.\n", + "# Minimal max_depth is 15115.\n", + "#molecule = molecule_C2H4\n", + "# The exponentiation constraints are not satisfiable.\n", + "# Minimal max_depth is 24471." + ] + }, + { + "cell_type": "markdown", + "source": [ + "# **Results for BeH2:**\n", + "\n", + "Your qubit solution is [{'phase': 0.46875}: 135341]\n", + "\n", + "The final results of the Energy (matrix's eigenvlues) is therefore:\n", + "\n", + "[-5.0500156710895965]\n", + "\n", + "exact result: -3.940331561325765\n", + "\n", + "The results including the error contributed from the resolution (number of qubits participating in the QPE) are: The resolution of result is 3.3666771140597356 the energy solution is between -8.416692785149332 and -1.683338557029861" + ], + "metadata": { + "id": "ClsUidSlHIsO" + }, + "id": "ClsUidSlHIsO" + }, + { + "cell_type": "markdown", + "source": [ + "# **Results for H2O:**\n", + "\n", + "Your qubit solution is\n", + "[{'phase': 0.453125}: 89076]\n", + "\n", + "The final results of the Energy (matrix's eigenvlues) is therefore:\n", + "\n", + "[-29.018825909142947]\n", + "\n", + "exact result: -23.54449724044351\n", + "\n", + "\n", + "The results including the error contributed from the resolution (number of qubits\n", + "participating in the QPE) are:\n", + "The resolution of result is 11.607530363657174\n", + "the energy solution is between -40.62635627280012 and -17.41129554548577\n", + "\n" + ], + "metadata": { + "id": "Cab7eyKPHSW8" + }, + "id": "Cab7eyKPHSW8" + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "5d27e5df-e16e-44b2-b78a-187905577908", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:39.301806Z", + "iopub.status.busy": "2024-05-07T15:16:39.300600Z", + "iopub.status.idle": "2024-05-07T15:16:41.781375Z", + "shell.execute_reply": "2024-05-07T15:16:41.780596Z" + }, + "tags": [], + "id": "5d27e5df-e16e-44b2-b78a-187905577908", + "outputId": "7bad3408-043c-4a50-beb7-a0b2acfb6360", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Your Hamiltonian is\n", + "-0.702 * IIIIIII\n", + "-0.230 * ZIZZZIZ\n", + "-0.022 * IIIIIZX\n", + "+0.022 * ZIZZZZX\n", + "-0.251 * ZIIIZZI\n", + "-0.058 * ZIZZZXZ\n", + "+0.058 * IIZZIXZ\n", + "-0.857 * IIIZIII\n", + "-0.857 * IIZIIII\n", + "-0.495 * IIIIIIZ\n", + "-0.755 * IIIIIZI\n", + "-0.230 * ZZZZZII\n", + "-0.022 * ZXIIIII\n", + "+0.022 * IXZZZII\n", + "-0.251 * IIIIZII\n", + "+0.058 * YZZZYII\n", + "+0.058 * XZZZXII\n", + "-0.495 * IZIIIII\n", + "-0.755 * ZIIIIII\n", + "+0.062 * IIZZIZZ\n", + "+0.010 * IIIIIXI\n", + "-0.010 * ZIIIZXI\n", + "+0.172 * ZIZIZIZ\n", + "+0.172 * ZIIZZIZ\n", + "+0.159 * ZIZZZII\n", + "+0.093 * ZIZZZZZ\n", + "+0.012 * ZIIIZIX\n", + "-0.012 * IIZZIIX\n", + "+0.003 * ZIZZZYY\n", + "+0.020 * IIZZIXX\n", + "+0.017 * IIZZIYY\n", + "+0.017 * IIIIIYY\n", + "+0.020 * IIIIIXX\n", + "+0.003 * ZIIIZYY\n", + "+0.014 * IIIZIZX\n", + "-0.014 * ZIZIZZX\n", + "+0.014 * IIZIIZX\n", + "-0.014 * ZIIZZZX\n", + "+0.005 * IIIIIIX\n", + "-0.005 * ZIZZZIX\n", + "+0.202 * IZIIIIZ\n", + "+0.003 * ZZZZZZX\n", + "-0.003 * IZIIIZX\n", + "+0.041 * ZZIIXZZ\n", + "-0.041 * IIZZXZZ\n", + "-0.041 * ZZZZXII\n", + "+0.041 * IIIIXII\n", + "-0.011 * ZZZZXXI\n", + "+0.011 * IIIIXXI\n", + "-0.011 * IZIIYYZ\n", + "+0.011 * ZIZZYYZ\n", + "+0.012 * ZZIXIZZ\n", + "-0.012 * IIZXZZZ\n", + "-0.012 * IZZXZZI\n", + "+0.012 * ZIIXIZI\n", + "+0.012 * ZZXIIZZ\n", + "-0.012 * IIXZZZZ\n", + "-0.012 * IZXZZZI\n", + "+0.012 * ZIXIIZI\n", + "+0.003 * IXZZZIZ\n", + "-0.003 * ZXIIIIZ\n", + "+0.039 * ZXIIIZX\n", + "-0.039 * IXZZZZX\n", + "-0.011 * XIZZIZZ\n", + "+0.011 * XZIIZZZ\n", + "+0.011 * XIIIIII\n", + "-0.011 * XZZZZII\n", + "+0.014 * XIIIIXI\n", + "-0.014 * XZZZZXI\n", + "+0.014 * YIZZZYZ\n", + "-0.014 * YZIIIYZ\n", + "+0.103 * ZIZZIIZ\n", + "-0.012 * IIIIZZX\n", + "+0.012 * ZIZZIZX\n", + "+0.024 * IYIIYZZ\n", + "+0.024 * IXIIXZZ\n", + "-0.024 * IYZZYII\n", + "-0.024 * IXZZXII\n", + "-0.015 * IYZZYXI\n", + "-0.015 * IXZZXXI\n", + "+0.015 * ZYIIXYZ\n", + "-0.015 * ZXIIYYZ\n", + "-0.001 * XZIIXIZ\n", + "-0.001 * YZIIYIZ\n", + "-0.018 * YZZZYZX\n", + "-0.018 * XZZZXZX\n", + "-0.018 * XZIIXZX\n", + "-0.018 * YZIIYZX\n", + "-0.012 * IYIYIZZ\n", + "-0.012 * IXIXIZZ\n", + "+0.012 * ZYZYZZI\n", + "+0.012 * ZXZXZZI\n", + "-0.012 * IYYIIZZ\n", + "-0.012 * IXXIIZZ\n", + "+0.012 * ZYYZZZI\n", + "+0.012 * ZXXZZZI\n", + "+0.198 * ZZZZZIZ\n", + "-0.036 * YYZZIZZ\n", + "-0.036 * XXZZIZZ\n", + "+0.036 * YYIIIII\n", + "+0.036 * XXIIIII\n", + "+0.014 * YYIIIXI\n", + "+0.014 * XXIIIXI\n", + "-0.014 * XYZZZYZ\n", + "+0.014 * YXZZZYZ\n", + "+0.107 * IIZZZIZ\n", + "-0.009 * ZIIIIZX\n", + "+0.009 * IIZZZZX\n", + "+0.174 * ZIIZZZI\n", + "+0.174 * ZIZIZZI\n", + "+0.081 * ZIIIZZZ\n", + "+0.182 * ZIIIZII\n", + "+0.026 * ZIZIZXZ\n", + "-0.026 * IIZIIXZ\n", + "+0.026 * ZIIZZXZ\n", + "-0.026 * IIIZIXZ\n", + "+0.017 * ZIZZZXI\n", + "-0.017 * IIZZIXI\n", + "+0.103 * IZZZIZI\n", + "-0.001 * IZIIIXZ\n", + "+0.001 * ZZIIZXZ\n", + "+0.024 * IZIIYZY\n", + "-0.024 * ZIZZYZY\n", + "+0.024 * ZZIIXIX\n", + "-0.024 * IIZZXIX\n", + "-0.012 * IXIIZZI\n", + "+0.012 * ZXZZIZI\n", + "+0.018 * IXZZZXZ\n", + "-0.018 * ZXIIIXZ\n", + "-0.018 * ZXZZIXZ\n", + "+0.018 * IXIIZXZ\n", + "-0.015 * YIZZZZY\n", + "+0.015 * YZIIIZY\n", + "-0.015 * XIZZIIX\n", + "+0.015 * XZIIZIX\n", + "+0.231 * ZIIIIZI\n", + "-0.003 * ZIZZIXZ\n", + "+0.003 * IIZZZXZ\n", + "+0.004 * ZIIXXZI\n", + "+0.004 * ZIIYYZI\n", + "+0.004 * IIIYYII\n", + "+0.004 * IIIXXII\n", + "+0.004 * ZIXIXZI\n", + "+0.004 * ZIYIYZI\n", + "+0.004 * IIYIYII\n", + "+0.004 * IIXIXII\n", + "-0.021 * ZYIIXZY\n", + "+0.021 * ZXIIYZY\n", + "+0.021 * IYIIYIX\n", + "+0.021 * IXIIXIX\n", + "-0.003 * XZZZXZI\n", + "-0.003 * YZZZYZI\n", + "+0.041 * XZIIXXZ\n", + "+0.041 * YZIIYXZ\n", + "+0.003 * XZZXZZI\n", + "+0.003 * YZZYZZI\n", + "+0.003 * YZZYIII\n", + "+0.003 * XZZXIII\n", + "+0.003 * XZXZZZI\n", + "+0.003 * YZYZZZI\n", + "+0.003 * YZYZIII\n", + "+0.003 * XZXZIII\n", + "+0.102 * ZZIIZZI\n", + "-0.007 * ZZZZZXZ\n", + "+0.007 * IZZZIXZ\n", + "+0.024 * XYZZZZY\n", + "-0.024 * YXZZZZY\n", + "-0.024 * YYZZIIX\n", + "-0.024 * XXZZIIX\n", + "+0.223 * IIIIZZI\n", + "+0.389 * IIZZIII\n", + "+0.171 * IIIZIIZ\n", + "+0.191 * IIIZIZI\n", + "+0.172 * ZZZIZII\n", + "-0.012 * ZZIYIIY\n", + "+0.012 * IIZYZIY\n", + "-0.012 * ZZIXIIX\n", + "+0.012 * IIZXZIX\n", + "+0.014 * ZXIZIII\n", + "-0.014 * IXZIZII\n", + "+0.174 * IIIZZII\n", + "-0.003 * IIZXYYZ\n", + "+0.003 * IIZYXYZ\n", + "+0.003 * IIZYYXZ\n", + "+0.003 * IIZXXXZ\n", + "-0.026 * YZZIYII\n", + "-0.026 * XZZIXII\n", + "+0.012 * IIXXIII\n", + "+0.012 * IIYYIII\n", + "-0.013 * IYIXIIY\n", + "+0.013 * IXIYIIY\n", + "+0.013 * IYIYIIX\n", + "+0.013 * IXIXIIX\n", + "-0.004 * YZIXIYZ\n", + "+0.004 * XZIYIYZ\n", + "+0.004 * YZIYIXZ\n", + "+0.004 * XZIXIXZ\n", + "+0.171 * IZIZIII\n", + "+0.191 * ZIIZIII\n", + "+0.171 * IIZIIIZ\n", + "+0.191 * IIZIIZI\n", + "+0.172 * ZZIZZII\n", + "-0.012 * ZZYIIIY\n", + "+0.012 * IIYZZIY\n", + "-0.012 * ZZXIIIX\n", + "+0.012 * IIXZZIX\n", + "+0.014 * ZXZIIII\n", + "-0.014 * IXIZZII\n", + "+0.174 * IIZIZII\n", + "-0.003 * IIXZYYZ\n", + "+0.003 * IIYZXYZ\n", + "+0.003 * IIYZYXZ\n", + "+0.003 * IIXZXXZ\n", + "-0.026 * YZIZYII\n", + "-0.026 * XZIZXII\n", + "-0.013 * IYXIIIY\n", + "+0.013 * IXYIIIY\n", + "+0.013 * IYYIIIX\n", + "+0.013 * IXXIIIX\n", + "-0.004 * YZXIIYZ\n", + "+0.004 * XZYIIYZ\n", + "+0.004 * YZYIIXZ\n", + "+0.004 * XZXIIXZ\n", + "+0.171 * IZZIIII\n", + "+0.191 * ZIZIIII\n", + "+0.074 * IIIIIZZ\n", + "-0.036 * ZZZZXYY\n", + "+0.036 * IIIIXYY\n", + "-0.036 * ZZZZXXX\n", + "+0.036 * IIIIXXX\n", + "+0.014 * XIIIIYY\n", + "-0.014 * XZZZZYY\n", + "+0.014 * XIIIIXX\n", + "-0.014 * XZZZZXX\n", + "+0.102 * IIIIZIZ\n", + "-0.024 * IYZZYYY\n", + "-0.024 * IXZZXYY\n", + "-0.024 * IYZZYXX\n", + "-0.024 * IXZZXXX\n", + "+0.007 * YZZZYIZ\n", + "+0.007 * XZZZXIZ\n", + "+0.035 * YYIIIYY\n", + "+0.035 * XXIIIYY\n", + "+0.035 * YYIIIXX\n", + "+0.035 * XXIIIXX\n", + "+0.109 * ZIIIIIZ\n", + "+0.107 * ZZZZZZI\n", + "-0.009 * ZXIIIZI\n", + "+0.009 * IXZZZZI\n", + "+0.109 * IZIIIZI\n", + "+0.062 * ZZZZIII\n", + "+0.010 * XIIIXII\n", + "+0.010 * YIIIYII\n", + "+0.093 * IZZZZII\n", + "+0.012 * ZXIIZII\n", + "-0.012 * IXZZIII\n", + "+0.003 * XYZZYII\n", + "+0.020 * XXZZXII\n", + "+0.017 * YYZZXII\n", + "+0.017 * YYIIXII\n", + "+0.020 * XXIIXII\n", + "+0.003 * XYIIYII\n", + "+0.005 * IXIIIII\n", + "-0.005 * ZXZZZII\n", + "+0.081 * IZIIZII\n", + "-0.017 * YIZZYII\n", + "-0.017 * XIZZXII\n", + "+0.074 * ZZIIIII\n" + ] + } + ], + "source": [ + "# define your molecule problem\n", + "\n", + "gs_problem = MoleculeProblem(\n", + " molecule=molecule,\n", + " basis=\"sto3g\",\n", + " mapping=\"jordan_wigner\", #'bravyi_kitaev'\n", + " z2_symmetries=True,\n", + " freeze_core=True,\n", + ")\n", + "\n", + "operator = gs_problem.generate_hamiltonian()\n", + "gs_problem = gs_problem.update_problem(operator.num_qubits)\n", + "print(\"Your Hamiltonian is\", operator.show(), sep=\"\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "7a0b57c6-a057-41cb-8163-cc91d559bbdd", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:41.786010Z", + "iopub.status.busy": "2024-05-07T15:16:41.784773Z", + "iopub.status.idle": "2024-05-07T15:16:41.791592Z", + "shell.execute_reply": "2024-05-07T15:16:41.790923Z" + }, + "tags": [], + "id": "7a0b57c6-a057-41cb-8163-cc91d559bbdd", + "outputId": "1460479e-94e8-4c11-baa9-d0b96c9916b7", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Your Pauli list is\n", + "[('IIIIIII', (-0.7022930768258964+0j)), ('ZIZZZIZ', (-0.230190604546995+0j)), ('IIIIIZX', (-0.022105135983230894+0j)), ('ZIZZZZX', (0.022105135983230894+0j)), ('ZIIIZZI', (-0.25083590558353214+0j)), ('ZIZZZXZ', (-0.05762054716987154+0j)), ('IIZZIXZ', (0.05762054716987154+0j)), ('IIIZIII', (-0.8572771753840476+0j)), ('IIZIIII', (-0.8572771753840476+0j)), ('IIIIIIZ', (-0.49539136059267835+0j)), ('IIIIIZI', (-0.7554221157797676+0j)), ('ZZZZZII', (-0.23019060454699486+0j)), ('ZXIIIII', (-0.022105135983230894+0j)), ('IXZZZII', (0.022105135983230894+0j)), ('IIIIZII', (-0.2508359055835321+0j)), ('YZZZYII', (0.05762054716987154+0j)), ('XZZZXII', (0.05762054716987154+0j)), ('IZIIIII', (-0.4953913605926782+0j)), ('ZIIIIII', (-0.7554221157797675+0j)), ('IIZZIZZ', (0.06177536902294071+0j)), ('IIIIIXI', (0.009628629697052212+0j)), ('ZIIIZXI', (-0.009628629697052212+0j)), ('ZIZIZIZ', (0.1721312352568632+0j)), ('ZIIZZIZ', (0.17213123525686325+0j)), ('ZIZZZII', (0.15942306177427756+0j)), ('ZIZZZZZ', (0.09279153113235829+0j)), ('ZIIIZIX', (0.011782782608242623+0j)), ('IIZZIIX', (-0.011782782608242623+0j)), ('ZIZZZYY', (0.002973281387454195+0j)), ('IIZZIXX', (0.02038882910889495+0j)), ('IIZZIYY', (0.01741554772144075+0j)), ('IIIIIYY', (0.01741554772144075+0j)), ('IIIIIXX', (0.02038882910889495+0j)), ('ZIIIZYY', (0.002973281387454195+0j)), ('IIIZIZX', (0.014419981611826815+0j)), ('ZIZIZZX', (-0.014419981611826815+0j)), ('IIZIIZX', (0.01441998161182683+0j)), ('ZIIZZZX', (-0.01441998161182683+0j)), ('IIIIIIX', (0.004816137943065805+0j)), ('ZIZZZIX', (-0.004816137943065805+0j)), ('IZIIIIZ', (0.20240438090181115+0j)), ('ZZZZZZX', (0.002565939742358075+0j)), ('IZIIIZX', (-0.002565939742358075+0j)), ('ZZIIXZZ', (0.04108938500992233+0j)), ('IIZZXZZ', (-0.04108938500992233+0j)), ('ZZZZXII', (-0.04108938500992233+0j)), ('IIIIXII', (0.04108938500992233+0j)), ('ZZZZXXI', (-0.011051936749184695+0j)), ('IIIIXXI', (0.011051936749184695+0j)), ('IZIIYYZ', (-0.011051936749184695+0j)), ('ZIZZYYZ', (0.011051936749184695+0j)), ('ZZIXIZZ', (0.01234821063234333+0j)), ('IIZXZZZ', (-0.01234821063234333+0j)), ('IZZXZZI', (-0.01234821063234333+0j)), ('ZIIXIZI', (0.01234821063234333+0j)), ('ZZXIIZZ', (0.012348210632343334+0j)), ('IIXZZZZ', (-0.012348210632343334+0j)), ('IZXZZZI', (-0.012348210632343334+0j)), ('ZIXIIZI', (0.012348210632343334+0j)), ('IXZZZIZ', (0.002565939742358075+0j)), ('ZXIIIIZ', (-0.002565939742358075+0j)), ('ZXIIIZX', (0.038895655891840034+0j)), ('IXZZZZX', (-0.038895655891840034+0j)), ('XIZZIZZ', (-0.011051936749184699+0j)), ('XZIIZZZ', (0.011051936749184699+0j)), ('XIIIIII', (0.011051936749184699+0j)), ('XZZZZII', (-0.011051936749184699+0j)), ('XIIIIXI', (0.014149650962831172+0j)), ('XZZZZXI', (-0.014149650962831172+0j)), ('YIZZZYZ', (0.014149650962831172+0j)), ('YZIIIYZ', (-0.014149650962831172+0j)), ('ZIZZIIZ', (0.10286475403286305+0j)), ('IIIIZZX', (-0.011879666226520692+0j)), ('ZIZZIZX', (0.011879666226520692+0j)), ('IYIIYZZ', (0.023662448834763317+0j)), ('IXIIXZZ', (0.023662448834763317+0j)), ('IYZZYII', (-0.023662448834763317+0j)), ('IXZZXII', (-0.023662448834763317+0j)), ('IYZZYXI', (-0.015307708024581802+0j)), ('IXZZXXI', (-0.015307708024581802+0j)), ('ZYIIXYZ', (0.015307708024581802+0j)), ('ZXIIYYZ', (-0.015307708024581802+0j)), ('XZIIXIZ', (-0.0014233070521324851+0j)), ('YZIIYIZ', (-0.0014233070521324851+0j)), ('YZZZYZX', (-0.018280989412035993+0j)), ('XZZZXZX', (-0.018280989412035993+0j)), ('XZIIXZX', (-0.018280989412035993+0j)), ('YZIIYZX', (-0.018280989412035993+0j)), ('IYIYIZZ', (-0.01185327361540123+0j)), ('IXIXIZZ', (-0.01185327361540123+0j)), ('ZYZYZZI', (0.01185327361540123+0j)), ('ZXZXZZI', (0.01185327361540123+0j)), ('IYYIIZZ', (-0.011853273615401231+0j)), ('IXXIIZZ', (-0.011853273615401231+0j)), ('ZYYZZZI', (0.011853273615401231+0j)), ('ZXXZZZI', (0.011853273615401231+0j)), ('ZZZZZIZ', (0.19831871766611753+0j)), ('YYZZIZZ', (-0.03569653713347675+0j)), ('XXZZIZZ', (-0.03569653713347675+0j)), ('YYIIIII', (0.03569653713347675+0j)), ('XXIIIII', (0.03569653713347675+0j)), ('YYIIIXI', (0.01389796708217946+0j)), ('XXIIIXI', (0.01389796708217946+0j)), ('XYZZZYZ', (-0.01389796708217946+0j)), ('YXZZZYZ', (0.01389796708217946+0j)), ('IIZZZIZ', (0.10694118209518946+0j)), ('ZIIIIZX', (-0.009081829139113658+0j)), ('IIZZZZX', (0.009081829139113658+0j)), ('ZIIZZZI', (0.1744698035079175+0j)), ('ZIZIZZI', (0.17446980350791766+0j)), ('ZIIIZZZ', (0.0810458258950273+0j)), ('ZIIIZII', (0.18200001297184848+0j)), ('ZIZIZXZ', (0.026286745525201403+0j)), ('IIZIIXZ', (-0.026286745525201403+0j)), ('ZIIZZXZ', (0.026286745525201403+0j)), ('IIIZIXZ', (-0.026286745525201403+0j)), ('ZIZZZXI', (0.017265081835497856+0j)), ('IIZZIXI', (-0.017265081835497856+0j)), ('IZZZIZI', (0.10286475403286305+0j)), ('IZIIIXZ', (-0.0014233070521324851+0j)), ('ZZIIZXZ', (0.0014233070521324851+0j)), ('IZIIYZY', (0.023662448834763317+0j)), ('ZIZZYZY', (-0.023662448834763317+0j)), ('ZZIIXIX', (0.023662448834763317+0j)), ('IIZZXIX', (-0.023662448834763317+0j)), ('IXIIZZI', (-0.011879666226520692+0j)), ('ZXZZIZI', (0.011879666226520692+0j)), ('IXZZZXZ', (0.018280989412035993+0j)), ('ZXIIIXZ', (-0.018280989412035993+0j)), ('ZXZZIXZ', (-0.018280989412035993+0j)), ('IXIIZXZ', (0.018280989412035993+0j)), ('YIZZZZY', (-0.015307708024581803+0j)), ('YZIIIZY', (0.015307708024581803+0j)), ('XIZZIIX', (-0.015307708024581803+0j)), ('XZIIZIX', (0.015307708024581803+0j)), ('ZIIIIZI', (0.23075467521596388+0j)), ('ZIZZIXZ', (-0.002551353102471067+0j)), ('IIZZZXZ', (0.002551353102471067+0j)), ('ZIIXXZI', (0.0036560013958361033+0j)), ('ZIIYYZI', (0.0036560013958361033+0j)), ('IIIYYII', (0.0036560013958361033+0j)), ('IIIXXII', (0.0036560013958361033+0j)), ('ZIXIXZI', (0.0036560013958361033+0j)), ('ZIYIYZI', (0.0036560013958361033+0j)), ('IIYIYII', (0.0036560013958361033+0j)), ('IIXIXII', (0.0036560013958361033+0j)), ('ZYIIXZY', (-0.020873062000978698+0j)), ('ZXIIYZY', (0.020873062000978698+0j)), ('IYIIYIX', (0.020873062000978698+0j)), ('IXIIXIX', (0.020873062000978698+0j)), ('XZZZXZI', (-0.0025513531024710665+0j)), ('YZZZYZI', (-0.0025513531024710665+0j)), ('XZIIXXZ', (0.04125144772662373+0j)), ('YZIIYXZ', (0.04125144772662373+0j)), ('XZZXZZI', (0.0034405062273070984+0j)), ('YZZYZZI', (0.0034405062273070984+0j)), ('YZZYIII', (0.0034405062273070984+0j)), ('XZZXIII', (0.0034405062273070984+0j)), ('XZXZZZI', (0.0034405062273070992+0j)), ('YZYZZZI', (0.0034405062273070992+0j)), ('YZYZIII', (0.0034405062273070992+0j)), ('XZXZIII', (0.0034405062273070992+0j)), ('ZZIIZZI', (0.10191888789600599+0j)), ('ZZZZZXZ', (-0.006564129606561605+0j)), ('IZZZIXZ', (0.006564129606561605+0j)), ('XYZZZZY', (0.02382921144205946+0j)), ('YXZZZZY', (-0.02382921144205946+0j)), ('YYZZIIX', (-0.02382921144205946+0j)), ('XXZZIIX', (-0.02382921144205946+0j)), ('IIIIZZI', (0.22325146069847226+0j)), ('IIZZIII', (0.3892355930337423+0j)), ('IIIZIIZ', (0.17086285707799762+0j)), ('IIIZIZI', (0.19133630882633207+0j)), ('ZZZIZII', (0.1721312352568632+0j)), ('ZZIYIIY', (-0.01185327361540123+0j)), ('IIZYZIY', (0.01185327361540123+0j)), ('ZZIXIIX', (-0.01185327361540123+0j)), ('IIZXZIX', (0.01185327361540123+0j)), ('ZXIZIII', (0.014419981611826815+0j)), ('IXZIZII', (-0.014419981611826815+0j)), ('IIIZZII', (0.1744698035079175+0j)), ('IIZXYYZ', (-0.0034405062273070984+0j)), ('IIZYXYZ', (0.0034405062273070984+0j)), ('IIZYYXZ', (0.0034405062273070984+0j)), ('IIZXXXZ', (0.0034405062273070984+0j)), ('YZZIYII', (-0.026286745525201403+0j)), ('XZZIXII', (-0.026286745525201403+0j)), ('IIXXIII', (0.012124689610585541+0j)), ('IIYYIII', (0.012124689610585541+0j)), ('IYIXIIY', (-0.012722452161354642+0j)), ('IXIYIIY', (0.012722452161354642+0j)), ('IYIYIIX', (0.012722452161354642+0j)), ('IXIXIIX', (0.012722452161354642+0j)), ('YZIXIYZ', (-0.004138154161062567+0j)), ('XZIYIYZ', (0.004138154161062567+0j)), ('YZIYIXZ', (0.004138154161062567+0j)), ('XZIXIXZ', (0.004138154161062567+0j)), ('IZIZIII', (0.17086285707799762+0j)), ('ZIIZIII', (0.19133630882633207+0j)), ('IIZIIIZ', (0.17086285707799764+0j)), ('IIZIIZI', (0.19133630882633207+0j)), ('ZZIZZII', (0.17213123525686325+0j)), ('ZZYIIIY', (-0.011853273615401231+0j)), ('IIYZZIY', (0.011853273615401231+0j)), ('ZZXIIIX', (-0.011853273615401231+0j)), ('IIXZZIX', (0.011853273615401231+0j)), ('ZXZIIII', (0.01441998161182683+0j)), ('IXIZZII', (-0.01441998161182683+0j)), ('IIZIZII', (0.17446980350791766+0j)), ('IIXZYYZ', (-0.0034405062273070992+0j)), ('IIYZXYZ', (0.0034405062273070992+0j)), ('IIYZYXZ', (0.0034405062273070992+0j)), ('IIXZXXZ', (0.0034405062273070992+0j)), ('YZIZYII', (-0.026286745525201403+0j)), ('XZIZXII', (-0.026286745525201403+0j)), ('IYXIIIY', (-0.012722452161354645+0j)), ('IXYIIIY', (0.012722452161354645+0j)), ('IYYIIIX', (0.012722452161354645+0j)), ('IXXIIIX', (0.012722452161354645+0j)), ('YZXIIYZ', (-0.004138154161062567+0j)), ('XZYIIYZ', (0.004138154161062567+0j)), ('YZYIIXZ', (0.004138154161062567+0j)), ('XZXIIXZ', (0.004138154161062567+0j)), ('IZZIIII', (0.17086285707799764+0j)), ('ZIZIIII', (0.19133630882633207+0j)), ('IIIIIZZ', (0.07373286867690823+0j)), ('ZZZZXYY', (-0.035696537133476744+0j)), ('IIIIXYY', (0.035696537133476744+0j)), ('ZZZZXXX', (-0.035696537133476744+0j)), ('IIIIXXX', (0.035696537133476744+0j)), ('XIIIIYY', (0.013897967082179458+0j)), ('XZZZZYY', (-0.013897967082179458+0j)), ('XIIIIXX', (0.013897967082179458+0j)), ('XZZZZXX', (-0.013897967082179458+0j)), ('IIIIZIZ', (0.10191888789600599+0j)), ('IYZZYYY', (-0.02382921144205946+0j)), ('IXZZXYY', (-0.02382921144205946+0j)), ('IYZZYXX', (-0.02382921144205946+0j)), ('IXZZXXX', (-0.02382921144205946+0j)), ('YZZZYIZ', (0.006564129606561605+0j)), ('XZZZXIZ', (0.006564129606561605+0j)), ('YYIIIYY', (0.0351660524024311+0j)), ('XXIIIYY', (0.0351660524024311+0j)), ('YYIIIXX', (0.0351660524024311+0j)), ('XXIIIXX', (0.0351660524024311+0j)), ('ZIIIIIZ', (0.10889892107933934+0j)), ('ZZZZZZI', (0.10694118209518946+0j)), ('ZXIIIZI', (-0.009081829139113658+0j)), ('IXZZZZI', (0.009081829139113658+0j)), ('IZIIIZI', (0.10889892107933934+0j)), ('ZZZZIII', (0.06177536902294071+0j)), ('XIIIXII', (0.009628629697052212+0j)), ('YIIIYII', (0.009628629697052212+0j)), ('IZZZZII', (0.09279153113235829+0j)), ('ZXIIZII', (0.011782782608242623+0j)), ('IXZZIII', (-0.011782782608242623+0j)), ('XYZZYII', (0.002973281387454195+0j)), ('XXZZXII', (0.02038882910889495+0j)), ('YYZZXII', (0.01741554772144075+0j)), ('YYIIXII', (0.01741554772144075+0j)), ('XXIIXII', (0.02038882910889495+0j)), ('XYIIYII', (0.002973281387454195+0j)), ('IXIIIII', (0.004816137943065805+0j)), ('ZXZZZII', (-0.004816137943065805+0j)), ('IZIIZII', (0.0810458258950273+0j)), ('YIZZYII', (-0.017265081835497856+0j)), ('XIZZXII', (-0.017265081835497856+0j)), ('ZZIIIII', (0.07373286867690823+0j))]\n" + ] + } + ], + "source": [ + "pauli_ops = operator.pauli_list\n", + "N = operator.num_qubits\n", + "print(\"Your Pauli list is\", pauli_ops, sep=\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "685f4a01-caf3-4d0c-b9f3-4fc89bc5192a", + "metadata": { + "id": "685f4a01-caf3-4d0c-b9f3-4fc89bc5192a" + }, + "source": [ + "## 2. Preparing the Molecule for QPE" + ] + }, + { + "cell_type": "markdown", + "id": "1b1bafad-d35c-4504-9665-02b0ae86d52f", + "metadata": { + "id": "1b1bafad-d35c-4504-9665-02b0ae86d52f" + }, + "source": [ + "### 2.1 Chose the Algorithm's Precision\n", + "\n", + "For QPE algorithms, the precision is set by the number of qubits chosen $n$, such that the resolution is $1/{2^n}$. In case the matrix needs to be normlized, the resolution will be distorted. In case of normalization, that the span of results in the QPE is strached between the lowest and highest possible phase, thus the reslution will be mapped to $normalization-coefficient/{2^n} ~\\sim 1/{((\\lambda_{max}-\\lambda_{min})*2^n)}$.\n", + "\n", + "Here you can chose the precision in the parameter `n_qpe`, or by setting your desired resolution. If you chose your desired resolution and set the parameter `get_recommended_n` to be True, the number of qubits will be calculated for you accordingly.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "id": "4e96164f-aa00-4723-9f59-b1c13ccb58d8", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:41.796364Z", + "iopub.status.busy": "2024-05-07T15:16:41.795124Z", + "iopub.status.idle": "2024-05-07T15:16:41.800121Z", + "shell.execute_reply": "2024-05-07T15:16:41.799301Z" + }, + "tags": [], + "id": "4e96164f-aa00-4723-9f59-b1c13ccb58d8" + }, + "outputs": [], + "source": [ + "# `n_qpe`- The precision of the QPE (the number of qubits to be used in the QPE. Creates resolution of 1/2^n_qpe\n", + "n_qpe = 6" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "id": "74aeea8b-1e16-408f-bc5f-c5888b552a6f", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:41.804701Z", + "iopub.status.busy": "2024-05-07T15:16:41.803523Z", + "iopub.status.idle": "2024-05-07T15:16:41.810737Z", + "shell.execute_reply": "2024-05-07T15:16:41.810086Z" + }, + "tags": [], + "id": "74aeea8b-1e16-408f-bc5f-c5888b552a6f" + }, + "outputs": [], + "source": [ + "# recommanded n_qpe:\n", + "get_recommanded_n = False\n", + "\n", + "import math\n", + "\n", + "desired_resolution = 0.02\n", + "\n", + "\n", + "def get_nqpe(pauli_operator, desired_resolution):\n", + " N = pauli_operator.num_qubits\n", + " A = 0\n", + " for a, b in pauli_operator.pauli_list:\n", + " A = A + abs(b)\n", + " nqpe = math.log2(2 * N * A / desired_resolution)\n", + " return math.ceil(nqpe)\n", + "\n", + "\n", + "if get_recommanded_n:\n", + " n_qpe = get_nqpe(operator, desired_resolution)\n", + " print(\"number of qubits for QPE is\", n_qpe)" + ] + }, + { + "cell_type": "markdown", + "id": "fa3d1079-c12b-48db-8935-1ea059fdbce9", + "metadata": { + "id": "fa3d1079-c12b-48db-8935-1ea059fdbce9" + }, + "source": [ + "### 2.3 Normalize the Matrix\n", + "\n", + "As QPE obtains a phase in the form $e^{2\\pi i\\theta}$, there is meaning only for $\\theta \\in [0,2\\pi)$. Generally, our matrix M can have any eigenvalue, thus \\theta can have any value. In order to fix this discrepancy, the values of the matrix are stretched to be rescaled. We assume\n", + "$\\theta \\in [\\lambda_{min}, \\lambda_{max}]$\n", + "and use a normalization function in order to map those values into $[0, 1-1/{2^n}]$, where n is the number of qubits chosen for the QPE process in section 2.2.\n", + "\n", + "We perform the normalization procedure as following:\n", + "\n", + "a. We evaluate $\\lambda_{min},\\lambda_{max}$ (in the function ` normalization_params()` below). In order to do so we use rough estimation of the absolute max value that can take place by adding together all the pauli coefficients and multiplying by the matrix's dimensions. That will yield us a value $\\lambda$ (which is referred in the code as `normalization_coeff`) and we now assume that the domain is $\\theta \\in [-\\lambda, \\lambda]$.\n", + "In general, one can build a more accurate assessment, which will decrease the span of solutions and thus achieve a better resolution.\n", + "\n", + "b. We make sure only positive values are available by adding $\\lambda*I^n$ to the pauli list. Now our evaluated span is $[0, 2*\\lambda]$.\n", + "\n", + "c. We normlize our matrix by multiplying all of the pauli coefficients by $(1-1/2^n)/(2*\\lambda)$. Now the span of $\\theta$ is $[0, 1-1/2^n]$, as required for proper QPE process.\n", + "\n", + "The values of the matrix's eigenvalues should be now between $0$ to $1-(1/2^n)$. The QPE procedure will be performed on this new normalized matrix. After the phases are obtained, the original phases of the pre-normalized matrix will be gathered by performing opposite steps to this normalization procedure.\n", + "\n", + "* Note that in case your matrix's eigenvalues are naturally between the values $0$ to $1-(1/2^n)$, you may not want to normalize it, as the normalization procedure may enlarge the span, thus lowering the resolution of the agorithm. In that case, you may skip those lines or change the value `normalize` to False." + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "70d8b16f-5f50-4272-9b7b-0ca7cad00b60", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:41.815396Z", + "iopub.status.busy": "2024-05-07T15:16:41.814254Z", + "iopub.status.idle": "2024-05-07T15:16:41.824473Z", + "shell.execute_reply": "2024-05-07T15:16:41.823778Z" + }, + "tags": [], + "id": "70d8b16f-5f50-4272-9b7b-0ca7cad00b60", + "outputId": "4c9491de-b9f5-4855-edac-2798e3def5ab", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[('IIIIIII', (0.4889281053643878+0j)), ('ZIZZZIZ', (-0.0010683317925043465+0j)), ('IIIIIZX', (-0.00010259158750198293+0j)), ('ZIZZZZX', (0.00010259158750198293+0j)), ('ZIIIZZI', (-0.001164148176959137+0j)), ('ZIZZZXZ', (-0.0002674212640616383+0j)), ('IIZZIXZ', (0.0002674212640616383+0j)), ('IIIZIII', (-0.003978687415385471+0j)), ('IIZIIII', (-0.003978687415385471+0j)), ('IIIIIIZ', (-0.0022991483136102307+0j)), ('IIIIIZI', (-0.0035059704744971982+0j)), ('ZZZZZII', (-0.0010683317925043458+0j)), ('ZXIIIII', (-0.00010259158750198293+0j)), ('IXZZZII', (0.00010259158750198293+0j)), ('IIIIZII', (-0.0011641481769591368+0j)), ('YZZZYII', (0.0002674212640616383+0j)), ('XZZZXII', (0.0002674212640616383+0j)), ('IZIIIII', (-0.0022991483136102302+0j)), ('ZIIIIII', (-0.003505970474497198+0j)), ('IIZZIZZ', (0.0002867041026751466+0j)), ('IIIIIXI', (4.46871897480607e-05+0j)), ('ZIIIZXI', (-4.46871897480607e-05+0j)), ('ZIZIZIZ', (0.0007988739221995871+0j)), ('ZIIZZIZ', (0.0007988739221995873+0j)), ('ZIZZZII', (0.0007398943396800271+0j)), ('ZIZZZZZ', (0.00043065242814294217+0j)), ('ZIIIZIX', (5.4684774338750076e-05+0j)), ('IIZZIIX', (-5.4684774338750076e-05+0j)), ('ZIZZZYY', (1.3799221043490745e-05+0j)), ('IIZZIXX', (9.462607907840818e-05+0j)), ('IIZZIYY', (8.082685803491741e-05+0j)), ('IIIIIYY', (8.082685803491741e-05+0j)), ('IIIIIXX', (9.462607907840818e-05+0j)), ('ZIIIZYY', (1.3799221043490745e-05+0j)), ('IIIZIZX', (6.69242119310632e-05+0j)), ('ZIZIZZX', (-6.69242119310632e-05+0j)), ('IIZIIZX', (6.692421193106327e-05+0j)), ('ZIIZZZX', (-6.692421193106327e-05+0j)), ('IIIIIIX', (2.2352055991986643e-05+0j)), ('ZIZZZIX', (-2.2352055991986643e-05+0j)), ('IZIIIIZ', (0.0009393738527474023+0j)), ('ZZZZZZX', (1.1908718037411872e-05+0j)), ('IZIIIZX', (-1.1908718037411872e-05+0j)), ('ZZIIXZZ', (0.00019069890548721176+0j)), ('IIZZXZZ', (-0.00019069890548721176+0j)), ('ZZZZXII', (-0.00019069890548721176+0j)), ('IIIIXII', (0.00019069890548721176+0j)), ('ZZZZXXI', (-5.1292864107712246e-05+0j)), ('IIIIXXI', (5.1292864107712246e-05+0j)), ('IZIIYYZ', (-5.1292864107712246e-05+0j)), ('ZIZZYYZ', (5.1292864107712246e-05+0j)), ('ZZIXIZZ', (5.7308968039915556e-05+0j)), ('IIZXZZZ', (-5.7308968039915556e-05+0j)), ('IZZXZZI', (-5.7308968039915556e-05+0j)), ('ZIIXIZI', (5.7308968039915556e-05+0j)), ('ZZXIIZZ', (5.7308968039915576e-05+0j)), ('IIXZZZZ', (-5.7308968039915576e-05+0j)), ('IZXZZZI', (-5.7308968039915576e-05+0j)), ('ZIXIIZI', (5.7308968039915576e-05+0j)), ('IXZZZIZ', (1.1908718037411872e-05+0j)), ('ZXIIIIZ', (-1.1908718037411872e-05+0j)), ('ZXIIIZX', (0.0001805176447637257+0j)), ('IXZZZZX', (-0.0001805176447637257+0j)), ('XIZZIZZ', (-5.129286410771227e-05+0j)), ('XZIIZZZ', (5.129286410771227e-05+0j)), ('XIIIIII', (5.129286410771227e-05+0j)), ('XZZZZII', (-5.129286410771227e-05+0j)), ('XIIIIXI', (6.56695871935387e-05+0j)), ('XZZZZXI', (-6.56695871935387e-05+0j)), ('YIZZZYZ', (6.56695871935387e-05+0j)), ('YZIIIYZ', (-6.56695871935387e-05+0j)), ('ZIZZIIZ', (0.00047740300816235837+0j)), ('IIIIZZX', (-5.5134418449042965e-05+0j)), ('ZIZZIZX', (5.5134418449042965e-05+0j)), ('IYIIYZZ', (0.00010981919278779304+0j)), ('IXIIXZZ', (0.00010981919278779304+0j)), ('IYZZYII', (-0.00010981919278779304+0j)), ('IXZZXII', (-0.00010981919278779304+0j)), ('IYZZYXI', (-7.104421653185207e-05+0j)), ('IXZZXXI', (-7.104421653185207e-05+0j)), ('ZYIIXYZ', (7.104421653185207e-05+0j)), ('ZXIIYYZ', (-7.104421653185207e-05+0j)), ('XZIIXIZ', (-6.605674359651552e-06+0j)), ('YZIIYIZ', (-6.605674359651552e-06+0j)), ('YZZZYZX', (-8.48434375753428e-05+0j)), ('XZZZXZX', (-8.48434375753428e-05+0j)), ('XZIIXZX', (-8.48434375753428e-05+0j)), ('YZIIYZX', (-8.48434375753428e-05+0j)), ('IYIYIZZ', (-5.5011928369130214e-05+0j)), ('IXIXIZZ', (-5.5011928369130214e-05+0j)), ('ZYZYZZI', (5.5011928369130214e-05+0j)), ('ZXZXZZI', (5.5011928369130214e-05+0j)), ('IYYIIZZ', (-5.501192836913023e-05+0j)), ('IXXIIZZ', (-5.501192836913023e-05+0j)), ('ZYYZZZI', (5.501192836913023e-05+0j)), ('ZXXZZZI', (5.501192836913023e-05+0j)), ('ZZZZZIZ', (0.0009204119844437524+0j)), ('YYZZIZZ', (-0.00016567029561026026+0j)), ('XXZZIZZ', (-0.00016567029561026026+0j)), ('YYIIIII', (0.00016567029561026026+0j)), ('XXIIIII', (0.00016567029561026026+0j)), ('YYIIIXI', (6.450150350093865e-05+0j)), ('XXIIIXI', (6.450150350093865e-05+0j)), ('XYZZZYZ', (-6.450150350093865e-05+0j)), ('YXZZZYZ', (6.450150350093865e-05+0j)), ('IIZZZIZ', (0.0004963220153364809+0j)), ('ZIIIIZX', (-4.214944750895202e-05+0j)), ('IIZZZZX', (4.214944750895202e-05+0j)), ('ZIIZZZI', (0.0008097273921596632+0j)), ('ZIZIZZI', (0.000809727392159664+0j)), ('ZIIIZZZ', (0.0003761397326525245+0j)), ('ZIIIZII', (0.0008446756568395633+0j)), ('ZIZIZXZ', (0.00012199874978090467+0j)), ('IIZIIXZ', (-0.00012199874978090467+0j)), ('ZIIZZXZ', (0.00012199874978090467+0j)), ('IIIZIXZ', (-0.00012199874978090467+0j)), ('ZIZZZXI', (8.012853461743272e-05+0j)), ('IIZZIXI', (-8.012853461743272e-05+0j)), ('IZZZIZI', (0.00047740300816235837+0j)), ('IZIIIXZ', (-6.605674359651552e-06+0j)), ('ZZIIZXZ', (6.605674359651552e-06+0j)), ('IZIIYZY', (0.00010981919278779304+0j)), ('ZIZZYZY', (-0.00010981919278779304+0j)), ('ZZIIXIX', (0.00010981919278779304+0j)), ('IIZZXIX', (-0.00010981919278779304+0j)), ('IXIIZZI', (-5.5134418449042965e-05+0j)), ('ZXZZIZI', (5.5134418449042965e-05+0j)), ('IXZZZXZ', (8.48434375753428e-05+0j)), ('ZXIIIXZ', (-8.48434375753428e-05+0j)), ('ZXZZIXZ', (-8.48434375753428e-05+0j)), ('IXIIZXZ', (8.48434375753428e-05+0j)), ('YIZZZZY', (-7.104421653185207e-05+0j)), ('YZIIIZY', (7.104421653185207e-05+0j)), ('XIZZIIX', (-7.104421653185207e-05+0j)), ('XZIIZIX', (7.104421653185207e-05+0j)), ('ZIIIIZI', (0.0010709496866189413+0j)), ('ZIZZIXZ', (-1.1841020351975189e-05+0j)), ('IIZZZXZ', (1.1841020351975189e-05+0j)), ('ZIIXXZI', (1.6967775606213222e-05+0j)), ('ZIIYYZI', (1.6967775606213222e-05+0j)), ('IIIYYII', (1.6967775606213222e-05+0j)), ('IIIXXII', (1.6967775606213222e-05+0j)), ('ZIXIXZI', (1.6967775606213222e-05+0j)), ('ZIYIYZI', (1.6967775606213222e-05+0j)), ('IIYIYII', (1.6967775606213222e-05+0j)), ('IIXIXII', (1.6967775606213222e-05+0j)), ('ZYIIXZY', (-9.687344010605508e-05+0j)), ('ZXIIYZY', (9.687344010605508e-05+0j)), ('IYIIYIX', (9.687344010605508e-05+0j)), ('IXIIXIX', (9.687344010605508e-05+0j)), ('XZZZXZI', (-1.1841020351975187e-05+0j)), ('YZZZYZI', (-1.1841020351975187e-05+0j)), ('XZIIXXZ', (0.00019145105066260875+0j)), ('YZIIYXZ', (0.00019145105066260875+0j)), ('XZZXZZI', (1.5967646430117258e-05+0j)), ('YZZYZZI', (1.5967646430117258e-05+0j)), ('YZZYIII', (1.5967646430117258e-05+0j)), ('XZZXIII', (1.5967646430117258e-05+0j)), ('XZXZZZI', (1.5967646430117264e-05+0j)), ('YZYZZZI', (1.5967646430117264e-05+0j)), ('YZYZIII', (1.5967646430117264e-05+0j)), ('XZXZIII', (1.5967646430117264e-05+0j)), ('ZZIIZZI', (0.0004730131727585795+0j)), ('ZZZZZXZ', (-3.0464615889121246e-05+0j)), ('IZZZIXZ', (3.0464615889121246e-05+0j)), ('XYZZZZY', (0.00011059315050655396+0j)), ('YXZZZZY', (-0.00011059315050655396+0j)), ('YYZZIIX', (-0.00011059315050655396+0j)), ('XXZZIIX', (-0.00011059315050655396+0j)), ('IIIIZZI', (0.0010361267075021724+0j)), ('IIZZIII', (0.0018064714658123026+0j)), ('IIIZIIZ', (0.0007929872843150064+0j)), ('IIIZIZI', (0.0008880061033849394+0j)), ('ZZZIZII', (0.0007988739221995871+0j)), ('ZZIYIIY', (-5.5011928369130214e-05+0j)), ('IIZYZIY', (5.5011928369130214e-05+0j)), ('ZZIXIIX', (-5.5011928369130214e-05+0j)), ('IIZXZIX', (5.5011928369130214e-05+0j)), ('ZXIZIII', (6.69242119310632e-05+0j)), ('IXZIZII', (-6.69242119310632e-05+0j)), ('IIIZZII', (0.0008097273921596632+0j)), ('IIZXYYZ', (-1.5967646430117258e-05+0j)), ('IIZYXYZ', (1.5967646430117258e-05+0j)), ('IIZYYXZ', (1.5967646430117258e-05+0j)), ('IIZXXXZ', (1.5967646430117258e-05+0j)), ('YZZIYII', (-0.00012199874978090467+0j)), ('XZZIXII', (-0.00012199874978090467+0j)), ('IIXXIII', (5.627159027939906e-05+0j)), ('IIYYIII', (5.627159027939906e-05+0j)), ('IYIXIIY', (-5.904585093444133e-05+0j)), ('IXIYIIY', (5.904585093444133e-05+0j)), ('IYIYIIX', (5.904585093444133e-05+0j)), ('IXIXIIX', (5.904585093444133e-05+0j)), ('YZIXIYZ', (-1.9205482609715852e-05+0j)), ('XZIYIYZ', (1.9205482609715852e-05+0j)), ('YZIYIXZ', (1.9205482609715852e-05+0j)), ('XZIXIXZ', (1.9205482609715852e-05+0j)), ('IZIZIII', (0.0007929872843150064+0j)), ('ZIIZIII', (0.0008880061033849394+0j)), ('IIZIIIZ', (0.0007929872843150065+0j)), ('IIZIIZI', (0.0008880061033849394+0j)), ('ZZIZZII', (0.0007988739221995873+0j)), ('ZZYIIIY', (-5.501192836913023e-05+0j)), ('IIYZZIY', (5.501192836913023e-05+0j)), ('ZZXIIIX', (-5.501192836913023e-05+0j)), ('IIXZZIX', (5.501192836913023e-05+0j)), ('ZXZIIII', (6.692421193106327e-05+0j)), ('IXIZZII', (-6.692421193106327e-05+0j)), ('IIZIZII', (0.000809727392159664+0j)), ('IIXZYYZ', (-1.5967646430117264e-05+0j)), ('IIYZXYZ', (1.5967646430117264e-05+0j)), ('IIYZYXZ', (1.5967646430117264e-05+0j)), ('IIXZXXZ', (1.5967646430117264e-05+0j)), ('YZIZYII', (-0.00012199874978090467+0j)), ('XZIZXII', (-0.00012199874978090467+0j)), ('IYXIIIY', (-5.904585093444135e-05+0j)), ('IXYIIIY', (5.904585093444135e-05+0j)), ('IYYIIIX', (5.904585093444135e-05+0j)), ('IXXIIIX', (5.904585093444135e-05+0j)), ('YZXIIYZ', (-1.9205482609715852e-05+0j)), ('XZYIIYZ', (1.9205482609715852e-05+0j)), ('YZYIIXZ', (1.9205482609715852e-05+0j)), ('XZXIIXZ', (1.9205482609715852e-05+0j)), ('IZZIIII', (0.0007929872843150065+0j)), ('ZIZIIII', (0.0008880061033849394+0j)), ('IIIIIZZ', (0.00034219975187565604+0j)), ('ZZZZXYY', (-0.00016567029561026023+0j)), ('IIIIXYY', (0.00016567029561026023+0j)), ('ZZZZXXX', (-0.00016567029561026023+0j)), ('IIIIXXX', (0.00016567029561026023+0j)), ('XIIIIYY', (6.450150350093864e-05+0j)), ('XZZZZYY', (-6.450150350093864e-05+0j)), ('XIIIIXX', (6.450150350093864e-05+0j)), ('XZZZZXX', (-6.450150350093864e-05+0j)), ('IIIIZIZ', (0.0004730131727585795+0j)), ('IYZZYYY', (-0.00011059315050655396+0j)), ('IXZZXYY', (-0.00011059315050655396+0j)), ('IYZZYXX', (-0.00011059315050655396+0j)), ('IXZZXXX', (-0.00011059315050655396+0j)), ('YZZZYIZ', (3.0464615889121246e-05+0j)), ('XZZZXIZ', (3.0464615889121246e-05+0j)), ('YYIIIYY', (0.00016320827634266463+0j)), ('XXIIIYY', (0.00016320827634266463+0j)), ('YYIIIXX', (0.00016320827634266463+0j)), ('XXIIIXX', (0.00016320827634266463+0j)), ('ZIIIIIZ', (0.0005054080282183206+0j)), ('ZZZZZZI', (0.0004963220153364809+0j)), ('ZXIIIZI', (-4.214944750895202e-05+0j)), ('IXZZZZI', (4.214944750895202e-05+0j)), ('IZIIIZI', (0.0005054080282183206+0j)), ('ZZZZIII', (0.0002867041026751466+0j)), ('XIIIXII', (4.46871897480607e-05+0j)), ('YIIIYII', (4.46871897480607e-05+0j)), ('IZZZZII', (0.00043065242814294217+0j)), ('ZXIIZII', (5.4684774338750076e-05+0j)), ('IXZZIII', (-5.4684774338750076e-05+0j)), ('XYZZYII', (1.3799221043490745e-05+0j)), ('XXZZXII', (9.462607907840818e-05+0j)), ('YYZZXII', (8.082685803491741e-05+0j)), ('YYIIXII', (8.082685803491741e-05+0j)), ('XXIIXII', (9.462607907840818e-05+0j)), ('XYIIYII', (1.3799221043490745e-05+0j)), ('IXIIIII', (2.2352055991986643e-05+0j)), ('ZXZZZII', (-2.2352055991986643e-05+0j)), ('IZIIZII', (0.0003761397326525245+0j)), ('YIZZYII', (-8.012853461743272e-05+0j)), ('XIZZXII', (-8.012853461743272e-05+0j)), ('ZZIIIII', (0.00034219975187565604+0j))]\n" + ] + } + ], + "source": [ + "from typing import cast\n", + "\n", + "from classiq import Pauli, PauliTerm\n", + "\n", + "# normalizing the operator\n", + "## we need to create a matrix such that its normalized version will have eigenvalues of [0,1/2^k] when k is the resolution of the QPE\n", + "normalize = True\n", + "\n", + "\n", + "def normalization_params(pauli_list, N):\n", + " A = 0\n", + " for a, b in pauli_list:\n", + " A = A + abs(b)\n", + " return N * A\n", + "\n", + "\n", + "def normalize_hamiltonian(pauli_list, normalization_coeff, k):\n", + " new_pauli_list = []\n", + " for a, b in pauli_list:\n", + " if a == \"I\" * N:\n", + " new_pauli_list.append(\n", + " (\n", + " a,\n", + " (b + normalization_coeff)\n", + " * (1 - 1 / (2**k))\n", + " / (2 * normalization_coeff),\n", + " )\n", + " )\n", + " else:\n", + " new_pauli_list.append((a, b * (1 - 1 / (2**k)) / (2 * normalization_coeff)))\n", + " return new_pauli_list\n", + "\n", + "\n", + "pauli_list = pauli_ops\n", + "if normalize:\n", + " normalization_coeff = normalization_params(pauli_ops, N)\n", + " new_pauli_list = normalize_hamiltonian(pauli_ops, normalization_coeff, n_qpe)\n", + " pauli_ops = new_pauli_list\n", + " print(pauli_ops)" + ] + }, + { + "cell_type": "markdown", + "id": "21e4de42-3417-46d4-b981-664bb0683dc4", + "metadata": { + "id": "21e4de42-3417-46d4-b981-664bb0683dc4" + }, + "source": [ + "Convert the objects to qmod:" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "e340b469-5566-4bd5-bb5d-3107ebc790e0", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:41.828923Z", + "iopub.status.busy": "2024-05-07T15:16:41.827843Z", + "iopub.status.idle": "2024-05-07T15:16:41.834314Z", + "shell.execute_reply": "2024-05-07T15:16:41.833663Z" + }, + "tags": [], + "id": "e340b469-5566-4bd5-bb5d-3107ebc790e0" + }, + "outputs": [], + "source": [ + "CHAR_TO_STUCT_DICT = {\"I\": Pauli.I, \"X\": Pauli.X, \"Y\": Pauli.Y, \"Z\": Pauli.Z}\n", + "\n", + "\n", + "def pauli_str_to_enums(pauli):\n", + " return [CHAR_TO_STUCT_DICT[s] for s in pauli]\n", + "\n", + "\n", + "def pauli_list_to_hamiltonian(pauli_list):\n", + " return [\n", + " PauliTerm(\n", + " pauli=pauli_str_to_enums(pauli), coefficient=cast(complex, coeff).real\n", + " )\n", + " for pauli, coeff in pauli_list\n", + " ]" + ] + }, + { + "cell_type": "markdown", + "id": "62d2e51d-d532-4c26-86dd-a5b9b40d009e", + "metadata": { + "id": "62d2e51d-d532-4c26-86dd-a5b9b40d009e" + }, + "source": [ + "## 3. Creating the Quantum Circuit\n", + "\n", + "We will now create a quantum circuit of the QPE algorithm using the Classiq platform. The user is able to fill in their constraints and preferences as desired." + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "id": "fd4ee616-2a11-46ba-adc0-ed5171d7dd7d", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:41.838788Z", + "iopub.status.busy": "2024-05-07T15:16:41.837667Z", + "iopub.status.idle": "2024-05-07T15:16:41.842620Z", + "shell.execute_reply": "2024-05-07T15:16:41.841962Z" + }, + "tags": [], + "id": "fd4ee616-2a11-46ba-adc0-ed5171d7dd7d" + }, + "outputs": [], + "source": [ + "constraints = Constraints()\n", + "preferences = Preferences(timeout_seconds=600)" + ] + }, + { + "cell_type": "markdown", + "id": "43c249a1-9db3-4164-bec1-f345670d4cd1", + "metadata": { + "id": "43c249a1-9db3-4164-bec1-f345670d4cd1" + }, + "source": [ + "### 3.1. Create the phase estimation model" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "id": "b05c5ced-e02a-4b56-acc5-c62de3564239", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:41.847063Z", + "iopub.status.busy": "2024-05-07T15:16:41.845892Z", + "iopub.status.idle": "2024-05-07T15:16:41.856296Z", + "shell.execute_reply": "2024-05-07T15:16:41.855646Z" + }, + "tags": [], + "id": "b05c5ced-e02a-4b56-acc5-c62de3564239" + }, + "outputs": [], + "source": [ + "from classiq import molecule_problem_to_qmod\n", + "from classiq.qmod import (\n", + " CInt,\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QCallable,\n", + " QNum,\n", + " allocate,\n", + " allocate_num,\n", + " control,\n", + " invert,\n", + " qfunc,\n", + " repeat,\n", + ")\n", + "from classiq.qmod.builtins import (\n", + " H,\n", + " apply_to_all,\n", + " exponentiation_with_depth_constraint,\n", + " molecule_hartree_fock,\n", + " qft,\n", + ")\n", + "from classiq.qmod.symbolic import log, pi\n", + "\n", + "# this constant will be multipled be a linear factor for each qbit of the qpe, so the\n", + "# depth will scale linear with the power of each unitary, on the expense of approximating the\n", + "# exponentiation function\n", + "exp_max_depth = 2200\n", + "\n", + "\n", + "# define a Quantum Phase Estimation function that allows specifying each controlled\n", + "# power unitary directly\n", + "@qfunc\n", + "def my_flexible_qpe(\n", + " unitary_with_power: QCallable[CInt],\n", + " phase: QArray[QBit],\n", + ") -> None:\n", + " apply_to_all(H, phase)\n", + "\n", + " repeat(\n", + " count=phase.len,\n", + " iteration=lambda index: control(\n", + " ctrl=phase[index],\n", + " operand=lambda: unitary_with_power(2**index),\n", + " ),\n", + " )\n", + " invert(lambda: qft(phase))\n", + "\n", + "\n", + "@qfunc\n", + "def main(reg: Output[QArray[QBit]], phase: Output[QNum]):\n", + " allocate_num(num_qubits=n_qpe, is_signed=False, fraction_digits=n_qpe, out=phase)\n", + " allocate(N, reg)\n", + "\n", + " # The state chosen for the initial state is HF, as usually it has good overlap with the with the eigenstate of minimal energy.\n", + " molecule_hartree_fock(molecule_problem_to_qmod(gs_problem), reg)\n", + "\n", + " # # Hereby we send the pauli list created for the molecule for creating phase estimation circuit.\n", + " my_flexible_qpe(\n", + " lambda power: exponentiation_with_depth_constraint(\n", + " pauli_list_to_hamiltonian(pauli_ops),\n", + " evolution_coefficient=-2 * np.pi * power,\n", + " max_depth=exp_max_depth * ((2**0.5) ** log(power, 2)),\n", + " qbv=reg,\n", + " ),\n", + " phase,\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "467eca03-8a66-43d8-b2af-6d86b21e36d5", + "metadata": { + "tags": [], + "id": "467eca03-8a66-43d8-b2af-6d86b21e36d5" + }, + "source": [ + "## 3.2. Synthesizing the Circuit\n", + "\n", + "Hereby we syntesize the circuit and show it using the analyzer." + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "10eaa569-de42-41b4-b615-c04bdc850ecf", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:41.861003Z", + "iopub.status.busy": "2024-05-07T15:16:41.859910Z", + "iopub.status.idle": "2024-05-07T15:16:41.880458Z", + "shell.execute_reply": "2024-05-07T15:16:41.879759Z" + }, + "tags": [], + "id": "10eaa569-de42-41b4-b615-c04bdc850ecf" + }, + "outputs": [], + "source": [ + "from classiq import create_model\n", + "from classiq.execution import ExecutionPreferences\n", + "\n", + "num_shots = 200000\n", + "\n", + "qmod = create_model(\n", + " main,\n", + " constraints=constraints,\n", + " preferences=preferences,\n", + " execution_preferences=ExecutionPreferences(num_shots=num_shots),\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "id": "a7aae67f-1750-43be-9446-74fa0565058a", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:41.885344Z", + "iopub.status.busy": "2024-05-07T15:16:41.884136Z", + "iopub.status.idle": "2024-05-07T15:16:41.904022Z", + "shell.execute_reply": "2024-05-07T15:16:41.903307Z" + }, + "id": "a7aae67f-1750-43be-9446-74fa0565058a" + }, + "outputs": [], + "source": [ + "from classiq import write_qmod\n", + "\n", + "write_qmod(qmod, name=\"qpe_for_molecules\")" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "8d434afe-5cbc-4a56-a48c-e657090c348a", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:16:41.909027Z", + "iopub.status.busy": "2024-05-07T15:16:41.907875Z", + "iopub.status.idle": "2024-05-07T15:20:36.342504Z", + "shell.execute_reply": "2024-05-07T15:20:36.341786Z" + }, + "tags": [], + "id": "8d434afe-5cbc-4a56-a48c-e657090c348a", + "outputId": "660ea141-5ece-4b9f-ca7b-68e2abdea824", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Opening: https://platform.classiq.io/circuit/4c2b4185-9a94-4654-9c86-f119894f8fe4?version=0.42.1\n" + ] + } + ], + "source": [ + "from classiq import show, synthesize\n", + "\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "id": "7483f266-af0f-4d08-aa96-317b4044df58", + "metadata": { + "id": "7483f266-af0f-4d08-aa96-317b4044df58" + }, + "source": [ + "# 4. Measurment and Analysis\n" + ] + }, + { + "cell_type": "markdown", + "id": "e5bf0b3c-839f-43de-9da1-cba55ceba995", + "metadata": { + "id": "e5bf0b3c-839f-43de-9da1-cba55ceba995" + }, + "source": [ + "### 4.1. Circuit Execution\n", + "\n", + "The circuit is now sent to execution on a default simulator" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "id": "bc063bfc-de4b-4181-82b1-f805f86baa2e", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:20:36.347128Z", + "iopub.status.busy": "2024-05-07T15:20:36.345984Z", + "iopub.status.idle": "2024-05-07T15:21:50.459583Z", + "shell.execute_reply": "2024-05-07T15:21:50.458947Z" + }, + "tags": [], + "id": "bc063bfc-de4b-4181-82b1-f805f86baa2e" + }, + "outputs": [], + "source": [ + "from classiq import execute\n", + "\n", + "results = execute(qprog).result()" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "id": "05e682bd-0f1a-4e10-ba0b-e0bf3378fecd", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:21:50.462348Z", + "iopub.status.busy": "2024-05-07T15:21:50.461903Z", + "iopub.status.idle": "2024-05-07T15:21:50.464971Z", + "shell.execute_reply": "2024-05-07T15:21:50.464409Z" + }, + "tags": [], + "id": "05e682bd-0f1a-4e10-ba0b-e0bf3378fecd" + }, + "outputs": [], + "source": [ + "from classiq.execution import ExecutionDetails\n", + "\n", + "results = results[0].value" + ] + }, + { + "cell_type": "markdown", + "id": "8611351f-1b14-4969-878d-6f022cdfce2a", + "metadata": { + "id": "8611351f-1b14-4969-878d-6f022cdfce2a" + }, + "source": [ + "### 4.2. Presenting the Result's Count" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "id": "9c0ee98c-3ffa-4f1d-9cb2-4fada19b08b4", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:21:50.467938Z", + "iopub.status.busy": "2024-05-07T15:21:50.466973Z", + "iopub.status.idle": "2024-05-07T15:21:50.474468Z", + "shell.execute_reply": "2024-05-07T15:21:50.473904Z" + }, + "tags": [], + "id": "9c0ee98c-3ffa-4f1d-9cb2-4fada19b08b4", + "outputId": "dbdec0d4-3bef-487c-ce25-5761628ee8ab", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + } + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[{'phase': 0.46875}: 135341,\n", + " {'phase': 0.484375}: 36274,\n", + " {'phase': 0.453125}: 8283,\n", + " {'phase': 0.5}: 5402,\n", + " {'phase': 0.4375}: 2781,\n", + " {'phase': 0.515625}: 2139,\n", + " {'phase': 0.421875}: 1322,\n", + " {'phase': 0.53125}: 1110,\n", + " {'phase': 0.40625}: 793,\n", + " {'phase': 0.546875}: 692]" + ] + }, + "metadata": {}, + "execution_count": 71 + } + ], + "source": [ + "results.parsed_counts_of_outputs(\"phase\")[:10]" + ] + }, + { + "cell_type": "markdown", + "id": "41009d2c-4276-409b-b9f4-8dee8103f208", + "metadata": { + "id": "41009d2c-4276-409b-b9f4-8dee8103f208" + }, + "source": [ + "### 4.3. Chosing the Most Probable Solution\n", + "\n", + "Hereby the user will choose the number of eigenvalues they wish to extract from the poll of results. The\n", + "value `number_of_solutions` will determine how many results out of `qpe_results` will be analyzed.\n", + "The `parsed_counts` property is already sorted.\n", + "\n", + "We get the result in the `phase` variable already encoded as fixed point variable in the range [0,1]." + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "id": "ba022acc-738c-4685-a7ff-70ea2c400bfd", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:21:50.476943Z", + "iopub.status.busy": "2024-05-07T15:21:50.476435Z", + "iopub.status.idle": "2024-05-07T15:21:50.479735Z", + "shell.execute_reply": "2024-05-07T15:21:50.479163Z" + }, + "id": "ba022acc-738c-4685-a7ff-70ea2c400bfd" + }, + "outputs": [], + "source": [ + "number_of_solutions = 1 # to be set" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "id": "4a54cb17-8c0a-4b00-a3a3-6e276fa92b53", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:21:50.482120Z", + "iopub.status.busy": "2024-05-07T15:21:50.481642Z", + "iopub.status.idle": "2024-05-07T15:21:50.488542Z", + "shell.execute_reply": "2024-05-07T15:21:50.487983Z" + }, + "tags": [], + "id": "4a54cb17-8c0a-4b00-a3a3-6e276fa92b53", + "outputId": "52406be4-77d6-4bc1-e6f5-891113990de4", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Your qubit solution is\n", + "[{'phase': 0.46875}: 135341]\n" + ] + } + ], + "source": [ + "solutions = results.parsed_counts_of_outputs(\"phase\")[:number_of_solutions]\n", + "print(\"Your qubit solution is\", solutions, sep=\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "2f784e6f-d7ed-4cc9-81dd-f6b952d0dc01", + "metadata": { + "id": "2f784e6f-d7ed-4cc9-81dd-f6b952d0dc01" + }, + "source": [ + "### 4.4. Translating into Energy value (Phase)" + ] + }, + { + "cell_type": "markdown", + "id": "d83d16de-2450-4c7a-8093-26bf13d4dce4", + "metadata": { + "id": "d83d16de-2450-4c7a-8093-26bf13d4dce4" + }, + "source": [ + "Map the phase back into the original values, i.e. renormalized into it's original span." + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "836084e1-a20d-4a55-93cc-91a40c1d2f53", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:21:50.491382Z", + "iopub.status.busy": "2024-05-07T15:21:50.491220Z", + "iopub.status.idle": "2024-05-07T15:21:50.494025Z", + "shell.execute_reply": "2024-05-07T15:21:50.493447Z" + }, + "id": "836084e1-a20d-4a55-93cc-91a40c1d2f53" + }, + "outputs": [], + "source": [ + "def post_process_phase(phase):\n", + " return (\n", + " (phase * 2 * normalization_coeff) / (1 - (1 / 2**n_qpe))\n", + " ) - normalization_coeff" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "id": "a5bdb723-b015-4e80-98ea-985901c6c8d7", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:21:50.496211Z", + "iopub.status.busy": "2024-05-07T15:21:50.495859Z", + "iopub.status.idle": "2024-05-07T15:21:50.499028Z", + "shell.execute_reply": "2024-05-07T15:21:50.498455Z" + }, + "tags": [], + "id": "a5bdb723-b015-4e80-98ea-985901c6c8d7" + }, + "outputs": [], + "source": [ + "# renormalize into the \"real\" solution -\n", + "if normalize:\n", + " solution = [post_process_phase(value.state[\"phase\"]) for value in solutions]\n", + "else:\n", + " solution = phase" + ] + }, + { + "cell_type": "markdown", + "id": "6c963b82-26a7-4251-bae0-32e66c57fa1d", + "metadata": { + "id": "6c963b82-26a7-4251-bae0-32e66c57fa1d" + }, + "source": [ + "The final results of the Energy (matrix's eigenvlues) is therefore:" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "id": "43e8ec8f-2be9-403d-8ae9-9380fb2b08c9", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:21:50.501429Z", + "iopub.status.busy": "2024-05-07T15:21:50.500917Z", + "iopub.status.idle": "2024-05-07T15:21:50.504469Z", + "shell.execute_reply": "2024-05-07T15:21:50.503902Z" + }, + "tags": [], + "id": "43e8ec8f-2be9-403d-8ae9-9380fb2b08c9", + "outputId": "57fe6127-9b33-4cc5-ffcc-a121004cf862", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[-5.0500156710895965]\n" + ] + } + ], + "source": [ + "print(solution)" + ] + }, + { + "cell_type": "markdown", + "id": "7565aa1f-b8ba-4617-a2ef-79317261dfe7", + "metadata": { + "id": "7565aa1f-b8ba-4617-a2ef-79317261dfe7" + }, + "source": [ + "And the results including the error contributed from the resolution (number of qubits participating in the QPE) are:" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "id": "79f1c1ba-61fd-438e-a3d5-7606ea95e70f", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:21:50.506581Z", + "iopub.status.busy": "2024-05-07T15:21:50.506402Z", + "iopub.status.idle": "2024-05-07T15:21:50.510455Z", + "shell.execute_reply": "2024-05-07T15:21:50.509818Z" + }, + "tags": [], + "id": "79f1c1ba-61fd-438e-a3d5-7606ea95e70f", + "outputId": "d75f1d8a-8af0-48c8-a552-a37bf9fbf641", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "the resolution of result is 3.3666771140597356\n", + "the eneregy solution is beteen -8.416692785149332 and -1.683338557029861\n" + ] + } + ], + "source": [ + "if normalize:\n", + " energy_resolution = (\n", + " (1 / (2**n_qpe)) * 2 * normalization_coeff / (1 - (1 / 2**n_qpe))\n", + " )\n", + "else:\n", + " energy_resolution = 1 / (2**n_qpe)\n", + "\n", + "print(\"the resolution of result is\", energy_resolution)\n", + "\n", + "for sol in solution:\n", + " print(\n", + " \"the eneregy solution is beteen\",\n", + " sol - energy_resolution,\n", + " \"and\",\n", + " sol + energy_resolution,\n", + " )\n", + "\n", + " ###if zero or exceed the normalization range need to add conditions" + ] + }, + { + "cell_type": "markdown", + "id": "d570c6b0-bd32-40d1-9ebb-c1ee7c8663ad", + "metadata": { + "id": "d570c6b0-bd32-40d1-9ebb-c1ee7c8663ad" + }, + "source": [ + "### 4.4. Find Exact Solution for Comparison" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "id": "bd9e84a5-d131-4835-bade-13ba01035b44", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:21:50.512649Z", + "iopub.status.busy": "2024-05-07T15:21:50.512475Z", + "iopub.status.idle": "2024-05-07T15:21:50.516587Z", + "shell.execute_reply": "2024-05-07T15:21:50.515949Z" + }, + "tags": [], + "id": "bd9e84a5-d131-4835-bade-13ba01035b44", + "outputId": "7cfc9892-b918-4447-806d-f13493e84053", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "exact result: -3.940331561325765\n" + ] + } + ], + "source": [ + "mat = operator.to_matrix()\n", + "w, v = np.linalg.eig(mat)\n", + "print(\"exact result:\", np.real(min(w)))" + ] + }, + { + "cell_type": "markdown", + "id": "703c6ae7-5174-433f-ad9f-78f9864b1914", + "metadata": { + "id": "703c6ae7-5174-433f-ad9f-78f9864b1914" + }, + "source": [ + "### 4.4. Find the Solution's Histogram" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "id": "dfc5f725-495b-45d1-9c67-a1daf80a1454", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:21:50.519020Z", + "iopub.status.busy": "2024-05-07T15:21:50.518676Z", + "iopub.status.idle": "2024-05-07T15:21:50.523706Z", + "shell.execute_reply": "2024-05-07T15:21:50.523090Z" + }, + "tags": [], + "id": "dfc5f725-495b-45d1-9c67-a1daf80a1454" + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "energy_vec = []\n", + "energy_prob = []\n", + "\n", + "for value, counts in results.parsed_counts_of_outputs(\"phase\"):\n", + " temp = value[1][\"phase\"]\n", + " if normalize:\n", + " temp2 = (\n", + " temp * 2 * normalization_coeff / (1 - (1 / 2**n_qpe))\n", + " ) - normalization_coeff\n", + " else:\n", + " temp2 = temp\n", + " energy_vec.append(temp2)\n", + " energy_prob.append(counts[1] / num_shots)" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "id": "993c5b3b-7a05-44f1-9c4e-6651cd50f4cb", + "metadata": { + "execution": { + "iopub.execute_input": "2024-05-07T15:21:50.525902Z", + "iopub.status.busy": "2024-05-07T15:21:50.525629Z", + "iopub.status.idle": "2024-05-07T15:21:50.659434Z", + "shell.execute_reply": "2024-05-07T15:21:50.658856Z" + }, + "tags": [], + "id": "993c5b3b-7a05-44f1-9c4e-6651cd50f4cb", + "outputId": "640fb07e-7b78-45ad-958a-c447af80f9be", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 430 + } + }, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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qwgjAADAKsIIAACwijACAACsIowAAACrCCMAAMAqwggAALCKMAIAAKwijAAAAKsIIwAAwCrCCAAAsIowAgAArCKMAAAAqwgjAADAKsIIAACwijACAACsIowAAACrCCMAAMAqwggAALCKMAIAAKwijAAAAKsIIwAAwCrCCAAAsIowAgAArCKMAAAAqwgjAADAqlGFkYaGBhUUFCgjI0M+n0+tra1Dtt2+fbtKSkqUnZ2tGTNmqKioSD/84Q9HXTAAAJhckg4jTU1NCgQCqqur0969e1VYWKjy8nIdOXJk0PazZ8/W3XffrZaWFr388suqrq5WdXW1nn322XMuHgAApD6HMcYk08Hn82nFihXatGmTJCkWi8nr9Wrt2rVat27diPZxxRVXaOXKlfrWt741ovbRaFRut1uRSERZWVnJlAsAACwZ6ft3UiMj/f39amtrk9/vP70Dp1N+v18tLS1n7W+MUSgUUnt7u6655poh2/X19SkajSYsAABgckoqjPT09GhgYEAejydhvcfjUTgcHrJfJBLRzJkzlZ6erpUrV+rhhx/W9ddfP2T7YDAot9sdX7xebzJlAgCAFDIud9NceOGF2rdvn1588UXdf//9CgQC2rlz55Dta2pqFIlE4ktnZ+d4lAkAACy4IJnGOTk5SktLU3d3d8L67u5u5ebmDtnP6XTq0ksvlSQVFRVp//79CgaD+vSnPz1oe5fLJZfLlUxpAAAgRSU1MpKenq7i4mKFQqH4ulgsplAopLKyshHvJxaLqa+vL5lDAwCASSqpkRFJCgQCqqqqUklJiUpLS1VfX6/e3l5VV1dLkiorK5Wfn69gMCjpw/kfJSUluuSSS9TX16cdO3bohz/8oR555JGxPRMAAJCSkg4jFRUVOnr0qGpraxUOh1VUVKTm5ub4pNaOjg45nacHXHp7e/XlL39Zv/vd7zR9+nQtXrxYjz/+uCoqKsbuLAAAQMpK+jkjNvCcEQAAUs95ec4IAADAWCOMAAAAqwgjAADAKsIIAACwijACAACsIowAAACrCCMAAMAqwggAALCKMAIAAKwijAAAAKsIIwAAwCrCCAAAsIowAgAArCKMAAAAqwgjAADAKsIIAACwijACAACsIowAAACrCCMAAMAqwggAALCKMAIAAKwijAAAAKsIIwAAwCrCCAAAsIowAgAArCKMAAAAqwgjAADA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\n" + }, + "metadata": {} + } + ], + "source": [ + "plt.plot(energy_vec, energy_prob, \".\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "9797b512-d41f-47c1-8c0f-4134f0500b80", + "metadata": { + "id": "9797b512-d41f-47c1-8c0f-4134f0500b80" + }, + "source": [ + "## References\n", + "\n", + "[1]: [Michael A. Nielsen and Isaac L. Chuang. 2011. Quantum Computation and Quantum Information: 10th Anniversary Edition, Cambridge University Press, New York, NY, USA.\n", + "](http://mmrc.amss.cas.cn/tlb/201702/W020170224608149940643.pdf)\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# **Results for BeH2:**\n", + "\n", + "Your qubit solution is [{'phase': 0.46875}: 135341]\n", + "\n", + "The final results of the Energy (matrix's eigenvlues) is therefore:\n", + "\n", + "[-5.0500156710895965]\n", + "\n", + "exact result: -3.940331561325765\n", + "\n", + "The results including the error contributed from the resolution (number of qubits participating in the QPE) are: The resolution of result is 3.3666771140597356 the energy solution is between -8.416692785149332 and -1.683338557029861" + ], + "metadata": { + "id": "ttDDvHfPDI4y" + }, + "id": "ttDDvHfPDI4y" + }, + { + "cell_type": "markdown", + "source": [ + "# **Results for H2O:**\n", + "\n", + "Your qubit solution is\n", + "[{'phase': 0.453125}: 89076]\n", + "\n", + "The final results of the Energy (matrix's eigenvlues) is therefore:\n", + "\n", + "[-29.018825909142947]\n", + "\n", + "exact result: -23.54449724044351\n", + "\n", + "\n", + "The results including the error contributed from the resolution (number of qubits\n", + "participating in the QPE) are:\n", + "The resolution of result is 11.607530363657174\n", + "the energy solution is between -40.62635627280012 and -17.41129554548577\n", + "\n" + ], + "metadata": { + "id": "JvBCdhv08YSu" + }, + "id": "JvBCdhv08YSu" + }, + { + "cell_type": "markdown", + "source": [], + "metadata": { + "id": "PGUPJn2Y9Hxr" + }, + "id": "PGUPJn2Y9Hxr" + }, + { + "cell_type": "markdown", + "source": [], + "metadata": { + "id": "1xjsIzhx2iV1" + }, + "id": "1xjsIzhx2iV1" + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + }, + "colab": { + "provenance": [], + "include_colab_link": true + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file From 00261ead85c10d8ad8c5c7882cb6b0dd9144c066 Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Sat, 15 Jun 2024 04:48:53 +0200 Subject: [PATCH 11/18] Delete community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb --- ...Hisham_Mansour_HW4_qpe_for_molecules.ipynb | 1786 ----------------- 1 file changed, 1786 deletions(-) delete mode 100644 community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb diff --git a/community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb b/community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb deleted file mode 100644 index 81409e9b..00000000 --- a/community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb +++ /dev/null @@ -1,1786 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "view-in-github", - "colab_type": "text" - }, - "source": [ - "\"Open" - ] - }, - { - "cell_type": "markdown", - "id": "75e2c1fe-8a06-4f0b-8fd6-d1b6d10ce82f", - "metadata": { - "id": "75e2c1fe-8a06-4f0b-8fd6-d1b6d10ce82f" - }, - "source": [ - "# Quantum Phase Estimation (QPE) for Solving Molecular Energies\n", - "\n", - "\n", - "Quantum Phase Estimation (QPE) is a key algorithm in quantum computing, allowing one to estimate the phase (or eigenvalue) of an eigenvector of a unitary operation. The algorithm is designed so, that for a given Hamiltonian $H$, and an eigenvalue ${|\\psi\\rangle}$, the output that will be obtained is $\\epsilon$ where\n", - "\n", - "$U{|\\psi\\rangle} = e^{2\\pi i\\epsilon}{|\\psi\\rangle} , U = e^{2\\pi iH}$ .\n", - "\n", - "\n", - "Therefore, by measuring the phase accumulated, the QPE algorithm allows calculating the energies relating to the chosen initial state.\n", - "When using QPE for chemistry problems, it is common to search for the lowest energy of a given molecule. As the molecule can be written in the form of a Hamiltonian (Hermitian matrix which meaning is the energetic forces of the structure), usually symbolized by \"H\", one only need to insert the ground eigenvector in order to obtain the minimal energy value using QPE. However, obtaining the ground state is not a trivial problem. In order to overcome it, it is sufficient to use a state with big overlap with the ground state.\n", - "\n", - "We define a state ${|v\\rangle}$ which will be chosen as the algorithm's initial state. Let us define {$\\psi_i$} to be the set of (unknown) eigenvalues of $H$. Generally, any vector can be rewritten as a superposition of any basis set, thus -\n", - "\n", - "${|v\\rangle} = \\sum_i a_i{|\\psi_i\\rangle}$\n", - "\n", - "and -\n", - "\n", - "$U{|v\\rangle} = \\sum_i a_i e^{2\\pi i\\epsilon_i}{|\\psi_i\\rangle}$.\n", - "\n", - "where ${\\epsilon_i}$ are the eigenvalues of H, i.e. the span of energies relating to the molecule. Using execution with enough shots, one will obtain this set of $\\theta_i$, i.e., a subset of the Hamiltonian's eigenvalues. As we are specifically interested in $\\epsilon_0$, the ground state of H, it is important that there is a large overlap between ${\\psi_0}$ and ${|v\\rangle}$ so the probability to measure ${\\epsilon_0}$ is high, i.e.\n", - "\n", - "$P(\\epsilon_0) = |\\langle v|\\psi_0\\rangle|^2 > \\epsilon $.\n", - "\n", - "How large is $\\epsilon$? After execution, we will obtain a set of ${E_i}$.\n", - "If we have done 1000 shots of execution, and $P(\\epsilon_0)>1$, it should be measured is about 10 times to get a good statistical variance.\n", - "\n", - "A common choice for ${|v\\rangle}$ (the initial state) is the Hartree-Fock (HF) state, which with good probability have a large overlap with the ground state. However, other guesses for the initial state are possibly good or even better fit, and choosing the right initial state is a sort of art and an active field of research.\n", - "\n", - "For further reading about QPE we recommend [[1](#NC)].\n", - "\n", - "\n", - "#### What are the benefits of using QPE algorithm for finding a molecule's ground state?\n", - "\n", - "The two most prominent methods to solve ground energy for molecules are quantum variational algorithm (VQE) and QPE. Those promise better scalability compared to classical counterparts as the molecules becomes more complex, with larger number of electrons manifesting as more degrees of freedom for the problem.\n", - "\n", - "While so, the number of parameters in VQE is closely related to the number of electrons. This may create inherent difficulty achieving high-precision calculations through sampling statistical estimators, and paraphs even not converge for very large systems. While so, the number of parameters in QPE is a flexible value which is directly related to the resolution of the problem, but is not bonded with the number of electrons.\n", - "\n", - "Furthermore, it is known that advanced quantum algorithms based on QPE can perform electronic structure calculations in sub-exponential time with accuracy that rivals exact diagonalization methods. This guarantee of simultaneously achieving high accuracy, efficiency, and generality is a feat that is believed to be impossible for classical algorithms. For those reasons, VQE is applicable in the near term (NISQ) era, while QPE is suited for fault-tolerant design.\n", - "\n", - "#### During this tutorial, we will follow the QPE algorithms steps as following:\n", - "\n", - "a. Define a molecule and convert it into a Hamiltonian H, manifested as a pauli list.\n", - "\n", - "b. Prepare the Hamiltonian for QPE: including normalization and choosing the resolution.\n", - "\n", - "c. Initializing the state for the HF state.\n", - "\n", - "d. Preparing the quantum circuit.\n", - "\n", - "e. Executing the circuit to find the related phases and analyzing the results to find the ground state.\n", - "\n", - "f. Comparing the QPE results with exact solution for the molecule’s ground state." - ] - }, - { - "cell_type": "markdown", - "id": "7cd71faa-1ef3-4d67-8c9a-d66e0a895b9a", - "metadata": { - "id": "7cd71faa-1ef3-4d67-8c9a-d66e0a895b9a" - }, - "source": [ - "## 0. Pre-requirments\n", - "\n", - "The model is using several Classiq's libraries in addition to IBM's simulating tool." - ] - }, - { - "cell_type": "code", - "source": [ - "!pip install -U classiq" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "id": "k3DQRV9GpPSG", - "outputId": "4039a7c0-2b12-4e86-d14a-455090db8a57", - "collapsed": true - }, - "id": "k3DQRV9GpPSG", - "execution_count": 1, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Collecting classiq\n", - " Downloading classiq-0.42.1-py3-none-any.whl (401 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m401.5/401.5 kB\u001b[0m \u001b[31m5.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hCollecting ConfigArgParse<2.0.0,>=1.5.3 (from classiq)\n", - " Downloading ConfigArgParse-1.7-py3-none-any.whl (25 kB)\n", - "Collecting Pyomo<6.6,>=6.5 (from classiq)\n", - " Downloading Pyomo-6.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (10.7 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m10.7/10.7 MB\u001b[0m \u001b[31m32.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hCollecting black<25.0,>=24.0 (from classiq)\n", - " Downloading black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.8/1.8 MB\u001b[0m \u001b[31m45.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hCollecting httpx<1,>=0.23.0 (from classiq)\n", - " Downloading httpx-0.27.0-py3-none-any.whl (75 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.6/75.6 kB\u001b[0m \u001b[31m7.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: keyring<24.0.0,>=23.5.0 in /usr/lib/python3/dist-packages (from classiq) (23.5.0)\n", - "Requirement already satisfied: matplotlib<4.0.0,>=3.4.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (3.7.1)\n", - "Collecting networkx<3.0.0,>=2.5.1 (from classiq)\n", - " Downloading networkx-2.8.8-py3-none-any.whl (2.0 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m43.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: numexpr<3.0.0,>=2.7.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.10.0)\n", - "Requirement already satisfied: numpy<2.0.0,>=1.20.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.25.2)\n", - "Collecting packaging<23.0,>=22.0 (from classiq)\n", - " Downloading packaging-22.0-py3-none-any.whl (42 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m42.6/42.6 kB\u001b[0m \u001b[31m3.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: pandas<3.0.0,>=1.4.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.0.3)\n", - "Requirement already satisfied: plotly<6.0.0,>=5.7.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (5.15.0)\n", - "Collecting pydantic<2.0.0,>=1.9.1 (from classiq)\n", - " Downloading pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.1/3.1 MB\u001b[0m \u001b[31m33.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: scipy<2.0.0,>=1.10.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.11.4)\n", - "Collecting sympy<1.11.0,>=1.9.0 (from classiq)\n", - " Downloading sympy-1.10.1-py3-none-any.whl (6.4 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.4/6.4 MB\u001b[0m \u001b[31m21.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: tabulate<1,>=0.8.9 in /usr/local/lib/python3.10/dist-packages (from classiq) (0.9.0)\n", - "Requirement already satisfied: click>=8.0.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (8.1.7)\n", - "Collecting mypy-extensions>=0.4.3 (from black<25.0,>=24.0->classiq)\n", - " Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n", - "Collecting pathspec>=0.9.0 (from black<25.0,>=24.0->classiq)\n", - " Downloading pathspec-0.12.1-py3-none-any.whl (31 kB)\n", - "Requirement already satisfied: platformdirs>=2 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.2.2)\n", - "Requirement already satisfied: tomli>=1.1.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (2.0.1)\n", - "Requirement already satisfied: typing-extensions>=4.0.1 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.12.1)\n", - "Requirement already satisfied: anyio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7.1)\n", - "Requirement already satisfied: certifi in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (2024.6.2)\n", - "Collecting httpcore==1.* (from httpx<1,>=0.23.0->classiq)\n", - " Downloading httpcore-1.0.5-py3-none-any.whl (77 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.9/77.9 kB\u001b[0m \u001b[31m3.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: idna in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7)\n", - "Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (1.3.1)\n", - "Collecting h11<0.15,>=0.13 (from httpcore==1.*->httpx<1,>=0.23.0->classiq)\n", - " Downloading h11-0.14.0-py3-none-any.whl (58 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m2.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.2.1)\n", - "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (0.12.1)\n", - "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (4.53.0)\n", - "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.4.5)\n", - "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (9.4.0)\n", - "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (3.1.2)\n", - "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (2.8.2)\n", - "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2023.4)\n", - "Requirement already satisfied: tzdata>=2022.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2024.1)\n", - "Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from plotly<6.0.0,>=5.7.0->classiq) (8.3.0)\n", - "Collecting ply (from Pyomo<6.6,>=6.5->classiq)\n", - " Downloading ply-3.11-py2.py3-none-any.whl (49 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.6/49.6 kB\u001b[0m \u001b[31m3.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy<1.11.0,>=1.9.0->classiq) (1.3.0)\n", - "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.7->matplotlib<4.0.0,>=3.4.3->classiq) (1.16.0)\n", - "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio->httpx<1,>=0.23.0->classiq) (1.2.1)\n", - "Installing collected packages: ply, sympy, Pyomo, pydantic, pathspec, packaging, networkx, mypy-extensions, h11, ConfigArgParse, httpcore, black, httpx, classiq\n", - " Attempting uninstall: sympy\n", - " Found existing installation: sympy 1.12.1\n", - " Uninstalling sympy-1.12.1:\n", - " Successfully uninstalled sympy-1.12.1\n", - " Attempting uninstall: pydantic\n", - " Found existing installation: pydantic 2.7.3\n", - " Uninstalling pydantic-2.7.3:\n", - " Successfully uninstalled pydantic-2.7.3\n", - " Attempting uninstall: packaging\n", - " Found existing installation: packaging 24.0\n", - " Uninstalling packaging-24.0:\n", - " Successfully uninstalled packaging-24.0\n", - " Attempting uninstall: networkx\n", - " Found existing installation: networkx 3.3\n", - " Uninstalling networkx-3.3:\n", - " Successfully uninstalled networkx-3.3\n", - "\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", - "torch 2.3.0+cu121 requires nvidia-cublas-cu12==12.1.3.1; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cuda-cupti-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cuda-nvrtc-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cuda-runtime-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cudnn-cu12==8.9.2.26; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cufft-cu12==11.0.2.54; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-curand-cu12==10.3.2.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cusolver-cu12==11.4.5.107; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cusparse-cu12==12.1.0.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-nccl-cu12==2.20.5; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-nvtx-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\u001b[0m\u001b[31m\n", - "\u001b[0mSuccessfully installed ConfigArgParse-1.7 Pyomo-6.5.0 black-24.4.2 classiq-0.42.1 h11-0.14.0 httpcore-1.0.5 httpx-0.27.0 mypy-extensions-1.0.0 networkx-2.8.8 packaging-22.0 pathspec-0.12.1 ply-3.11 pydantic-1.10.15 sympy-1.10.1\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "import classiq\n", - "classiq.authenticate()" - ], - "metadata": { - "id": "Nsm3pKlqpZpr", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "c7a6175b-bfa2-4b6a-f067-36f48d33d94c" - }, - "id": "Nsm3pKlqpZpr", - "execution_count": 2, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Your user code: TJLL-VDWQ\n", - "If a browser doesn't automatically open, please visit this URL from any trusted device: https://auth.classiq.io/activate?user_code=TJLL-VDWQ\n" - ] - } - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "11eaf8f8-c06e-443e-ac74-5aa364f5198c", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:36.283533Z", - "iopub.status.busy": "2024-05-07T15:16:36.283079Z", - "iopub.status.idle": "2024-05-07T15:16:39.275433Z", - "shell.execute_reply": "2024-05-07T15:16:39.274629Z" - }, - "tags": [], - "id": "11eaf8f8-c06e-443e-ac74-5aa364f5198c" - }, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import scipy\n", - "from numpy import linalg as LA\n", - "\n", - "# for state preperation and phase estimation\n", - "from classiq import Constraints, Preferences\n", - "\n", - "# for chemistry\n", - "from classiq.applications.chemistry import Molecule, MoleculeProblem, PauliOperator" - ] - }, - { - "cell_type": "markdown", - "id": "ac537458-568d-4718-9020-408cc7232641", - "metadata": { - "id": "ac537458-568d-4718-9020-408cc7232641" - }, - "source": [ - "## 1. Create Your Molecule" - ] - }, - { - "cell_type": "markdown", - "source": [ - "### XYZ cartesian coordinates" - ], - "metadata": { - "id": "WC3NKxILHo6H" - }, - "id": "WC3NKxILHo6H" - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "2b67b2e1-94c2-4c8f-8ee9-577c79a7234f", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:39.279850Z", - "iopub.status.busy": "2024-05-07T15:16:39.279309Z", - "iopub.status.idle": "2024-05-07T15:16:39.288752Z", - "shell.execute_reply": "2024-05-07T15:16:39.288033Z" - }, - "tags": [], - "id": "2b67b2e1-94c2-4c8f-8ee9-577c79a7234f" - }, - "outputs": [], - "source": [ - "# build your molecule\n", - "\n", - "#hydrogen\n", - "molecule_H2 = Molecule(atoms=[(\"H\", (0.0, 0.0, 0)), (\"H\", (0.0, 0.0, 0.735))])\n", - "#oxygen\n", - "molecule_O2 = Molecule(atoms=[(\"O\", (0.0, 0.0, 0)), (\"O\", (0.0, 0.0, 1.16))])\n", - "#lithium hydride\n", - "molecule_LiH = Molecule(atoms=[(\"H\", (0.0, 0.0, 0.0)), (\"Li\", (0.0, 0.0, 1.596))])\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", - "#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", - "#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", - "#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))])" - ] - }, - { - "cell_type": "code", - "execution_count": 57, - "id": "9e37fada-9ecc-4a24-bf2c-0994e9c14149", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:39.293443Z", - "iopub.status.busy": "2024-05-07T15:16:39.292243Z", - "iopub.status.idle": "2024-05-07T15:16:39.297244Z", - "shell.execute_reply": "2024-05-07T15:16:39.296486Z" - }, - "tags": [], - "id": "9e37fada-9ecc-4a24-bf2c-0994e9c14149" - }, - "outputs": [], - "source": [ - "# define your molecule\n", - "#molecule = molecule_H2\n", - "#molecule = molecule_O2\n", - "#molecule = molecule_LiH\n", - "\n", - "molecule = molecule_BeH2\n", - "\n", - "#molecule = molecule_H2O\n", - "\n", - "#molecule = molecule_CO2\n", - "# The exponentiation constraints are not satisfiable.\n", - "# Minimal max_depth is 36476.\n", - "#molecule = molecule_CH3Cl\n", - "# The exponentiation constraints are not satisfiable.\n", - "# Minimal max_depth is 57965.\n", - "#molecule = molecule_C2H2\n", - "# The exponentiation constraints are not satisfiable.\n", - "# Minimal max_depth is 15115.\n", - "#molecule = molecule_C2H4\n", - "# The exponentiation constraints are not satisfiable.\n", - "# Minimal max_depth is 24471." - ] - }, - { - "cell_type": "markdown", - "source": [ - "# **Results for BeH2:**\n", - "\n", - "Your qubit solution is [{'phase': 0.46875}: 135341]\n", - "\n", - "The final results of the Energy (matrix's eigenvlues) is therefore:\n", - "\n", - "[-5.0500156710895965]\n", - "\n", - "exact result: -3.940331561325765\n", - "\n", - "The results including the error contributed from the resolution (number of qubits participating in the QPE) are: The resolution of result is 3.3666771140597356 the energy solution is between -8.416692785149332 and -1.683338557029861" - ], - "metadata": { - "id": "ClsUidSlHIsO" - }, - "id": "ClsUidSlHIsO" - }, - { - "cell_type": "markdown", - "source": [ - "# **Results for H2O:**\n", - "\n", - "Your qubit solution is\n", - "[{'phase': 0.453125}: 89076]\n", - "\n", - "The final results of the Energy (matrix's eigenvlues) is therefore:\n", - "\n", - "[-29.018825909142947]\n", - "\n", - "exact result: -23.54449724044351\n", - "\n", - "\n", - "The results including the error contributed from the resolution (number of qubits\n", - "participating in the QPE) are:\n", - "The resolution of result is 11.607530363657174\n", - "the energy solution is between -40.62635627280012 and -17.41129554548577\n", - "\n" - ], - "metadata": { - "id": "Cab7eyKPHSW8" - }, - "id": "Cab7eyKPHSW8" - }, - { - "cell_type": "code", - "execution_count": 58, - "id": "5d27e5df-e16e-44b2-b78a-187905577908", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:39.301806Z", - "iopub.status.busy": "2024-05-07T15:16:39.300600Z", - "iopub.status.idle": "2024-05-07T15:16:41.781375Z", - "shell.execute_reply": "2024-05-07T15:16:41.780596Z" - }, - "tags": [], - "id": "5d27e5df-e16e-44b2-b78a-187905577908", - "outputId": "7bad3408-043c-4a50-beb7-a0b2acfb6360", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - } - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Your Hamiltonian is\n", - "-0.702 * IIIIIII\n", - "-0.230 * ZIZZZIZ\n", - "-0.022 * IIIIIZX\n", - "+0.022 * ZIZZZZX\n", - "-0.251 * ZIIIZZI\n", - "-0.058 * ZIZZZXZ\n", - "+0.058 * IIZZIXZ\n", - "-0.857 * IIIZIII\n", - "-0.857 * IIZIIII\n", - "-0.495 * IIIIIIZ\n", - "-0.755 * IIIIIZI\n", - "-0.230 * ZZZZZII\n", - "-0.022 * ZXIIIII\n", - "+0.022 * IXZZZII\n", - "-0.251 * IIIIZII\n", - "+0.058 * YZZZYII\n", - "+0.058 * XZZZXII\n", - "-0.495 * IZIIIII\n", - "-0.755 * ZIIIIII\n", - "+0.062 * IIZZIZZ\n", - "+0.010 * IIIIIXI\n", - "-0.010 * ZIIIZXI\n", - "+0.172 * ZIZIZIZ\n", - "+0.172 * ZIIZZIZ\n", - "+0.159 * ZIZZZII\n", - "+0.093 * ZIZZZZZ\n", - "+0.012 * ZIIIZIX\n", - "-0.012 * IIZZIIX\n", - "+0.003 * ZIZZZYY\n", - "+0.020 * IIZZIXX\n", - "+0.017 * IIZZIYY\n", - "+0.017 * IIIIIYY\n", - "+0.020 * IIIIIXX\n", - "+0.003 * ZIIIZYY\n", - "+0.014 * IIIZIZX\n", - "-0.014 * ZIZIZZX\n", - "+0.014 * IIZIIZX\n", - "-0.014 * ZIIZZZX\n", - "+0.005 * IIIIIIX\n", - "-0.005 * ZIZZZIX\n", - "+0.202 * IZIIIIZ\n", - "+0.003 * ZZZZZZX\n", - "-0.003 * IZIIIZX\n", - "+0.041 * ZZIIXZZ\n", - "-0.041 * IIZZXZZ\n", - "-0.041 * ZZZZXII\n", - "+0.041 * IIIIXII\n", - "-0.011 * ZZZZXXI\n", - "+0.011 * IIIIXXI\n", - "-0.011 * IZIIYYZ\n", - "+0.011 * ZIZZYYZ\n", - "+0.012 * ZZIXIZZ\n", - "-0.012 * IIZXZZZ\n", - "-0.012 * IZZXZZI\n", - "+0.012 * ZIIXIZI\n", - "+0.012 * ZZXIIZZ\n", - "-0.012 * IIXZZZZ\n", - "-0.012 * IZXZZZI\n", - "+0.012 * ZIXIIZI\n", - "+0.003 * IXZZZIZ\n", - "-0.003 * ZXIIIIZ\n", - "+0.039 * ZXIIIZX\n", - "-0.039 * IXZZZZX\n", - "-0.011 * XIZZIZZ\n", - "+0.011 * XZIIZZZ\n", - "+0.011 * XIIIIII\n", - "-0.011 * XZZZZII\n", - "+0.014 * XIIIIXI\n", - "-0.014 * XZZZZXI\n", - "+0.014 * YIZZZYZ\n", - "-0.014 * YZIIIYZ\n", - "+0.103 * ZIZZIIZ\n", - "-0.012 * IIIIZZX\n", - "+0.012 * ZIZZIZX\n", - "+0.024 * IYIIYZZ\n", - "+0.024 * IXIIXZZ\n", - "-0.024 * IYZZYII\n", - "-0.024 * IXZZXII\n", - "-0.015 * IYZZYXI\n", - "-0.015 * IXZZXXI\n", - "+0.015 * ZYIIXYZ\n", - "-0.015 * ZXIIYYZ\n", - "-0.001 * XZIIXIZ\n", - "-0.001 * YZIIYIZ\n", - "-0.018 * YZZZYZX\n", - "-0.018 * XZZZXZX\n", - "-0.018 * XZIIXZX\n", - "-0.018 * YZIIYZX\n", - "-0.012 * IYIYIZZ\n", - "-0.012 * IXIXIZZ\n", - "+0.012 * ZYZYZZI\n", - "+0.012 * ZXZXZZI\n", - "-0.012 * IYYIIZZ\n", - "-0.012 * IXXIIZZ\n", - "+0.012 * ZYYZZZI\n", - "+0.012 * ZXXZZZI\n", - "+0.198 * ZZZZZIZ\n", - "-0.036 * YYZZIZZ\n", - "-0.036 * XXZZIZZ\n", - "+0.036 * YYIIIII\n", - "+0.036 * XXIIIII\n", - "+0.014 * YYIIIXI\n", - "+0.014 * XXIIIXI\n", - "-0.014 * XYZZZYZ\n", - "+0.014 * YXZZZYZ\n", - "+0.107 * IIZZZIZ\n", - "-0.009 * ZIIIIZX\n", - "+0.009 * IIZZZZX\n", - "+0.174 * ZIIZZZI\n", - "+0.174 * ZIZIZZI\n", - "+0.081 * ZIIIZZZ\n", - "+0.182 * ZIIIZII\n", - "+0.026 * ZIZIZXZ\n", - "-0.026 * IIZIIXZ\n", - "+0.026 * ZIIZZXZ\n", - "-0.026 * IIIZIXZ\n", - "+0.017 * ZIZZZXI\n", - "-0.017 * IIZZIXI\n", - "+0.103 * IZZZIZI\n", - "-0.001 * IZIIIXZ\n", - "+0.001 * ZZIIZXZ\n", - "+0.024 * IZIIYZY\n", - "-0.024 * ZIZZYZY\n", - "+0.024 * ZZIIXIX\n", - "-0.024 * IIZZXIX\n", - "-0.012 * IXIIZZI\n", - "+0.012 * ZXZZIZI\n", - "+0.018 * IXZZZXZ\n", - "-0.018 * ZXIIIXZ\n", - "-0.018 * ZXZZIXZ\n", - "+0.018 * IXIIZXZ\n", - "-0.015 * YIZZZZY\n", - "+0.015 * YZIIIZY\n", - "-0.015 * XIZZIIX\n", - "+0.015 * XZIIZIX\n", - "+0.231 * ZIIIIZI\n", - "-0.003 * ZIZZIXZ\n", - "+0.003 * IIZZZXZ\n", - "+0.004 * ZIIXXZI\n", - "+0.004 * ZIIYYZI\n", - "+0.004 * IIIYYII\n", - "+0.004 * IIIXXII\n", - "+0.004 * ZIXIXZI\n", - "+0.004 * ZIYIYZI\n", - "+0.004 * IIYIYII\n", - "+0.004 * IIXIXII\n", - "-0.021 * ZYIIXZY\n", - "+0.021 * ZXIIYZY\n", - "+0.021 * IYIIYIX\n", - "+0.021 * IXIIXIX\n", - "-0.003 * XZZZXZI\n", - "-0.003 * YZZZYZI\n", - "+0.041 * XZIIXXZ\n", - "+0.041 * YZIIYXZ\n", - "+0.003 * XZZXZZI\n", - "+0.003 * YZZYZZI\n", - "+0.003 * YZZYIII\n", - "+0.003 * XZZXIII\n", - "+0.003 * XZXZZZI\n", - "+0.003 * YZYZZZI\n", - "+0.003 * YZYZIII\n", - "+0.003 * XZXZIII\n", - "+0.102 * ZZIIZZI\n", - "-0.007 * ZZZZZXZ\n", - "+0.007 * IZZZIXZ\n", - "+0.024 * XYZZZZY\n", - "-0.024 * YXZZZZY\n", - "-0.024 * YYZZIIX\n", - "-0.024 * XXZZIIX\n", - "+0.223 * IIIIZZI\n", - "+0.389 * IIZZIII\n", - "+0.171 * IIIZIIZ\n", - "+0.191 * IIIZIZI\n", - "+0.172 * ZZZIZII\n", - "-0.012 * ZZIYIIY\n", - "+0.012 * IIZYZIY\n", - "-0.012 * ZZIXIIX\n", - "+0.012 * IIZXZIX\n", - "+0.014 * ZXIZIII\n", - "-0.014 * IXZIZII\n", - "+0.174 * IIIZZII\n", - "-0.003 * IIZXYYZ\n", - "+0.003 * IIZYXYZ\n", - "+0.003 * IIZYYXZ\n", - "+0.003 * IIZXXXZ\n", - "-0.026 * YZZIYII\n", - "-0.026 * XZZIXII\n", - "+0.012 * IIXXIII\n", - "+0.012 * IIYYIII\n", - "-0.013 * IYIXIIY\n", - "+0.013 * IXIYIIY\n", - "+0.013 * IYIYIIX\n", - "+0.013 * IXIXIIX\n", - "-0.004 * YZIXIYZ\n", - "+0.004 * XZIYIYZ\n", - "+0.004 * YZIYIXZ\n", - "+0.004 * XZIXIXZ\n", - "+0.171 * IZIZIII\n", - "+0.191 * ZIIZIII\n", - "+0.171 * IIZIIIZ\n", - "+0.191 * IIZIIZI\n", - "+0.172 * ZZIZZII\n", - "-0.012 * ZZYIIIY\n", - "+0.012 * IIYZZIY\n", - "-0.012 * ZZXIIIX\n", - "+0.012 * IIXZZIX\n", - "+0.014 * ZXZIIII\n", - "-0.014 * IXIZZII\n", - "+0.174 * IIZIZII\n", - "-0.003 * IIXZYYZ\n", - "+0.003 * IIYZXYZ\n", - "+0.003 * IIYZYXZ\n", - "+0.003 * IIXZXXZ\n", - "-0.026 * YZIZYII\n", - "-0.026 * XZIZXII\n", - "-0.013 * IYXIIIY\n", - "+0.013 * IXYIIIY\n", - "+0.013 * IYYIIIX\n", - "+0.013 * IXXIIIX\n", - "-0.004 * YZXIIYZ\n", - "+0.004 * XZYIIYZ\n", - "+0.004 * YZYIIXZ\n", - "+0.004 * XZXIIXZ\n", - "+0.171 * IZZIIII\n", - "+0.191 * ZIZIIII\n", - "+0.074 * IIIIIZZ\n", - "-0.036 * ZZZZXYY\n", - "+0.036 * IIIIXYY\n", - "-0.036 * ZZZZXXX\n", - "+0.036 * IIIIXXX\n", - "+0.014 * XIIIIYY\n", - "-0.014 * XZZZZYY\n", - "+0.014 * XIIIIXX\n", - "-0.014 * XZZZZXX\n", - "+0.102 * IIIIZIZ\n", - "-0.024 * IYZZYYY\n", - "-0.024 * IXZZXYY\n", - "-0.024 * IYZZYXX\n", - "-0.024 * IXZZXXX\n", - "+0.007 * YZZZYIZ\n", - "+0.007 * XZZZXIZ\n", - "+0.035 * YYIIIYY\n", - "+0.035 * XXIIIYY\n", - "+0.035 * YYIIIXX\n", - "+0.035 * XXIIIXX\n", - "+0.109 * ZIIIIIZ\n", - "+0.107 * ZZZZZZI\n", - "-0.009 * ZXIIIZI\n", - "+0.009 * IXZZZZI\n", - "+0.109 * IZIIIZI\n", - "+0.062 * ZZZZIII\n", - "+0.010 * XIIIXII\n", - "+0.010 * YIIIYII\n", - "+0.093 * IZZZZII\n", - "+0.012 * ZXIIZII\n", - "-0.012 * IXZZIII\n", - "+0.003 * XYZZYII\n", - "+0.020 * XXZZXII\n", - "+0.017 * YYZZXII\n", - "+0.017 * YYIIXII\n", - "+0.020 * XXIIXII\n", - "+0.003 * XYIIYII\n", - "+0.005 * IXIIIII\n", - "-0.005 * ZXZZZII\n", - "+0.081 * IZIIZII\n", - "-0.017 * YIZZYII\n", - "-0.017 * XIZZXII\n", - "+0.074 * ZZIIIII\n" - ] - } - ], - "source": [ - "# define your molecule problem\n", - "\n", - "gs_problem = MoleculeProblem(\n", - " molecule=molecule,\n", - " basis=\"sto3g\",\n", - " mapping=\"jordan_wigner\", #'bravyi_kitaev'\n", - " z2_symmetries=True,\n", - " freeze_core=True,\n", - ")\n", - "\n", - "operator = gs_problem.generate_hamiltonian()\n", - "gs_problem = gs_problem.update_problem(operator.num_qubits)\n", - "print(\"Your Hamiltonian is\", operator.show(), sep=\"\\n\")" - ] - }, - { - "cell_type": "code", - "execution_count": 59, - "id": "7a0b57c6-a057-41cb-8163-cc91d559bbdd", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:41.786010Z", - "iopub.status.busy": "2024-05-07T15:16:41.784773Z", - "iopub.status.idle": "2024-05-07T15:16:41.791592Z", - "shell.execute_reply": "2024-05-07T15:16:41.790923Z" - }, - "tags": [], - "id": "7a0b57c6-a057-41cb-8163-cc91d559bbdd", - "outputId": "1460479e-94e8-4c11-baa9-d0b96c9916b7", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - } - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Your Pauli list is\n", - "[('IIIIIII', (-0.7022930768258964+0j)), ('ZIZZZIZ', (-0.230190604546995+0j)), ('IIIIIZX', (-0.022105135983230894+0j)), ('ZIZZZZX', (0.022105135983230894+0j)), ('ZIIIZZI', (-0.25083590558353214+0j)), ('ZIZZZXZ', (-0.05762054716987154+0j)), ('IIZZIXZ', (0.05762054716987154+0j)), ('IIIZIII', (-0.8572771753840476+0j)), ('IIZIIII', (-0.8572771753840476+0j)), ('IIIIIIZ', (-0.49539136059267835+0j)), ('IIIIIZI', (-0.7554221157797676+0j)), ('ZZZZZII', (-0.23019060454699486+0j)), ('ZXIIIII', (-0.022105135983230894+0j)), ('IXZZZII', (0.022105135983230894+0j)), ('IIIIZII', (-0.2508359055835321+0j)), ('YZZZYII', (0.05762054716987154+0j)), ('XZZZXII', (0.05762054716987154+0j)), ('IZIIIII', (-0.4953913605926782+0j)), ('ZIIIIII', (-0.7554221157797675+0j)), ('IIZZIZZ', (0.06177536902294071+0j)), ('IIIIIXI', (0.009628629697052212+0j)), ('ZIIIZXI', (-0.009628629697052212+0j)), ('ZIZIZIZ', (0.1721312352568632+0j)), ('ZIIZZIZ', (0.17213123525686325+0j)), ('ZIZZZII', (0.15942306177427756+0j)), ('ZIZZZZZ', (0.09279153113235829+0j)), ('ZIIIZIX', (0.011782782608242623+0j)), ('IIZZIIX', (-0.011782782608242623+0j)), ('ZIZZZYY', (0.002973281387454195+0j)), ('IIZZIXX', (0.02038882910889495+0j)), ('IIZZIYY', (0.01741554772144075+0j)), ('IIIIIYY', (0.01741554772144075+0j)), ('IIIIIXX', (0.02038882910889495+0j)), ('ZIIIZYY', (0.002973281387454195+0j)), ('IIIZIZX', (0.014419981611826815+0j)), ('ZIZIZZX', (-0.014419981611826815+0j)), ('IIZIIZX', (0.01441998161182683+0j)), ('ZIIZZZX', (-0.01441998161182683+0j)), ('IIIIIIX', (0.004816137943065805+0j)), ('ZIZZZIX', (-0.004816137943065805+0j)), ('IZIIIIZ', (0.20240438090181115+0j)), ('ZZZZZZX', (0.002565939742358075+0j)), ('IZIIIZX', (-0.002565939742358075+0j)), ('ZZIIXZZ', (0.04108938500992233+0j)), ('IIZZXZZ', (-0.04108938500992233+0j)), ('ZZZZXII', (-0.04108938500992233+0j)), ('IIIIXII', (0.04108938500992233+0j)), ('ZZZZXXI', (-0.011051936749184695+0j)), ('IIIIXXI', (0.011051936749184695+0j)), ('IZIIYYZ', (-0.011051936749184695+0j)), ('ZIZZYYZ', (0.011051936749184695+0j)), ('ZZIXIZZ', (0.01234821063234333+0j)), ('IIZXZZZ', (-0.01234821063234333+0j)), ('IZZXZZI', (-0.01234821063234333+0j)), ('ZIIXIZI', (0.01234821063234333+0j)), ('ZZXIIZZ', (0.012348210632343334+0j)), ('IIXZZZZ', (-0.012348210632343334+0j)), ('IZXZZZI', (-0.012348210632343334+0j)), ('ZIXIIZI', (0.012348210632343334+0j)), ('IXZZZIZ', (0.002565939742358075+0j)), ('ZXIIIIZ', (-0.002565939742358075+0j)), ('ZXIIIZX', (0.038895655891840034+0j)), ('IXZZZZX', (-0.038895655891840034+0j)), ('XIZZIZZ', (-0.011051936749184699+0j)), ('XZIIZZZ', (0.011051936749184699+0j)), ('XIIIIII', (0.011051936749184699+0j)), ('XZZZZII', (-0.011051936749184699+0j)), ('XIIIIXI', (0.014149650962831172+0j)), ('XZZZZXI', (-0.014149650962831172+0j)), ('YIZZZYZ', (0.014149650962831172+0j)), ('YZIIIYZ', (-0.014149650962831172+0j)), ('ZIZZIIZ', (0.10286475403286305+0j)), ('IIIIZZX', (-0.011879666226520692+0j)), ('ZIZZIZX', (0.011879666226520692+0j)), ('IYIIYZZ', (0.023662448834763317+0j)), ('IXIIXZZ', (0.023662448834763317+0j)), ('IYZZYII', (-0.023662448834763317+0j)), ('IXZZXII', (-0.023662448834763317+0j)), ('IYZZYXI', (-0.015307708024581802+0j)), ('IXZZXXI', (-0.015307708024581802+0j)), ('ZYIIXYZ', (0.015307708024581802+0j)), ('ZXIIYYZ', (-0.015307708024581802+0j)), ('XZIIXIZ', (-0.0014233070521324851+0j)), ('YZIIYIZ', (-0.0014233070521324851+0j)), ('YZZZYZX', (-0.018280989412035993+0j)), ('XZZZXZX', (-0.018280989412035993+0j)), ('XZIIXZX', (-0.018280989412035993+0j)), ('YZIIYZX', (-0.018280989412035993+0j)), ('IYIYIZZ', (-0.01185327361540123+0j)), ('IXIXIZZ', (-0.01185327361540123+0j)), ('ZYZYZZI', (0.01185327361540123+0j)), ('ZXZXZZI', (0.01185327361540123+0j)), ('IYYIIZZ', (-0.011853273615401231+0j)), ('IXXIIZZ', (-0.011853273615401231+0j)), ('ZYYZZZI', (0.011853273615401231+0j)), ('ZXXZZZI', (0.011853273615401231+0j)), ('ZZZZZIZ', (0.19831871766611753+0j)), ('YYZZIZZ', (-0.03569653713347675+0j)), ('XXZZIZZ', (-0.03569653713347675+0j)), ('YYIIIII', (0.03569653713347675+0j)), ('XXIIIII', (0.03569653713347675+0j)), ('YYIIIXI', (0.01389796708217946+0j)), ('XXIIIXI', (0.01389796708217946+0j)), ('XYZZZYZ', (-0.01389796708217946+0j)), ('YXZZZYZ', (0.01389796708217946+0j)), ('IIZZZIZ', (0.10694118209518946+0j)), ('ZIIIIZX', (-0.009081829139113658+0j)), ('IIZZZZX', (0.009081829139113658+0j)), ('ZIIZZZI', (0.1744698035079175+0j)), ('ZIZIZZI', (0.17446980350791766+0j)), ('ZIIIZZZ', (0.0810458258950273+0j)), ('ZIIIZII', (0.18200001297184848+0j)), ('ZIZIZXZ', (0.026286745525201403+0j)), ('IIZIIXZ', (-0.026286745525201403+0j)), ('ZIIZZXZ', (0.026286745525201403+0j)), ('IIIZIXZ', (-0.026286745525201403+0j)), ('ZIZZZXI', (0.017265081835497856+0j)), ('IIZZIXI', (-0.017265081835497856+0j)), ('IZZZIZI', (0.10286475403286305+0j)), ('IZIIIXZ', (-0.0014233070521324851+0j)), ('ZZIIZXZ', (0.0014233070521324851+0j)), ('IZIIYZY', (0.023662448834763317+0j)), ('ZIZZYZY', (-0.023662448834763317+0j)), ('ZZIIXIX', (0.023662448834763317+0j)), ('IIZZXIX', (-0.023662448834763317+0j)), ('IXIIZZI', (-0.011879666226520692+0j)), ('ZXZZIZI', (0.011879666226520692+0j)), ('IXZZZXZ', (0.018280989412035993+0j)), ('ZXIIIXZ', (-0.018280989412035993+0j)), ('ZXZZIXZ', (-0.018280989412035993+0j)), ('IXIIZXZ', (0.018280989412035993+0j)), ('YIZZZZY', (-0.015307708024581803+0j)), ('YZIIIZY', (0.015307708024581803+0j)), ('XIZZIIX', (-0.015307708024581803+0j)), ('XZIIZIX', (0.015307708024581803+0j)), ('ZIIIIZI', (0.23075467521596388+0j)), ('ZIZZIXZ', (-0.002551353102471067+0j)), ('IIZZZXZ', (0.002551353102471067+0j)), ('ZIIXXZI', (0.0036560013958361033+0j)), ('ZIIYYZI', (0.0036560013958361033+0j)), ('IIIYYII', (0.0036560013958361033+0j)), ('IIIXXII', (0.0036560013958361033+0j)), ('ZIXIXZI', (0.0036560013958361033+0j)), ('ZIYIYZI', (0.0036560013958361033+0j)), ('IIYIYII', (0.0036560013958361033+0j)), ('IIXIXII', (0.0036560013958361033+0j)), ('ZYIIXZY', (-0.020873062000978698+0j)), ('ZXIIYZY', (0.020873062000978698+0j)), ('IYIIYIX', (0.020873062000978698+0j)), ('IXIIXIX', (0.020873062000978698+0j)), ('XZZZXZI', (-0.0025513531024710665+0j)), ('YZZZYZI', (-0.0025513531024710665+0j)), ('XZIIXXZ', (0.04125144772662373+0j)), ('YZIIYXZ', (0.04125144772662373+0j)), ('XZZXZZI', (0.0034405062273070984+0j)), ('YZZYZZI', (0.0034405062273070984+0j)), ('YZZYIII', (0.0034405062273070984+0j)), ('XZZXIII', (0.0034405062273070984+0j)), ('XZXZZZI', (0.0034405062273070992+0j)), ('YZYZZZI', (0.0034405062273070992+0j)), ('YZYZIII', (0.0034405062273070992+0j)), ('XZXZIII', (0.0034405062273070992+0j)), ('ZZIIZZI', (0.10191888789600599+0j)), ('ZZZZZXZ', (-0.006564129606561605+0j)), ('IZZZIXZ', (0.006564129606561605+0j)), ('XYZZZZY', (0.02382921144205946+0j)), ('YXZZZZY', (-0.02382921144205946+0j)), ('YYZZIIX', (-0.02382921144205946+0j)), ('XXZZIIX', (-0.02382921144205946+0j)), ('IIIIZZI', (0.22325146069847226+0j)), ('IIZZIII', (0.3892355930337423+0j)), ('IIIZIIZ', (0.17086285707799762+0j)), ('IIIZIZI', (0.19133630882633207+0j)), ('ZZZIZII', (0.1721312352568632+0j)), ('ZZIYIIY', (-0.01185327361540123+0j)), ('IIZYZIY', (0.01185327361540123+0j)), ('ZZIXIIX', (-0.01185327361540123+0j)), ('IIZXZIX', (0.01185327361540123+0j)), ('ZXIZIII', (0.014419981611826815+0j)), ('IXZIZII', (-0.014419981611826815+0j)), ('IIIZZII', (0.1744698035079175+0j)), ('IIZXYYZ', (-0.0034405062273070984+0j)), ('IIZYXYZ', (0.0034405062273070984+0j)), ('IIZYYXZ', (0.0034405062273070984+0j)), ('IIZXXXZ', (0.0034405062273070984+0j)), ('YZZIYII', (-0.026286745525201403+0j)), ('XZZIXII', (-0.026286745525201403+0j)), ('IIXXIII', (0.012124689610585541+0j)), ('IIYYIII', (0.012124689610585541+0j)), ('IYIXIIY', (-0.012722452161354642+0j)), ('IXIYIIY', (0.012722452161354642+0j)), ('IYIYIIX', (0.012722452161354642+0j)), ('IXIXIIX', (0.012722452161354642+0j)), ('YZIXIYZ', (-0.004138154161062567+0j)), ('XZIYIYZ', (0.004138154161062567+0j)), ('YZIYIXZ', (0.004138154161062567+0j)), ('XZIXIXZ', (0.004138154161062567+0j)), ('IZIZIII', (0.17086285707799762+0j)), ('ZIIZIII', (0.19133630882633207+0j)), ('IIZIIIZ', (0.17086285707799764+0j)), ('IIZIIZI', (0.19133630882633207+0j)), ('ZZIZZII', (0.17213123525686325+0j)), ('ZZYIIIY', (-0.011853273615401231+0j)), ('IIYZZIY', (0.011853273615401231+0j)), ('ZZXIIIX', (-0.011853273615401231+0j)), ('IIXZZIX', (0.011853273615401231+0j)), ('ZXZIIII', (0.01441998161182683+0j)), ('IXIZZII', (-0.01441998161182683+0j)), ('IIZIZII', (0.17446980350791766+0j)), ('IIXZYYZ', (-0.0034405062273070992+0j)), ('IIYZXYZ', (0.0034405062273070992+0j)), ('IIYZYXZ', (0.0034405062273070992+0j)), ('IIXZXXZ', (0.0034405062273070992+0j)), ('YZIZYII', (-0.026286745525201403+0j)), ('XZIZXII', (-0.026286745525201403+0j)), ('IYXIIIY', (-0.012722452161354645+0j)), ('IXYIIIY', (0.012722452161354645+0j)), ('IYYIIIX', (0.012722452161354645+0j)), ('IXXIIIX', (0.012722452161354645+0j)), ('YZXIIYZ', (-0.004138154161062567+0j)), ('XZYIIYZ', (0.004138154161062567+0j)), ('YZYIIXZ', (0.004138154161062567+0j)), ('XZXIIXZ', (0.004138154161062567+0j)), ('IZZIIII', (0.17086285707799764+0j)), ('ZIZIIII', (0.19133630882633207+0j)), ('IIIIIZZ', (0.07373286867690823+0j)), ('ZZZZXYY', (-0.035696537133476744+0j)), ('IIIIXYY', (0.035696537133476744+0j)), ('ZZZZXXX', (-0.035696537133476744+0j)), ('IIIIXXX', (0.035696537133476744+0j)), ('XIIIIYY', (0.013897967082179458+0j)), ('XZZZZYY', (-0.013897967082179458+0j)), ('XIIIIXX', (0.013897967082179458+0j)), ('XZZZZXX', (-0.013897967082179458+0j)), ('IIIIZIZ', (0.10191888789600599+0j)), ('IYZZYYY', (-0.02382921144205946+0j)), ('IXZZXYY', (-0.02382921144205946+0j)), ('IYZZYXX', (-0.02382921144205946+0j)), ('IXZZXXX', (-0.02382921144205946+0j)), ('YZZZYIZ', (0.006564129606561605+0j)), ('XZZZXIZ', (0.006564129606561605+0j)), ('YYIIIYY', (0.0351660524024311+0j)), ('XXIIIYY', (0.0351660524024311+0j)), ('YYIIIXX', (0.0351660524024311+0j)), ('XXIIIXX', (0.0351660524024311+0j)), ('ZIIIIIZ', (0.10889892107933934+0j)), ('ZZZZZZI', (0.10694118209518946+0j)), ('ZXIIIZI', (-0.009081829139113658+0j)), ('IXZZZZI', (0.009081829139113658+0j)), ('IZIIIZI', (0.10889892107933934+0j)), ('ZZZZIII', (0.06177536902294071+0j)), ('XIIIXII', (0.009628629697052212+0j)), ('YIIIYII', (0.009628629697052212+0j)), ('IZZZZII', (0.09279153113235829+0j)), ('ZXIIZII', (0.011782782608242623+0j)), ('IXZZIII', (-0.011782782608242623+0j)), ('XYZZYII', (0.002973281387454195+0j)), ('XXZZXII', (0.02038882910889495+0j)), ('YYZZXII', (0.01741554772144075+0j)), ('YYIIXII', (0.01741554772144075+0j)), ('XXIIXII', (0.02038882910889495+0j)), ('XYIIYII', (0.002973281387454195+0j)), ('IXIIIII', (0.004816137943065805+0j)), ('ZXZZZII', (-0.004816137943065805+0j)), ('IZIIZII', (0.0810458258950273+0j)), ('YIZZYII', (-0.017265081835497856+0j)), ('XIZZXII', (-0.017265081835497856+0j)), ('ZZIIIII', (0.07373286867690823+0j))]\n" - ] - } - ], - "source": [ - "pauli_ops = operator.pauli_list\n", - "N = operator.num_qubits\n", - "print(\"Your Pauli list is\", pauli_ops, sep=\"\\n\")" - ] - }, - { - "cell_type": "markdown", - "id": "685f4a01-caf3-4d0c-b9f3-4fc89bc5192a", - "metadata": { - "id": "685f4a01-caf3-4d0c-b9f3-4fc89bc5192a" - }, - "source": [ - "## 2. Preparing the Molecule for QPE" - ] - }, - { - "cell_type": "markdown", - "id": "1b1bafad-d35c-4504-9665-02b0ae86d52f", - "metadata": { - "id": "1b1bafad-d35c-4504-9665-02b0ae86d52f" - }, - "source": [ - "### 2.1 Chose the Algorithm's Precision\n", - "\n", - "For QPE algorithms, the precision is set by the number of qubits chosen $n$, such that the resolution is $1/{2^n}$. In case the matrix needs to be normlized, the resolution will be distorted. In case of normalization, that the span of results in the QPE is strached between the lowest and highest possible phase, thus the reslution will be mapped to $normalization-coefficient/{2^n} ~\\sim 1/{((\\lambda_{max}-\\lambda_{min})*2^n)}$.\n", - "\n", - "Here you can chose the precision in the parameter `n_qpe`, or by setting your desired resolution. If you chose your desired resolution and set the parameter `get_recommended_n` to be True, the number of qubits will be calculated for you accordingly.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 60, - "id": "4e96164f-aa00-4723-9f59-b1c13ccb58d8", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:41.796364Z", - "iopub.status.busy": "2024-05-07T15:16:41.795124Z", - "iopub.status.idle": "2024-05-07T15:16:41.800121Z", - "shell.execute_reply": "2024-05-07T15:16:41.799301Z" - }, - "tags": [], - "id": "4e96164f-aa00-4723-9f59-b1c13ccb58d8" - }, - "outputs": [], - "source": [ - "# `n_qpe`- The precision of the QPE (the number of qubits to be used in the QPE. Creates resolution of 1/2^n_qpe\n", - "n_qpe = 6" - ] - }, - { - "cell_type": "code", - "execution_count": 61, - "id": "74aeea8b-1e16-408f-bc5f-c5888b552a6f", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:41.804701Z", - "iopub.status.busy": "2024-05-07T15:16:41.803523Z", - "iopub.status.idle": "2024-05-07T15:16:41.810737Z", - "shell.execute_reply": "2024-05-07T15:16:41.810086Z" - }, - "tags": [], - "id": "74aeea8b-1e16-408f-bc5f-c5888b552a6f" - }, - "outputs": [], - "source": [ - "# recommanded n_qpe:\n", - "get_recommanded_n = False\n", - "\n", - "import math\n", - "\n", - "desired_resolution = 0.02\n", - "\n", - "\n", - "def get_nqpe(pauli_operator, desired_resolution):\n", - " N = pauli_operator.num_qubits\n", - " A = 0\n", - " for a, b in pauli_operator.pauli_list:\n", - " A = A + abs(b)\n", - " nqpe = math.log2(2 * N * A / desired_resolution)\n", - " return math.ceil(nqpe)\n", - "\n", - "\n", - "if get_recommanded_n:\n", - " n_qpe = get_nqpe(operator, desired_resolution)\n", - " print(\"number of qubits for QPE is\", n_qpe)" - ] - }, - { - "cell_type": "markdown", - "id": "fa3d1079-c12b-48db-8935-1ea059fdbce9", - "metadata": { - "id": "fa3d1079-c12b-48db-8935-1ea059fdbce9" - }, - "source": [ - "### 2.3 Normalize the Matrix\n", - "\n", - "As QPE obtains a phase in the form $e^{2\\pi i\\theta}$, there is meaning only for $\\theta \\in [0,2\\pi)$. Generally, our matrix M can have any eigenvalue, thus \\theta can have any value. In order to fix this discrepancy, the values of the matrix are stretched to be rescaled. We assume\n", - "$\\theta \\in [\\lambda_{min}, \\lambda_{max}]$\n", - "and use a normalization function in order to map those values into $[0, 1-1/{2^n}]$, where n is the number of qubits chosen for the QPE process in section 2.2.\n", - "\n", - "We perform the normalization procedure as following:\n", - "\n", - "a. We evaluate $\\lambda_{min},\\lambda_{max}$ (in the function ` normalization_params()` below). In order to do so we use rough estimation of the absolute max value that can take place by adding together all the pauli coefficients and multiplying by the matrix's dimensions. That will yield us a value $\\lambda$ (which is referred in the code as `normalization_coeff`) and we now assume that the domain is $\\theta \\in [-\\lambda, \\lambda]$.\n", - "In general, one can build a more accurate assessment, which will decrease the span of solutions and thus achieve a better resolution.\n", - "\n", - "b. We make sure only positive values are available by adding $\\lambda*I^n$ to the pauli list. Now our evaluated span is $[0, 2*\\lambda]$.\n", - "\n", - "c. We normlize our matrix by multiplying all of the pauli coefficients by $(1-1/2^n)/(2*\\lambda)$. Now the span of $\\theta$ is $[0, 1-1/2^n]$, as required for proper QPE process.\n", - "\n", - "The values of the matrix's eigenvalues should be now between $0$ to $1-(1/2^n)$. The QPE procedure will be performed on this new normalized matrix. After the phases are obtained, the original phases of the pre-normalized matrix will be gathered by performing opposite steps to this normalization procedure.\n", - "\n", - "* Note that in case your matrix's eigenvalues are naturally between the values $0$ to $1-(1/2^n)$, you may not want to normalize it, as the normalization procedure may enlarge the span, thus lowering the resolution of the agorithm. In that case, you may skip those lines or change the value `normalize` to False." - ] - }, - { - "cell_type": "code", - "execution_count": 62, - "id": "70d8b16f-5f50-4272-9b7b-0ca7cad00b60", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:41.815396Z", - "iopub.status.busy": "2024-05-07T15:16:41.814254Z", - "iopub.status.idle": "2024-05-07T15:16:41.824473Z", - "shell.execute_reply": "2024-05-07T15:16:41.823778Z" - }, - "tags": [], - "id": "70d8b16f-5f50-4272-9b7b-0ca7cad00b60", - "outputId": "4c9491de-b9f5-4855-edac-2798e3def5ab", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - } - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "[('IIIIIII', (0.4889281053643878+0j)), ('ZIZZZIZ', (-0.0010683317925043465+0j)), ('IIIIIZX', (-0.00010259158750198293+0j)), ('ZIZZZZX', (0.00010259158750198293+0j)), ('ZIIIZZI', (-0.001164148176959137+0j)), ('ZIZZZXZ', (-0.0002674212640616383+0j)), ('IIZZIXZ', (0.0002674212640616383+0j)), ('IIIZIII', (-0.003978687415385471+0j)), ('IIZIIII', (-0.003978687415385471+0j)), ('IIIIIIZ', (-0.0022991483136102307+0j)), ('IIIIIZI', (-0.0035059704744971982+0j)), ('ZZZZZII', (-0.0010683317925043458+0j)), ('ZXIIIII', (-0.00010259158750198293+0j)), ('IXZZZII', (0.00010259158750198293+0j)), ('IIIIZII', (-0.0011641481769591368+0j)), ('YZZZYII', (0.0002674212640616383+0j)), ('XZZZXII', (0.0002674212640616383+0j)), ('IZIIIII', (-0.0022991483136102302+0j)), ('ZIIIIII', (-0.003505970474497198+0j)), ('IIZZIZZ', (0.0002867041026751466+0j)), ('IIIIIXI', (4.46871897480607e-05+0j)), ('ZIIIZXI', (-4.46871897480607e-05+0j)), ('ZIZIZIZ', (0.0007988739221995871+0j)), ('ZIIZZIZ', (0.0007988739221995873+0j)), ('ZIZZZII', (0.0007398943396800271+0j)), ('ZIZZZZZ', (0.00043065242814294217+0j)), ('ZIIIZIX', (5.4684774338750076e-05+0j)), ('IIZZIIX', (-5.4684774338750076e-05+0j)), ('ZIZZZYY', (1.3799221043490745e-05+0j)), ('IIZZIXX', (9.462607907840818e-05+0j)), ('IIZZIYY', (8.082685803491741e-05+0j)), ('IIIIIYY', (8.082685803491741e-05+0j)), ('IIIIIXX', (9.462607907840818e-05+0j)), ('ZIIIZYY', (1.3799221043490745e-05+0j)), ('IIIZIZX', (6.69242119310632e-05+0j)), ('ZIZIZZX', (-6.69242119310632e-05+0j)), ('IIZIIZX', (6.692421193106327e-05+0j)), ('ZIIZZZX', (-6.692421193106327e-05+0j)), ('IIIIIIX', (2.2352055991986643e-05+0j)), ('ZIZZZIX', (-2.2352055991986643e-05+0j)), ('IZIIIIZ', (0.0009393738527474023+0j)), ('ZZZZZZX', (1.1908718037411872e-05+0j)), ('IZIIIZX', (-1.1908718037411872e-05+0j)), ('ZZIIXZZ', (0.00019069890548721176+0j)), ('IIZZXZZ', (-0.00019069890548721176+0j)), ('ZZZZXII', (-0.00019069890548721176+0j)), ('IIIIXII', (0.00019069890548721176+0j)), ('ZZZZXXI', (-5.1292864107712246e-05+0j)), ('IIIIXXI', (5.1292864107712246e-05+0j)), ('IZIIYYZ', (-5.1292864107712246e-05+0j)), ('ZIZZYYZ', (5.1292864107712246e-05+0j)), ('ZZIXIZZ', (5.7308968039915556e-05+0j)), ('IIZXZZZ', (-5.7308968039915556e-05+0j)), ('IZZXZZI', (-5.7308968039915556e-05+0j)), ('ZIIXIZI', (5.7308968039915556e-05+0j)), ('ZZXIIZZ', (5.7308968039915576e-05+0j)), ('IIXZZZZ', (-5.7308968039915576e-05+0j)), ('IZXZZZI', (-5.7308968039915576e-05+0j)), ('ZIXIIZI', (5.7308968039915576e-05+0j)), ('IXZZZIZ', (1.1908718037411872e-05+0j)), ('ZXIIIIZ', (-1.1908718037411872e-05+0j)), ('ZXIIIZX', (0.0001805176447637257+0j)), ('IXZZZZX', (-0.0001805176447637257+0j)), ('XIZZIZZ', (-5.129286410771227e-05+0j)), ('XZIIZZZ', (5.129286410771227e-05+0j)), ('XIIIIII', (5.129286410771227e-05+0j)), ('XZZZZII', (-5.129286410771227e-05+0j)), ('XIIIIXI', (6.56695871935387e-05+0j)), ('XZZZZXI', (-6.56695871935387e-05+0j)), ('YIZZZYZ', (6.56695871935387e-05+0j)), ('YZIIIYZ', (-6.56695871935387e-05+0j)), ('ZIZZIIZ', (0.00047740300816235837+0j)), ('IIIIZZX', (-5.5134418449042965e-05+0j)), ('ZIZZIZX', (5.5134418449042965e-05+0j)), ('IYIIYZZ', (0.00010981919278779304+0j)), ('IXIIXZZ', (0.00010981919278779304+0j)), ('IYZZYII', (-0.00010981919278779304+0j)), ('IXZZXII', (-0.00010981919278779304+0j)), ('IYZZYXI', (-7.104421653185207e-05+0j)), ('IXZZXXI', (-7.104421653185207e-05+0j)), ('ZYIIXYZ', (7.104421653185207e-05+0j)), ('ZXIIYYZ', (-7.104421653185207e-05+0j)), ('XZIIXIZ', (-6.605674359651552e-06+0j)), ('YZIIYIZ', (-6.605674359651552e-06+0j)), ('YZZZYZX', (-8.48434375753428e-05+0j)), ('XZZZXZX', (-8.48434375753428e-05+0j)), ('XZIIXZX', (-8.48434375753428e-05+0j)), ('YZIIYZX', (-8.48434375753428e-05+0j)), ('IYIYIZZ', (-5.5011928369130214e-05+0j)), ('IXIXIZZ', (-5.5011928369130214e-05+0j)), ('ZYZYZZI', (5.5011928369130214e-05+0j)), ('ZXZXZZI', (5.5011928369130214e-05+0j)), ('IYYIIZZ', (-5.501192836913023e-05+0j)), ('IXXIIZZ', (-5.501192836913023e-05+0j)), ('ZYYZZZI', (5.501192836913023e-05+0j)), ('ZXXZZZI', (5.501192836913023e-05+0j)), ('ZZZZZIZ', (0.0009204119844437524+0j)), ('YYZZIZZ', (-0.00016567029561026026+0j)), ('XXZZIZZ', (-0.00016567029561026026+0j)), ('YYIIIII', (0.00016567029561026026+0j)), ('XXIIIII', (0.00016567029561026026+0j)), ('YYIIIXI', (6.450150350093865e-05+0j)), ('XXIIIXI', (6.450150350093865e-05+0j)), ('XYZZZYZ', (-6.450150350093865e-05+0j)), ('YXZZZYZ', (6.450150350093865e-05+0j)), ('IIZZZIZ', (0.0004963220153364809+0j)), ('ZIIIIZX', (-4.214944750895202e-05+0j)), ('IIZZZZX', (4.214944750895202e-05+0j)), ('ZIIZZZI', (0.0008097273921596632+0j)), ('ZIZIZZI', (0.000809727392159664+0j)), ('ZIIIZZZ', (0.0003761397326525245+0j)), ('ZIIIZII', (0.0008446756568395633+0j)), ('ZIZIZXZ', (0.00012199874978090467+0j)), ('IIZIIXZ', (-0.00012199874978090467+0j)), ('ZIIZZXZ', (0.00012199874978090467+0j)), ('IIIZIXZ', (-0.00012199874978090467+0j)), ('ZIZZZXI', (8.012853461743272e-05+0j)), ('IIZZIXI', (-8.012853461743272e-05+0j)), ('IZZZIZI', (0.00047740300816235837+0j)), ('IZIIIXZ', (-6.605674359651552e-06+0j)), ('ZZIIZXZ', (6.605674359651552e-06+0j)), ('IZIIYZY', (0.00010981919278779304+0j)), ('ZIZZYZY', (-0.00010981919278779304+0j)), ('ZZIIXIX', (0.00010981919278779304+0j)), ('IIZZXIX', (-0.00010981919278779304+0j)), ('IXIIZZI', (-5.5134418449042965e-05+0j)), ('ZXZZIZI', (5.5134418449042965e-05+0j)), ('IXZZZXZ', (8.48434375753428e-05+0j)), ('ZXIIIXZ', (-8.48434375753428e-05+0j)), ('ZXZZIXZ', (-8.48434375753428e-05+0j)), ('IXIIZXZ', (8.48434375753428e-05+0j)), ('YIZZZZY', (-7.104421653185207e-05+0j)), ('YZIIIZY', (7.104421653185207e-05+0j)), ('XIZZIIX', (-7.104421653185207e-05+0j)), ('XZIIZIX', (7.104421653185207e-05+0j)), ('ZIIIIZI', (0.0010709496866189413+0j)), ('ZIZZIXZ', (-1.1841020351975189e-05+0j)), ('IIZZZXZ', (1.1841020351975189e-05+0j)), ('ZIIXXZI', (1.6967775606213222e-05+0j)), ('ZIIYYZI', (1.6967775606213222e-05+0j)), ('IIIYYII', (1.6967775606213222e-05+0j)), ('IIIXXII', (1.6967775606213222e-05+0j)), ('ZIXIXZI', (1.6967775606213222e-05+0j)), ('ZIYIYZI', (1.6967775606213222e-05+0j)), ('IIYIYII', (1.6967775606213222e-05+0j)), ('IIXIXII', (1.6967775606213222e-05+0j)), ('ZYIIXZY', (-9.687344010605508e-05+0j)), ('ZXIIYZY', (9.687344010605508e-05+0j)), ('IYIIYIX', (9.687344010605508e-05+0j)), ('IXIIXIX', (9.687344010605508e-05+0j)), ('XZZZXZI', (-1.1841020351975187e-05+0j)), ('YZZZYZI', (-1.1841020351975187e-05+0j)), ('XZIIXXZ', (0.00019145105066260875+0j)), ('YZIIYXZ', (0.00019145105066260875+0j)), ('XZZXZZI', (1.5967646430117258e-05+0j)), ('YZZYZZI', (1.5967646430117258e-05+0j)), ('YZZYIII', (1.5967646430117258e-05+0j)), ('XZZXIII', (1.5967646430117258e-05+0j)), ('XZXZZZI', (1.5967646430117264e-05+0j)), ('YZYZZZI', (1.5967646430117264e-05+0j)), ('YZYZIII', (1.5967646430117264e-05+0j)), ('XZXZIII', (1.5967646430117264e-05+0j)), ('ZZIIZZI', (0.0004730131727585795+0j)), ('ZZZZZXZ', (-3.0464615889121246e-05+0j)), ('IZZZIXZ', (3.0464615889121246e-05+0j)), ('XYZZZZY', (0.00011059315050655396+0j)), ('YXZZZZY', (-0.00011059315050655396+0j)), ('YYZZIIX', (-0.00011059315050655396+0j)), ('XXZZIIX', (-0.00011059315050655396+0j)), ('IIIIZZI', (0.0010361267075021724+0j)), ('IIZZIII', (0.0018064714658123026+0j)), ('IIIZIIZ', (0.0007929872843150064+0j)), ('IIIZIZI', (0.0008880061033849394+0j)), ('ZZZIZII', (0.0007988739221995871+0j)), ('ZZIYIIY', (-5.5011928369130214e-05+0j)), ('IIZYZIY', (5.5011928369130214e-05+0j)), ('ZZIXIIX', (-5.5011928369130214e-05+0j)), ('IIZXZIX', (5.5011928369130214e-05+0j)), ('ZXIZIII', (6.69242119310632e-05+0j)), ('IXZIZII', (-6.69242119310632e-05+0j)), ('IIIZZII', (0.0008097273921596632+0j)), ('IIZXYYZ', (-1.5967646430117258e-05+0j)), ('IIZYXYZ', (1.5967646430117258e-05+0j)), ('IIZYYXZ', (1.5967646430117258e-05+0j)), ('IIZXXXZ', (1.5967646430117258e-05+0j)), ('YZZIYII', (-0.00012199874978090467+0j)), ('XZZIXII', (-0.00012199874978090467+0j)), ('IIXXIII', (5.627159027939906e-05+0j)), ('IIYYIII', (5.627159027939906e-05+0j)), ('IYIXIIY', (-5.904585093444133e-05+0j)), ('IXIYIIY', (5.904585093444133e-05+0j)), ('IYIYIIX', (5.904585093444133e-05+0j)), ('IXIXIIX', (5.904585093444133e-05+0j)), ('YZIXIYZ', (-1.9205482609715852e-05+0j)), ('XZIYIYZ', (1.9205482609715852e-05+0j)), ('YZIYIXZ', (1.9205482609715852e-05+0j)), ('XZIXIXZ', (1.9205482609715852e-05+0j)), ('IZIZIII', (0.0007929872843150064+0j)), ('ZIIZIII', (0.0008880061033849394+0j)), ('IIZIIIZ', (0.0007929872843150065+0j)), ('IIZIIZI', (0.0008880061033849394+0j)), ('ZZIZZII', (0.0007988739221995873+0j)), ('ZZYIIIY', (-5.501192836913023e-05+0j)), ('IIYZZIY', (5.501192836913023e-05+0j)), ('ZZXIIIX', (-5.501192836913023e-05+0j)), ('IIXZZIX', (5.501192836913023e-05+0j)), ('ZXZIIII', (6.692421193106327e-05+0j)), ('IXIZZII', (-6.692421193106327e-05+0j)), ('IIZIZII', (0.000809727392159664+0j)), ('IIXZYYZ', (-1.5967646430117264e-05+0j)), ('IIYZXYZ', (1.5967646430117264e-05+0j)), ('IIYZYXZ', (1.5967646430117264e-05+0j)), ('IIXZXXZ', (1.5967646430117264e-05+0j)), ('YZIZYII', (-0.00012199874978090467+0j)), ('XZIZXII', (-0.00012199874978090467+0j)), ('IYXIIIY', (-5.904585093444135e-05+0j)), ('IXYIIIY', (5.904585093444135e-05+0j)), ('IYYIIIX', (5.904585093444135e-05+0j)), ('IXXIIIX', (5.904585093444135e-05+0j)), ('YZXIIYZ', (-1.9205482609715852e-05+0j)), ('XZYIIYZ', (1.9205482609715852e-05+0j)), ('YZYIIXZ', (1.9205482609715852e-05+0j)), ('XZXIIXZ', (1.9205482609715852e-05+0j)), ('IZZIIII', (0.0007929872843150065+0j)), ('ZIZIIII', (0.0008880061033849394+0j)), ('IIIIIZZ', (0.00034219975187565604+0j)), ('ZZZZXYY', (-0.00016567029561026023+0j)), ('IIIIXYY', (0.00016567029561026023+0j)), ('ZZZZXXX', (-0.00016567029561026023+0j)), ('IIIIXXX', (0.00016567029561026023+0j)), ('XIIIIYY', (6.450150350093864e-05+0j)), ('XZZZZYY', (-6.450150350093864e-05+0j)), ('XIIIIXX', (6.450150350093864e-05+0j)), ('XZZZZXX', (-6.450150350093864e-05+0j)), ('IIIIZIZ', (0.0004730131727585795+0j)), ('IYZZYYY', (-0.00011059315050655396+0j)), ('IXZZXYY', (-0.00011059315050655396+0j)), ('IYZZYXX', (-0.00011059315050655396+0j)), ('IXZZXXX', (-0.00011059315050655396+0j)), ('YZZZYIZ', (3.0464615889121246e-05+0j)), ('XZZZXIZ', (3.0464615889121246e-05+0j)), ('YYIIIYY', (0.00016320827634266463+0j)), ('XXIIIYY', (0.00016320827634266463+0j)), ('YYIIIXX', (0.00016320827634266463+0j)), ('XXIIIXX', (0.00016320827634266463+0j)), ('ZIIIIIZ', (0.0005054080282183206+0j)), ('ZZZZZZI', (0.0004963220153364809+0j)), ('ZXIIIZI', (-4.214944750895202e-05+0j)), ('IXZZZZI', (4.214944750895202e-05+0j)), ('IZIIIZI', (0.0005054080282183206+0j)), ('ZZZZIII', (0.0002867041026751466+0j)), ('XIIIXII', (4.46871897480607e-05+0j)), ('YIIIYII', (4.46871897480607e-05+0j)), ('IZZZZII', (0.00043065242814294217+0j)), ('ZXIIZII', (5.4684774338750076e-05+0j)), ('IXZZIII', (-5.4684774338750076e-05+0j)), ('XYZZYII', (1.3799221043490745e-05+0j)), ('XXZZXII', (9.462607907840818e-05+0j)), ('YYZZXII', (8.082685803491741e-05+0j)), ('YYIIXII', (8.082685803491741e-05+0j)), ('XXIIXII', (9.462607907840818e-05+0j)), ('XYIIYII', (1.3799221043490745e-05+0j)), ('IXIIIII', (2.2352055991986643e-05+0j)), ('ZXZZZII', (-2.2352055991986643e-05+0j)), ('IZIIZII', (0.0003761397326525245+0j)), ('YIZZYII', (-8.012853461743272e-05+0j)), ('XIZZXII', (-8.012853461743272e-05+0j)), ('ZZIIIII', (0.00034219975187565604+0j))]\n" - ] - } - ], - "source": [ - "from typing import cast\n", - "\n", - "from classiq import Pauli, PauliTerm\n", - "\n", - "# normalizing the operator\n", - "## we need to create a matrix such that its normalized version will have eigenvalues of [0,1/2^k] when k is the resolution of the QPE\n", - "normalize = True\n", - "\n", - "\n", - "def normalization_params(pauli_list, N):\n", - " A = 0\n", - " for a, b in pauli_list:\n", - " A = A + abs(b)\n", - " return N * A\n", - "\n", - "\n", - "def normalize_hamiltonian(pauli_list, normalization_coeff, k):\n", - " new_pauli_list = []\n", - " for a, b in pauli_list:\n", - " if a == \"I\" * N:\n", - " new_pauli_list.append(\n", - " (\n", - " a,\n", - " (b + normalization_coeff)\n", - " * (1 - 1 / (2**k))\n", - " / (2 * normalization_coeff),\n", - " )\n", - " )\n", - " else:\n", - " new_pauli_list.append((a, b * (1 - 1 / (2**k)) / (2 * normalization_coeff)))\n", - " return new_pauli_list\n", - "\n", - "\n", - "pauli_list = pauli_ops\n", - "if normalize:\n", - " normalization_coeff = normalization_params(pauli_ops, N)\n", - " new_pauli_list = normalize_hamiltonian(pauli_ops, normalization_coeff, n_qpe)\n", - " pauli_ops = new_pauli_list\n", - " print(pauli_ops)" - ] - }, - { - "cell_type": "markdown", - "id": "21e4de42-3417-46d4-b981-664bb0683dc4", - "metadata": { - "id": "21e4de42-3417-46d4-b981-664bb0683dc4" - }, - "source": [ - "Convert the objects to qmod:" - ] - }, - { - "cell_type": "code", - "execution_count": 63, - "id": "e340b469-5566-4bd5-bb5d-3107ebc790e0", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:41.828923Z", - "iopub.status.busy": "2024-05-07T15:16:41.827843Z", - "iopub.status.idle": "2024-05-07T15:16:41.834314Z", - "shell.execute_reply": "2024-05-07T15:16:41.833663Z" - }, - "tags": [], - "id": "e340b469-5566-4bd5-bb5d-3107ebc790e0" - }, - "outputs": [], - "source": [ - "CHAR_TO_STUCT_DICT = {\"I\": Pauli.I, \"X\": Pauli.X, \"Y\": Pauli.Y, \"Z\": Pauli.Z}\n", - "\n", - "\n", - "def pauli_str_to_enums(pauli):\n", - " return [CHAR_TO_STUCT_DICT[s] for s in pauli]\n", - "\n", - "\n", - "def pauli_list_to_hamiltonian(pauli_list):\n", - " return [\n", - " PauliTerm(\n", - " pauli=pauli_str_to_enums(pauli), coefficient=cast(complex, coeff).real\n", - " )\n", - " for pauli, coeff in pauli_list\n", - " ]" - ] - }, - { - "cell_type": "markdown", - "id": "62d2e51d-d532-4c26-86dd-a5b9b40d009e", - "metadata": { - "id": "62d2e51d-d532-4c26-86dd-a5b9b40d009e" - }, - "source": [ - "## 3. Creating the Quantum Circuit\n", - "\n", - "We will now create a quantum circuit of the QPE algorithm using the Classiq platform. The user is able to fill in their constraints and preferences as desired." - ] - }, - { - "cell_type": "code", - "execution_count": 64, - "id": "fd4ee616-2a11-46ba-adc0-ed5171d7dd7d", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:41.838788Z", - "iopub.status.busy": "2024-05-07T15:16:41.837667Z", - "iopub.status.idle": "2024-05-07T15:16:41.842620Z", - "shell.execute_reply": "2024-05-07T15:16:41.841962Z" - }, - "tags": [], - "id": "fd4ee616-2a11-46ba-adc0-ed5171d7dd7d" - }, - "outputs": [], - "source": [ - "constraints = Constraints()\n", - "preferences = Preferences(timeout_seconds=600)" - ] - }, - { - "cell_type": "markdown", - "id": "43c249a1-9db3-4164-bec1-f345670d4cd1", - "metadata": { - "id": "43c249a1-9db3-4164-bec1-f345670d4cd1" - }, - "source": [ - "### 3.1. Create the phase estimation model" - ] - }, - { - "cell_type": "code", - "execution_count": 65, - "id": "b05c5ced-e02a-4b56-acc5-c62de3564239", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:41.847063Z", - "iopub.status.busy": "2024-05-07T15:16:41.845892Z", - "iopub.status.idle": "2024-05-07T15:16:41.856296Z", - "shell.execute_reply": "2024-05-07T15:16:41.855646Z" - }, - "tags": [], - "id": "b05c5ced-e02a-4b56-acc5-c62de3564239" - }, - "outputs": [], - "source": [ - "from classiq import molecule_problem_to_qmod\n", - "from classiq.qmod import (\n", - " CInt,\n", - " Output,\n", - " QArray,\n", - " QBit,\n", - " QCallable,\n", - " QNum,\n", - " allocate,\n", - " allocate_num,\n", - " control,\n", - " invert,\n", - " qfunc,\n", - " repeat,\n", - ")\n", - "from classiq.qmod.builtins import (\n", - " H,\n", - " apply_to_all,\n", - " exponentiation_with_depth_constraint,\n", - " molecule_hartree_fock,\n", - " qft,\n", - ")\n", - "from classiq.qmod.symbolic import log, pi\n", - "\n", - "# this constant will be multipled be a linear factor for each qbit of the qpe, so the\n", - "# depth will scale linear with the power of each unitary, on the expense of approximating the\n", - "# exponentiation function\n", - "exp_max_depth = 2200\n", - "\n", - "\n", - "# define a Quantum Phase Estimation function that allows specifying each controlled\n", - "# power unitary directly\n", - "@qfunc\n", - "def my_flexible_qpe(\n", - " unitary_with_power: QCallable[CInt],\n", - " phase: QArray[QBit],\n", - ") -> None:\n", - " apply_to_all(H, phase)\n", - "\n", - " repeat(\n", - " count=phase.len,\n", - " iteration=lambda index: control(\n", - " ctrl=phase[index],\n", - " operand=lambda: unitary_with_power(2**index),\n", - " ),\n", - " )\n", - " invert(lambda: qft(phase))\n", - "\n", - "\n", - "@qfunc\n", - "def main(reg: Output[QArray[QBit]], phase: Output[QNum]):\n", - " allocate_num(num_qubits=n_qpe, is_signed=False, fraction_digits=n_qpe, out=phase)\n", - " allocate(N, reg)\n", - "\n", - " # The state chosen for the initial state is HF, as usually it has good overlap with the with the eigenstate of minimal energy.\n", - " molecule_hartree_fock(molecule_problem_to_qmod(gs_problem), reg)\n", - "\n", - " # # Hereby we send the pauli list created for the molecule for creating phase estimation circuit.\n", - " my_flexible_qpe(\n", - " lambda power: exponentiation_with_depth_constraint(\n", - " pauli_list_to_hamiltonian(pauli_ops),\n", - " evolution_coefficient=-2 * np.pi * power,\n", - " max_depth=exp_max_depth * ((2**0.5) ** log(power, 2)),\n", - " qbv=reg,\n", - " ),\n", - " phase,\n", - " )" - ] - }, - { - "cell_type": "markdown", - "id": "467eca03-8a66-43d8-b2af-6d86b21e36d5", - "metadata": { - "tags": [], - "id": "467eca03-8a66-43d8-b2af-6d86b21e36d5" - }, - "source": [ - "## 3.2. Synthesizing the Circuit\n", - "\n", - "Hereby we syntesize the circuit and show it using the analyzer." - ] - }, - { - "cell_type": "code", - "execution_count": 66, - "id": "10eaa569-de42-41b4-b615-c04bdc850ecf", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:41.861003Z", - "iopub.status.busy": "2024-05-07T15:16:41.859910Z", - "iopub.status.idle": "2024-05-07T15:16:41.880458Z", - "shell.execute_reply": "2024-05-07T15:16:41.879759Z" - }, - "tags": [], - "id": "10eaa569-de42-41b4-b615-c04bdc850ecf" - }, - "outputs": [], - "source": [ - "from classiq import create_model\n", - "from classiq.execution import ExecutionPreferences\n", - "\n", - "num_shots = 200000\n", - "\n", - "qmod = create_model(\n", - " main,\n", - " constraints=constraints,\n", - " preferences=preferences,\n", - " execution_preferences=ExecutionPreferences(num_shots=num_shots),\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 67, - "id": "a7aae67f-1750-43be-9446-74fa0565058a", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:41.885344Z", - "iopub.status.busy": "2024-05-07T15:16:41.884136Z", - "iopub.status.idle": "2024-05-07T15:16:41.904022Z", - "shell.execute_reply": "2024-05-07T15:16:41.903307Z" - }, - "id": "a7aae67f-1750-43be-9446-74fa0565058a" - }, - "outputs": [], - "source": [ - "from classiq import write_qmod\n", - "\n", - "write_qmod(qmod, name=\"qpe_for_molecules\")" - ] - }, - { - "cell_type": "code", - "execution_count": 68, - "id": "8d434afe-5cbc-4a56-a48c-e657090c348a", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:16:41.909027Z", - "iopub.status.busy": "2024-05-07T15:16:41.907875Z", - "iopub.status.idle": "2024-05-07T15:20:36.342504Z", - "shell.execute_reply": "2024-05-07T15:20:36.341786Z" - }, - "tags": [], - "id": "8d434afe-5cbc-4a56-a48c-e657090c348a", - "outputId": "660ea141-5ece-4b9f-ca7b-68e2abdea824", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - } - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/4c2b4185-9a94-4654-9c86-f119894f8fe4?version=0.42.1\n" - ] - } - ], - "source": [ - "from classiq import show, synthesize\n", - "\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "id": "7483f266-af0f-4d08-aa96-317b4044df58", - "metadata": { - "id": "7483f266-af0f-4d08-aa96-317b4044df58" - }, - "source": [ - "# 4. Measurment and Analysis\n" - ] - }, - { - "cell_type": "markdown", - "id": "e5bf0b3c-839f-43de-9da1-cba55ceba995", - "metadata": { - "id": "e5bf0b3c-839f-43de-9da1-cba55ceba995" - }, - "source": [ - "### 4.1. Circuit Execution\n", - "\n", - "The circuit is now sent to execution on a default simulator" - ] - }, - { - "cell_type": "code", - "execution_count": 69, - "id": "bc063bfc-de4b-4181-82b1-f805f86baa2e", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:20:36.347128Z", - "iopub.status.busy": "2024-05-07T15:20:36.345984Z", - "iopub.status.idle": "2024-05-07T15:21:50.459583Z", - "shell.execute_reply": "2024-05-07T15:21:50.458947Z" - }, - "tags": [], - "id": "bc063bfc-de4b-4181-82b1-f805f86baa2e" - }, - "outputs": [], - "source": [ - "from classiq import execute\n", - "\n", - "results = execute(qprog).result()" - ] - }, - { - "cell_type": "code", - "execution_count": 70, - "id": "05e682bd-0f1a-4e10-ba0b-e0bf3378fecd", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:21:50.462348Z", - "iopub.status.busy": "2024-05-07T15:21:50.461903Z", - "iopub.status.idle": "2024-05-07T15:21:50.464971Z", - "shell.execute_reply": "2024-05-07T15:21:50.464409Z" - }, - "tags": [], - "id": "05e682bd-0f1a-4e10-ba0b-e0bf3378fecd" - }, - "outputs": [], - "source": [ - "from classiq.execution import ExecutionDetails\n", - "\n", - "results = results[0].value" - ] - }, - { - "cell_type": "markdown", - "id": "8611351f-1b14-4969-878d-6f022cdfce2a", - "metadata": { - "id": "8611351f-1b14-4969-878d-6f022cdfce2a" - }, - "source": [ - "### 4.2. Presenting the Result's Count" - ] - }, - { - "cell_type": "code", - "execution_count": 71, - "id": "9c0ee98c-3ffa-4f1d-9cb2-4fada19b08b4", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:21:50.467938Z", - "iopub.status.busy": "2024-05-07T15:21:50.466973Z", - "iopub.status.idle": "2024-05-07T15:21:50.474468Z", - "shell.execute_reply": "2024-05-07T15:21:50.473904Z" - }, - "tags": [], - "id": "9c0ee98c-3ffa-4f1d-9cb2-4fada19b08b4", - "outputId": "dbdec0d4-3bef-487c-ce25-5761628ee8ab", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - } - }, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "[{'phase': 0.46875}: 135341,\n", - " {'phase': 0.484375}: 36274,\n", - " {'phase': 0.453125}: 8283,\n", - " {'phase': 0.5}: 5402,\n", - " {'phase': 0.4375}: 2781,\n", - " {'phase': 0.515625}: 2139,\n", - " {'phase': 0.421875}: 1322,\n", - " {'phase': 0.53125}: 1110,\n", - " {'phase': 0.40625}: 793,\n", - " {'phase': 0.546875}: 692]" - ] - }, - "metadata": {}, - "execution_count": 71 - } - ], - "source": [ - "results.parsed_counts_of_outputs(\"phase\")[:10]" - ] - }, - { - "cell_type": "markdown", - "id": "41009d2c-4276-409b-b9f4-8dee8103f208", - "metadata": { - "id": "41009d2c-4276-409b-b9f4-8dee8103f208" - }, - "source": [ - "### 4.3. Chosing the Most Probable Solution\n", - "\n", - "Hereby the user will choose the number of eigenvalues they wish to extract from the poll of results. The\n", - "value `number_of_solutions` will determine how many results out of `qpe_results` will be analyzed.\n", - "The `parsed_counts` property is already sorted.\n", - "\n", - "We get the result in the `phase` variable already encoded as fixed point variable in the range [0,1]." - ] - }, - { - "cell_type": "code", - "execution_count": 72, - "id": "ba022acc-738c-4685-a7ff-70ea2c400bfd", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:21:50.476943Z", - "iopub.status.busy": "2024-05-07T15:21:50.476435Z", - "iopub.status.idle": "2024-05-07T15:21:50.479735Z", - "shell.execute_reply": "2024-05-07T15:21:50.479163Z" - }, - "id": "ba022acc-738c-4685-a7ff-70ea2c400bfd" - }, - "outputs": [], - "source": [ - "number_of_solutions = 1 # to be set" - ] - }, - { - "cell_type": "code", - "execution_count": 73, - "id": "4a54cb17-8c0a-4b00-a3a3-6e276fa92b53", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:21:50.482120Z", - "iopub.status.busy": "2024-05-07T15:21:50.481642Z", - "iopub.status.idle": "2024-05-07T15:21:50.488542Z", - "shell.execute_reply": "2024-05-07T15:21:50.487983Z" - }, - "tags": [], - "id": "4a54cb17-8c0a-4b00-a3a3-6e276fa92b53", - "outputId": "52406be4-77d6-4bc1-e6f5-891113990de4", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - } - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Your qubit solution is\n", - "[{'phase': 0.46875}: 135341]\n" - ] - } - ], - "source": [ - "solutions = results.parsed_counts_of_outputs(\"phase\")[:number_of_solutions]\n", - "print(\"Your qubit solution is\", solutions, sep=\"\\n\")" - ] - }, - { - "cell_type": "markdown", - "id": "2f784e6f-d7ed-4cc9-81dd-f6b952d0dc01", - "metadata": { - "id": "2f784e6f-d7ed-4cc9-81dd-f6b952d0dc01" - }, - "source": [ - "### 4.4. Translating into Energy value (Phase)" - ] - }, - { - "cell_type": "markdown", - "id": "d83d16de-2450-4c7a-8093-26bf13d4dce4", - "metadata": { - "id": "d83d16de-2450-4c7a-8093-26bf13d4dce4" - }, - "source": [ - "Map the phase back into the original values, i.e. renormalized into it's original span." - ] - }, - { - "cell_type": "code", - "execution_count": 74, - "id": "836084e1-a20d-4a55-93cc-91a40c1d2f53", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:21:50.491382Z", - "iopub.status.busy": "2024-05-07T15:21:50.491220Z", - "iopub.status.idle": "2024-05-07T15:21:50.494025Z", - "shell.execute_reply": "2024-05-07T15:21:50.493447Z" - }, - "id": "836084e1-a20d-4a55-93cc-91a40c1d2f53" - }, - "outputs": [], - "source": [ - "def post_process_phase(phase):\n", - " return (\n", - " (phase * 2 * normalization_coeff) / (1 - (1 / 2**n_qpe))\n", - " ) - normalization_coeff" - ] - }, - { - "cell_type": "code", - "execution_count": 75, - "id": "a5bdb723-b015-4e80-98ea-985901c6c8d7", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:21:50.496211Z", - "iopub.status.busy": "2024-05-07T15:21:50.495859Z", - "iopub.status.idle": "2024-05-07T15:21:50.499028Z", - "shell.execute_reply": "2024-05-07T15:21:50.498455Z" - }, - "tags": [], - "id": "a5bdb723-b015-4e80-98ea-985901c6c8d7" - }, - "outputs": [], - "source": [ - "# renormalize into the \"real\" solution -\n", - "if normalize:\n", - " solution = [post_process_phase(value.state[\"phase\"]) for value in solutions]\n", - "else:\n", - " solution = phase" - ] - }, - { - "cell_type": "markdown", - "id": "6c963b82-26a7-4251-bae0-32e66c57fa1d", - "metadata": { - "id": "6c963b82-26a7-4251-bae0-32e66c57fa1d" - }, - "source": [ - "The final results of the Energy (matrix's eigenvlues) is therefore:" - ] - }, - { - "cell_type": "code", - "execution_count": 76, - "id": "43e8ec8f-2be9-403d-8ae9-9380fb2b08c9", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:21:50.501429Z", - "iopub.status.busy": "2024-05-07T15:21:50.500917Z", - "iopub.status.idle": "2024-05-07T15:21:50.504469Z", - "shell.execute_reply": "2024-05-07T15:21:50.503902Z" - }, - "tags": [], - "id": "43e8ec8f-2be9-403d-8ae9-9380fb2b08c9", - "outputId": "57fe6127-9b33-4cc5-ffcc-a121004cf862", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - } - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "[-5.0500156710895965]\n" - ] - } - ], - "source": [ - "print(solution)" - ] - }, - { - "cell_type": "markdown", - "id": "7565aa1f-b8ba-4617-a2ef-79317261dfe7", - "metadata": { - "id": "7565aa1f-b8ba-4617-a2ef-79317261dfe7" - }, - "source": [ - "And the results including the error contributed from the resolution (number of qubits participating in the QPE) are:" - ] - }, - { - "cell_type": "code", - "execution_count": 77, - "id": "79f1c1ba-61fd-438e-a3d5-7606ea95e70f", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:21:50.506581Z", - "iopub.status.busy": "2024-05-07T15:21:50.506402Z", - "iopub.status.idle": "2024-05-07T15:21:50.510455Z", - "shell.execute_reply": "2024-05-07T15:21:50.509818Z" - }, - "tags": [], - "id": "79f1c1ba-61fd-438e-a3d5-7606ea95e70f", - "outputId": "d75f1d8a-8af0-48c8-a552-a37bf9fbf641", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - } - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "the resolution of result is 3.3666771140597356\n", - "the eneregy solution is beteen -8.416692785149332 and -1.683338557029861\n" - ] - } - ], - "source": [ - "if normalize:\n", - " energy_resolution = (\n", - " (1 / (2**n_qpe)) * 2 * normalization_coeff / (1 - (1 / 2**n_qpe))\n", - " )\n", - "else:\n", - " energy_resolution = 1 / (2**n_qpe)\n", - "\n", - "print(\"the resolution of result is\", energy_resolution)\n", - "\n", - "for sol in solution:\n", - " print(\n", - " \"the eneregy solution is beteen\",\n", - " sol - energy_resolution,\n", - " \"and\",\n", - " sol + energy_resolution,\n", - " )\n", - "\n", - " ###if zero or exceed the normalization range need to add conditions" - ] - }, - { - "cell_type": "markdown", - "id": "d570c6b0-bd32-40d1-9ebb-c1ee7c8663ad", - "metadata": { - "id": "d570c6b0-bd32-40d1-9ebb-c1ee7c8663ad" - }, - "source": [ - "### 4.4. Find Exact Solution for Comparison" - ] - }, - { - "cell_type": "code", - "execution_count": 78, - "id": "bd9e84a5-d131-4835-bade-13ba01035b44", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:21:50.512649Z", - "iopub.status.busy": "2024-05-07T15:21:50.512475Z", - "iopub.status.idle": "2024-05-07T15:21:50.516587Z", - "shell.execute_reply": "2024-05-07T15:21:50.515949Z" - }, - "tags": [], - "id": "bd9e84a5-d131-4835-bade-13ba01035b44", - "outputId": "7cfc9892-b918-4447-806d-f13493e84053", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - } - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "exact result: -3.940331561325765\n" - ] - } - ], - "source": [ - "mat = operator.to_matrix()\n", - "w, v = np.linalg.eig(mat)\n", - "print(\"exact result:\", np.real(min(w)))" - ] - }, - { - "cell_type": "markdown", - "id": "703c6ae7-5174-433f-ad9f-78f9864b1914", - "metadata": { - "id": "703c6ae7-5174-433f-ad9f-78f9864b1914" - }, - "source": [ - "### 4.4. Find the Solution's Histogram" - ] - }, - { - "cell_type": "code", - "execution_count": 79, - "id": "dfc5f725-495b-45d1-9c67-a1daf80a1454", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:21:50.519020Z", - "iopub.status.busy": "2024-05-07T15:21:50.518676Z", - "iopub.status.idle": "2024-05-07T15:21:50.523706Z", - "shell.execute_reply": "2024-05-07T15:21:50.523090Z" - }, - "tags": [], - "id": "dfc5f725-495b-45d1-9c67-a1daf80a1454" - }, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "energy_vec = []\n", - "energy_prob = []\n", - "\n", - "for value, counts in results.parsed_counts_of_outputs(\"phase\"):\n", - " temp = value[1][\"phase\"]\n", - " if normalize:\n", - " temp2 = (\n", - " temp * 2 * normalization_coeff / (1 - (1 / 2**n_qpe))\n", - " ) - normalization_coeff\n", - " else:\n", - " temp2 = temp\n", - " energy_vec.append(temp2)\n", - " energy_prob.append(counts[1] / num_shots)" - ] - }, - { - "cell_type": "code", - "execution_count": 81, - "id": "993c5b3b-7a05-44f1-9c4e-6651cd50f4cb", - "metadata": { - "execution": { - "iopub.execute_input": "2024-05-07T15:21:50.525902Z", - "iopub.status.busy": "2024-05-07T15:21:50.525629Z", - "iopub.status.idle": "2024-05-07T15:21:50.659434Z", - "shell.execute_reply": "2024-05-07T15:21:50.658856Z" - }, - "tags": [], - "id": "993c5b3b-7a05-44f1-9c4e-6651cd50f4cb", - "outputId": "640fb07e-7b78-45ad-958a-c447af80f9be", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 430 - } - }, - "outputs": [ - { - "output_type": "display_data", - "data": { - "text/plain": [ - "
" - ], - "image/png": "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qwgjAADAKsIIAACwijACAACsIowAAACrCCMAAMAqwggAALCKMAIAAKwijAAAAKsIIwAAwCrCCAAAsIowAgAArCKMAAAAqwgjAADAKsIIAACwijACAACsIowAAACrCCMAAMAqwggAALCKMAIAAKwijAAAAKsIIwAAwCrCCAAAsIowAgAArCKMAAAAqwgjAADAqlGFkYaGBhUUFCgjI0M+n0+tra1Dtt2+fbtKSkqUnZ2tGTNmqKioSD/84Q9HXTAAAJhckg4jTU1NCgQCqqur0969e1VYWKjy8nIdOXJk0PazZ8/W3XffrZaWFr388suqrq5WdXW1nn322XMuHgAApD6HMcYk08Hn82nFihXatGmTJCkWi8nr9Wrt2rVat27diPZxxRVXaOXKlfrWt741ovbRaFRut1uRSERZWVnJlAsAACwZ6ft3UiMj/f39amtrk9/vP70Dp1N+v18tLS1n7W+MUSgUUnt7u6655poh2/X19SkajSYsAABgckoqjPT09GhgYEAejydhvcfjUTgcHrJfJBLRzJkzlZ6erpUrV+rhhx/W9ddfP2T7YDAot9sdX7xebzJlAgCAFDIud9NceOGF2rdvn1588UXdf//9CgQC2rlz55Dta2pqFIlE4ktnZ+d4lAkAACy4IJnGOTk5SktLU3d3d8L67u5u5ebmDtnP6XTq0ksvlSQVFRVp//79CgaD+vSnPz1oe5fLJZfLlUxpAAAgRSU1MpKenq7i4mKFQqH4ulgsplAopLKyshHvJxaLqa+vL5lDAwCASSqpkRFJCgQCqqqqUklJiUpLS1VfX6/e3l5VV1dLkiorK5Wfn69gMCjpw/kfJSUluuSSS9TX16cdO3bohz/8oR555JGxPRMAAJCSkg4jFRUVOnr0qGpraxUOh1VUVKTm5ub4pNaOjg45nacHXHp7e/XlL39Zv/vd7zR9+nQtXrxYjz/+uCoqKsbuLAAAQMpK+jkjNvCcEQAAUs95ec4IAADAWCOMAAAAqwgjAADAKsIIAACwijACAACsIowAAACrCCMAAMAqwggAALCKMAIAAKwijAAAAKsIIwAAwCrCCAAAsIowAgAArCKMAAAAqwgjAADAKsIIAACwijACAACsIowAAACrCCMAAMAqwggAALCKMAIAAKwijAAAAKsIIwAAwCrCCAAAsIowAgAArCKMAAAAqwgjAADA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\n" - }, - "metadata": {} - } - ], - "source": [ - "plt.plot(energy_vec, energy_prob, \".\")\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "id": "9797b512-d41f-47c1-8c0f-4134f0500b80", - "metadata": { - "id": "9797b512-d41f-47c1-8c0f-4134f0500b80" - }, - "source": [ - "## References\n", - "\n", - "[1]: [Michael A. Nielsen and Isaac L. Chuang. 2011. Quantum Computation and Quantum Information: 10th Anniversary Edition, Cambridge University Press, New York, NY, USA.\n", - "](http://mmrc.amss.cas.cn/tlb/201702/W020170224608149940643.pdf)\n" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# **Results for BeH2:**\n", - "\n", - "Your qubit solution is [{'phase': 0.46875}: 135341]\n", - "\n", - "The final results of the Energy (matrix's eigenvlues) is therefore:\n", - "\n", - "[-5.0500156710895965]\n", - "\n", - "exact result: -3.940331561325765\n", - "\n", - "The results including the error contributed from the resolution (number of qubits participating in the QPE) are: The resolution of result is 3.3666771140597356 the energy solution is between -8.416692785149332 and -1.683338557029861" - ], - "metadata": { - "id": "ttDDvHfPDI4y" - }, - "id": "ttDDvHfPDI4y" - }, - { - "cell_type": "markdown", - "source": [ - "# **Results for H2O:**\n", - "\n", - "Your qubit solution is\n", - "[{'phase': 0.453125}: 89076]\n", - "\n", - "The final results of the Energy (matrix's eigenvlues) is therefore:\n", - "\n", - "[-29.018825909142947]\n", - "\n", - "exact result: -23.54449724044351\n", - "\n", - "\n", - "The results including the error contributed from the resolution (number of qubits\n", - "participating in the QPE) are:\n", - "The resolution of result is 11.607530363657174\n", - "the energy solution is between -40.62635627280012 and -17.41129554548577\n", - "\n" - ], - "metadata": { - "id": "JvBCdhv08YSu" - }, - "id": "JvBCdhv08YSu" - }, - { - "cell_type": "markdown", - "source": [], - "metadata": { - "id": "PGUPJn2Y9Hxr" - }, - "id": "PGUPJn2Y9Hxr" - }, - { - "cell_type": "markdown", - "source": [], - "metadata": { - "id": "1xjsIzhx2iV1" - }, - "id": "1xjsIzhx2iV1" - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.9" - }, - "colab": { - "provenance": [], - "include_colab_link": true - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file From 7bf53aede7c953890ae31c45123af8282bfff947 Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Sat, 15 Jun 2024 04:49:29 +0200 Subject: [PATCH 12/18] Add files via upload --- ...Hisham_Mansour_HW4_qpe_for_molecules.ipynb | 1092 +++++++++++++++++ 1 file changed, 1092 insertions(+) create mode 100644 community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb diff --git a/community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb b/community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb new file mode 100644 index 00000000..83fee81b --- /dev/null +++ b/community/QClass_2024/Submissions/HW4/Hisham_Mansour_HW4_qpe_for_molecules.ipynb @@ -0,0 +1,1092 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "425612b8", + "metadata": { + "colab_type": "text", + "id": "view-in-github" + }, + "source": [ + "\"Open" + ] + }, + { + "cell_type": "markdown", + "id": "75e2c1fe-8a06-4f0b-8fd6-d1b6d10ce82f", + "metadata": { + "id": "75e2c1fe-8a06-4f0b-8fd6-d1b6d10ce82f" + }, + "source": [ + "# Quantum Phase Estimation (QPE) for Solving Molecular Energies\n", + "\n", + "\n", + "Quantum Phase Estimation (QPE) is a key algorithm in quantum computing, allowing one to estimate the phase (or eigenvalue) of an eigenvector of a unitary operation. The algorithm is designed so, that for a given Hamiltonian $H$, and an eigenvalue ${|\\psi\\rangle}$, the output that will be obtained is $\\epsilon$ where\n", + "\n", + "$U{|\\psi\\rangle} = e^{2\\pi i\\epsilon}{|\\psi\\rangle} , U = e^{2\\pi iH}$ .\n", + "\n", + "\n", + "Therefore, by measuring the phase accumulated, the QPE algorithm allows calculating the energies relating to the chosen initial state.\n", + "When using QPE for chemistry problems, it is common to search for the lowest energy of a given molecule. As the molecule can be written in the form of a Hamiltonian (Hermitian matrix which meaning is the energetic forces of the structure), usually symbolized by \"H\", one only need to insert the ground eigenvector in order to obtain the minimal energy value using QPE. However, obtaining the ground state is not a trivial problem. In order to overcome it, it is sufficient to use a state with big overlap with the ground state.\n", + "\n", + "We define a state ${|v\\rangle}$ which will be chosen as the algorithm's initial state. Let us define {$\\psi_i$} to be the set of (unknown) eigenvalues of $H$. Generally, any vector can be rewritten as a superposition of any basis set, thus -\n", + "\n", + "${|v\\rangle} = \\sum_i a_i{|\\psi_i\\rangle}$\n", + "\n", + "and -\n", + "\n", + "$U{|v\\rangle} = \\sum_i a_i e^{2\\pi i\\epsilon_i}{|\\psi_i\\rangle}$.\n", + "\n", + "where ${\\epsilon_i}$ are the eigenvalues of H, i.e. the span of energies relating to the molecule. Using execution with enough shots, one will obtain this set of $\\theta_i$, i.e., a subset of the Hamiltonian's eigenvalues. As we are specifically interested in $\\epsilon_0$, the ground state of H, it is important that there is a large overlap between ${\\psi_0}$ and ${|v\\rangle}$ so the probability to measure ${\\epsilon_0}$ is high, i.e.\n", + "\n", + "$P(\\epsilon_0) = |\\langle v|\\psi_0\\rangle|^2 > \\epsilon $.\n", + "\n", + "How large is $\\epsilon$? After execution, we will obtain a set of ${E_i}$.\n", + "If we have done 1000 shots of execution, and $P(\\epsilon_0)>1$, it should be measured is about 10 times to get a good statistical variance.\n", + "\n", + "A common choice for ${|v\\rangle}$ (the initial state) is the Hartree-Fock (HF) state, which with good probability have a large overlap with the ground state. However, other guesses for the initial state are possibly good or even better fit, and choosing the right initial state is a sort of art and an active field of research.\n", + "\n", + "For further reading about QPE we recommend [[1](#NC)].\n", + "\n", + "\n", + "#### What are the benefits of using QPE algorithm for finding a molecule's ground state?\n", + "\n", + "The two most prominent methods to solve ground energy for molecules are quantum variational algorithm (VQE) and QPE. Those promise better scalability compared to classical counterparts as the molecules becomes more complex, with larger number of electrons manifesting as more degrees of freedom for the problem.\n", + "\n", + "While so, the number of parameters in VQE is closely related to the number of electrons. This may create inherent difficulty achieving high-precision calculations through sampling statistical estimators, and paraphs even not converge for very large systems. While so, the number of parameters in QPE is a flexible value which is directly related to the resolution of the problem, but is not bonded with the number of electrons.\n", + "\n", + "Furthermore, it is known that advanced quantum algorithms based on QPE can perform electronic structure calculations in sub-exponential time with accuracy that rivals exact diagonalization methods. This guarantee of simultaneously achieving high accuracy, efficiency, and generality is a feat that is believed to be impossible for classical algorithms. For those reasons, VQE is applicable in the near term (NISQ) era, while QPE is suited for fault-tolerant design.\n", + "\n", + "#### During this tutorial, we will follow the QPE algorithms steps as following:\n", + "\n", + "a. Define a molecule and convert it into a Hamiltonian H, manifested as a pauli list.\n", + "\n", + "b. Prepare the Hamiltonian for QPE: including normalization and choosing the resolution.\n", + "\n", + "c. Initializing the state for the HF state.\n", + "\n", + "d. Preparing the quantum circuit.\n", + "\n", + "e. Executing the circuit to find the related phases and analyzing the results to find the ground state.\n", + "\n", + "f. Comparing the QPE results with exact solution for the molecule’s ground state." + ] + }, + { + "cell_type": "markdown", + "id": "7cd71faa-1ef3-4d67-8c9a-d66e0a895b9a", + "metadata": { + "id": "7cd71faa-1ef3-4d67-8c9a-d66e0a895b9a" + }, + "source": [ + "## 0. Pre-requirments\n", + "\n", + "The model is using several Classiq's libraries in addition to IBM's simulating tool." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "k3DQRV9GpPSG", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "k3DQRV9GpPSG", + "outputId": "4039a7c0-2b12-4e86-d14a-455090db8a57" + }, + "outputs": [], + "source": [ + "!pip install -U classiq" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "Nsm3pKlqpZpr", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "Nsm3pKlqpZpr", + "outputId": "c7a6175b-bfa2-4b6a-f067-36f48d33d94c" + }, + "outputs": [], + "source": [ + "import classiq\n", + "classiq.authenticate()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11eaf8f8-c06e-443e-ac74-5aa364f5198c", + "metadata": { + "id": "11eaf8f8-c06e-443e-ac74-5aa364f5198c", + "tags": [] + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import scipy\n", + "from numpy import linalg as LA\n", + "\n", + "# for state preperation and phase estimation\n", + "from classiq import Constraints, Preferences\n", + "\n", + "# for chemistry\n", + "from classiq.applications.chemistry import Molecule, MoleculeProblem, PauliOperator" + ] + }, + { + "cell_type": "markdown", + "id": "ac537458-568d-4718-9020-408cc7232641", + "metadata": { + "id": "ac537458-568d-4718-9020-408cc7232641", + "tags": [] + }, + "source": [ + "## 1. Create Your Molecule" + ] + }, + { + "cell_type": "markdown", + "id": "WC3NKxILHo6H", + "metadata": { + "id": "WC3NKxILHo6H" + }, + "source": [ + "### XYZ cartesian coordinates" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b67b2e1-94c2-4c8f-8ee9-577c79a7234f", + "metadata": { + "id": "2b67b2e1-94c2-4c8f-8ee9-577c79a7234f", + "tags": [] + }, + "outputs": [], + "source": [ + "# build your molecule\n", + "\n", + "#hydrogen\n", + "molecule_H2 = Molecule(atoms=[(\"H\", (0.0, 0.0, 0)), (\"H\", (0.0, 0.0, 0.735))])\n", + "#oxygen\n", + "molecule_O2 = Molecule(atoms=[(\"O\", (0.0, 0.0, 0)), (\"O\", (0.0, 0.0, 1.16))])\n", + "#lithium hydride\n", + "molecule_LiH = Molecule(atoms=[(\"H\", (0.0, 0.0, 0.0)), (\"Li\", (0.0, 0.0, 1.596))])\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", + "#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", + "#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", + "#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))])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9e37fada-9ecc-4a24-bf2c-0994e9c14149", + "metadata": { + "id": "9e37fada-9ecc-4a24-bf2c-0994e9c14149", + "tags": [] + }, + "outputs": [], + "source": [ + "# define your molecule\n", + "#molecule = molecule_H2\n", + "#molecule = molecule_O2\n", + "#molecule = molecule_LiH\n", + "\n", + "molecule = molecule_BeH2\n", + "\n", + "#molecule = molecule_H2O\n", + "\n", + "#molecule = molecule_CO2\n", + "# The exponentiation constraints are not satisfiable.\n", + "# Minimal max_depth is 36476.\n", + "#molecule = molecule_CH3Cl\n", + "# The exponentiation constraints are not satisfiable.\n", + "# Minimal max_depth is 57965.\n", + "#molecule = molecule_C2H2\n", + "# The exponentiation constraints are not satisfiable.\n", + "# Minimal max_depth is 15115.\n", + "#molecule = molecule_C2H4\n", + "# The exponentiation constraints are not satisfiable.\n", + "# Minimal max_depth is 24471." + ] + }, + { + "cell_type": "markdown", + "id": "ClsUidSlHIsO", + "metadata": { + "id": "ClsUidSlHIsO" + }, + "source": [ + "# **Results for BeH2:**\n", + "\n", + "Your qubit solution is [{'phase': 0.46875}: 135341]\n", + "\n", + "The final results of the Energy (matrix's eigenvlues) is therefore:\n", + "\n", + "[-5.0500156710895965]\n", + "\n", + "exact result: -3.940331561325765\n", + "\n", + "The results including the error contributed from the resolution (number of qubits participating in the QPE) are: The resolution of result is 3.3666771140597356 the energy solution is between -8.416692785149332 and -1.683338557029861" + ] + }, + { + "cell_type": "markdown", + "id": "Cab7eyKPHSW8", + "metadata": { + "id": "Cab7eyKPHSW8" + }, + "source": [ + "# **Results for H2O:**\n", + "\n", + "Your qubit solution is\n", + "[{'phase': 0.453125}: 89076]\n", + "\n", + "The final results of the Energy (matrix's eigenvlues) is therefore:\n", + "\n", + "[-29.018825909142947]\n", + "\n", + "exact result: -23.54449724044351\n", + "\n", + "\n", + "The results including the error contributed from the resolution (number of qubits\n", + "participating in the QPE) are:\n", + "The resolution of result is 11.607530363657174\n", + "the energy solution is between -40.62635627280012 and -17.41129554548577\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d27e5df-e16e-44b2-b78a-187905577908", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "5d27e5df-e16e-44b2-b78a-187905577908", + "outputId": "7bad3408-043c-4a50-beb7-a0b2acfb6360", + "tags": [] + }, + "outputs": [], + "source": [ + "# define your molecule problem\n", + "\n", + "gs_problem = MoleculeProblem(\n", + " molecule=molecule,\n", + " basis=\"sto3g\",\n", + " mapping=\"jordan_wigner\", #'bravyi_kitaev'\n", + " z2_symmetries=True,\n", + " freeze_core=True,\n", + ")\n", + "\n", + "operator = gs_problem.generate_hamiltonian()\n", + "gs_problem = gs_problem.update_problem(operator.num_qubits)\n", + "print(\"Your Hamiltonian is\", operator.show(), sep=\"\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a0b57c6-a057-41cb-8163-cc91d559bbdd", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "7a0b57c6-a057-41cb-8163-cc91d559bbdd", + "outputId": "1460479e-94e8-4c11-baa9-d0b96c9916b7", + "tags": [] + }, + "outputs": [], + "source": [ + "pauli_ops = operator.pauli_list\n", + "N = operator.num_qubits\n", + "print(\"Your Pauli list is\", pauli_ops, sep=\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "685f4a01-caf3-4d0c-b9f3-4fc89bc5192a", + "metadata": { + "id": "685f4a01-caf3-4d0c-b9f3-4fc89bc5192a" + }, + "source": [ + "## 2. Preparing the Molecule for QPE" + ] + }, + { + "cell_type": "markdown", + "id": "1b1bafad-d35c-4504-9665-02b0ae86d52f", + "metadata": { + "id": "1b1bafad-d35c-4504-9665-02b0ae86d52f" + }, + "source": [ + "### 2.1 Chose the Algorithm's Precision\n", + "\n", + "For QPE algorithms, the precision is set by the number of qubits chosen $n$, such that the resolution is $1/{2^n}$. In case the matrix needs to be normlized, the resolution will be distorted. In case of normalization, that the span of results in the QPE is strached between the lowest and highest possible phase, thus the reslution will be mapped to $normalization-coefficient/{2^n} ~\\sim 1/{((\\lambda_{max}-\\lambda_{min})*2^n)}$.\n", + "\n", + "Here you can chose the precision in the parameter `n_qpe`, or by setting your desired resolution. If you chose your desired resolution and set the parameter `get_recommended_n` to be True, the number of qubits will be calculated for you accordingly.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4e96164f-aa00-4723-9f59-b1c13ccb58d8", + "metadata": { + "id": "4e96164f-aa00-4723-9f59-b1c13ccb58d8", + "tags": [] + }, + "outputs": [], + "source": [ + "# `n_qpe`- The precision of the QPE (the number of qubits to be used in the QPE. Creates resolution of 1/2^n_qpe\n", + "n_qpe = 6" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "74aeea8b-1e16-408f-bc5f-c5888b552a6f", + "metadata": { + "id": "74aeea8b-1e16-408f-bc5f-c5888b552a6f", + "tags": [] + }, + "outputs": [], + "source": [ + "# recommanded n_qpe:\n", + "get_recommanded_n = False\n", + "\n", + "import math\n", + "\n", + "desired_resolution = 0.02\n", + "\n", + "\n", + "def get_nqpe(pauli_operator, desired_resolution):\n", + " N = pauli_operator.num_qubits\n", + " A = 0\n", + " for a, b in pauli_operator.pauli_list:\n", + " A = A + abs(b)\n", + " nqpe = math.log2(2 * N * A / desired_resolution)\n", + " return math.ceil(nqpe)\n", + "\n", + "\n", + "if get_recommanded_n:\n", + " n_qpe = get_nqpe(operator, desired_resolution)\n", + " print(\"number of qubits for QPE is\", n_qpe)" + ] + }, + { + "cell_type": "markdown", + "id": "fa3d1079-c12b-48db-8935-1ea059fdbce9", + "metadata": { + "id": "fa3d1079-c12b-48db-8935-1ea059fdbce9" + }, + "source": [ + "### 2.3 Normalize the Matrix\n", + "\n", + "As QPE obtains a phase in the form $e^{2\\pi i\\theta}$, there is meaning only for $\\theta \\in [0,2\\pi)$. Generally, our matrix M can have any eigenvalue, thus \\theta can have any value. In order to fix this discrepancy, the values of the matrix are stretched to be rescaled. We assume\n", + "$\\theta \\in [\\lambda_{min}, \\lambda_{max}]$\n", + "and use a normalization function in order to map those values into $[0, 1-1/{2^n}]$, where n is the number of qubits chosen for the QPE process in section 2.2.\n", + "\n", + "We perform the normalization procedure as following:\n", + "\n", + "a. We evaluate $\\lambda_{min},\\lambda_{max}$ (in the function ` normalization_params()` below). In order to do so we use rough estimation of the absolute max value that can take place by adding together all the pauli coefficients and multiplying by the matrix's dimensions. That will yield us a value $\\lambda$ (which is referred in the code as `normalization_coeff`) and we now assume that the domain is $\\theta \\in [-\\lambda, \\lambda]$.\n", + "In general, one can build a more accurate assessment, which will decrease the span of solutions and thus achieve a better resolution.\n", + "\n", + "b. We make sure only positive values are available by adding $\\lambda*I^n$ to the pauli list. Now our evaluated span is $[0, 2*\\lambda]$.\n", + "\n", + "c. We normlize our matrix by multiplying all of the pauli coefficients by $(1-1/2^n)/(2*\\lambda)$. Now the span of $\\theta$ is $[0, 1-1/2^n]$, as required for proper QPE process.\n", + "\n", + "The values of the matrix's eigenvalues should be now between $0$ to $1-(1/2^n)$. The QPE procedure will be performed on this new normalized matrix. After the phases are obtained, the original phases of the pre-normalized matrix will be gathered by performing opposite steps to this normalization procedure.\n", + "\n", + "* Note that in case your matrix's eigenvalues are naturally between the values $0$ to $1-(1/2^n)$, you may not want to normalize it, as the normalization procedure may enlarge the span, thus lowering the resolution of the agorithm. In that case, you may skip those lines or change the value `normalize` to False." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "70d8b16f-5f50-4272-9b7b-0ca7cad00b60", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "70d8b16f-5f50-4272-9b7b-0ca7cad00b60", + "outputId": "4c9491de-b9f5-4855-edac-2798e3def5ab", + "tags": [] + }, + "outputs": [], + "source": [ + "from typing import cast\n", + "\n", + "from classiq import Pauli, PauliTerm\n", + "\n", + "# normalizing the operator\n", + "## we need to create a matrix such that its normalized version will have eigenvalues of [0,1/2^k] when k is the resolution of the QPE\n", + "normalize = True\n", + "\n", + "\n", + "def normalization_params(pauli_list, N):\n", + " A = 0\n", + " for a, b in pauli_list:\n", + " A = A + abs(b)\n", + " return N * A\n", + "\n", + "\n", + "def normalize_hamiltonian(pauli_list, normalization_coeff, k):\n", + " new_pauli_list = []\n", + " for a, b in pauli_list:\n", + " if a == \"I\" * N:\n", + " new_pauli_list.append(\n", + " (\n", + " a,\n", + " (b + normalization_coeff)\n", + " * (1 - 1 / (2**k))\n", + " / (2 * normalization_coeff),\n", + " )\n", + " )\n", + " else:\n", + " new_pauli_list.append((a, b * (1 - 1 / (2**k)) / (2 * normalization_coeff)))\n", + " return new_pauli_list\n", + "\n", + "\n", + "pauli_list = pauli_ops\n", + "if normalize:\n", + " normalization_coeff = normalization_params(pauli_ops, N)\n", + " new_pauli_list = normalize_hamiltonian(pauli_ops, normalization_coeff, n_qpe)\n", + " pauli_ops = new_pauli_list\n", + " print(pauli_ops)" + ] + }, + { + "cell_type": "markdown", + "id": "21e4de42-3417-46d4-b981-664bb0683dc4", + "metadata": { + "id": "21e4de42-3417-46d4-b981-664bb0683dc4" + }, + "source": [ + "Convert the objects to qmod:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e340b469-5566-4bd5-bb5d-3107ebc790e0", + "metadata": { + "id": "e340b469-5566-4bd5-bb5d-3107ebc790e0", + "tags": [] + }, + "outputs": [], + "source": [ + "CHAR_TO_STUCT_DICT = {\"I\": Pauli.I, \"X\": Pauli.X, \"Y\": Pauli.Y, \"Z\": Pauli.Z}\n", + "\n", + "\n", + "def pauli_str_to_enums(pauli):\n", + " return [CHAR_TO_STUCT_DICT[s] for s in pauli]\n", + "\n", + "\n", + "def pauli_list_to_hamiltonian(pauli_list):\n", + " return [\n", + " PauliTerm(\n", + " pauli=pauli_str_to_enums(pauli), coefficient=cast(complex, coeff).real\n", + " )\n", + " for pauli, coeff in pauli_list\n", + " ]" + ] + }, + { + "cell_type": "markdown", + "id": "62d2e51d-d532-4c26-86dd-a5b9b40d009e", + "metadata": { + "id": "62d2e51d-d532-4c26-86dd-a5b9b40d009e" + }, + "source": [ + "## 3. Creating the Quantum Circuit\n", + "\n", + "We will now create a quantum circuit of the QPE algorithm using the Classiq platform. The user is able to fill in their constraints and preferences as desired." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd4ee616-2a11-46ba-adc0-ed5171d7dd7d", + "metadata": { + "id": "fd4ee616-2a11-46ba-adc0-ed5171d7dd7d", + "tags": [] + }, + "outputs": [], + "source": [ + "constraints = Constraints()\n", + "preferences = Preferences(timeout_seconds=600)" + ] + }, + { + "cell_type": "markdown", + "id": "43c249a1-9db3-4164-bec1-f345670d4cd1", + "metadata": { + "id": "43c249a1-9db3-4164-bec1-f345670d4cd1" + }, + "source": [ + "### 3.1. Create the phase estimation model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b05c5ced-e02a-4b56-acc5-c62de3564239", + "metadata": { + "id": "b05c5ced-e02a-4b56-acc5-c62de3564239", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import molecule_problem_to_qmod\n", + "from classiq.qmod import (\n", + " CInt,\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QCallable,\n", + " QNum,\n", + " allocate,\n", + " allocate_num,\n", + " control,\n", + " invert,\n", + " qfunc,\n", + " repeat,\n", + ")\n", + "from classiq.qmod.builtins import (\n", + " H,\n", + " apply_to_all,\n", + " exponentiation_with_depth_constraint,\n", + " molecule_hartree_fock,\n", + " qft,\n", + ")\n", + "from classiq.qmod.symbolic import log, pi\n", + "\n", + "# this constant will be multipled be a linear factor for each qbit of the qpe, so the\n", + "# depth will scale linear with the power of each unitary, on the expense of approximating the\n", + "# exponentiation function\n", + "exp_max_depth = 2200\n", + "\n", + "\n", + "# define a Quantum Phase Estimation function that allows specifying each controlled\n", + "# power unitary directly\n", + "@qfunc\n", + "def my_flexible_qpe(\n", + " unitary_with_power: QCallable[CInt],\n", + " phase: QArray[QBit],\n", + ") -> None:\n", + " apply_to_all(H, phase)\n", + "\n", + " repeat(\n", + " count=phase.len,\n", + " iteration=lambda index: control(\n", + " ctrl=phase[index],\n", + " operand=lambda: unitary_with_power(2**index),\n", + " ),\n", + " )\n", + " invert(lambda: qft(phase))\n", + "\n", + "\n", + "@qfunc\n", + "def main(reg: Output[QArray[QBit]], phase: Output[QNum]):\n", + " allocate_num(num_qubits=n_qpe, is_signed=False, fraction_digits=n_qpe, out=phase)\n", + " allocate(N, reg)\n", + "\n", + " # The state chosen for the initial state is HF, as usually it has good overlap with the with the eigenstate of minimal energy.\n", + " molecule_hartree_fock(molecule_problem_to_qmod(gs_problem), reg)\n", + "\n", + " # # Hereby we send the pauli list created for the molecule for creating phase estimation circuit.\n", + " my_flexible_qpe(\n", + " lambda power: exponentiation_with_depth_constraint(\n", + " pauli_list_to_hamiltonian(pauli_ops),\n", + " evolution_coefficient=-2 * np.pi * power,\n", + " max_depth=exp_max_depth * ((2**0.5) ** log(power, 2)),\n", + " qbv=reg,\n", + " ),\n", + " phase,\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "467eca03-8a66-43d8-b2af-6d86b21e36d5", + "metadata": { + "id": "467eca03-8a66-43d8-b2af-6d86b21e36d5", + "tags": [] + }, + "source": [ + "## 3.2. Synthesizing the Circuit\n", + "\n", + "Hereby we syntesize the circuit and show it using the analyzer." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10eaa569-de42-41b4-b615-c04bdc850ecf", + "metadata": { + "id": "10eaa569-de42-41b4-b615-c04bdc850ecf", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import create_model\n", + "from classiq.execution import ExecutionPreferences\n", + "\n", + "num_shots = 200000\n", + "\n", + "qmod = create_model(\n", + " main,\n", + " constraints=constraints,\n", + " preferences=preferences,\n", + " execution_preferences=ExecutionPreferences(num_shots=num_shots),\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7aae67f-1750-43be-9446-74fa0565058a", + "metadata": { + "id": "a7aae67f-1750-43be-9446-74fa0565058a", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import write_qmod\n", + "\n", + "write_qmod(qmod, name=\"qpe_for_molecules\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d434afe-5cbc-4a56-a48c-e657090c348a", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "8d434afe-5cbc-4a56-a48c-e657090c348a", + "outputId": "660ea141-5ece-4b9f-ca7b-68e2abdea824", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import show, synthesize\n", + "\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "id": "7483f266-af0f-4d08-aa96-317b4044df58", + "metadata": { + "id": "7483f266-af0f-4d08-aa96-317b4044df58" + }, + "source": [ + "# 4. Measurment and Analysis\n" + ] + }, + { + "cell_type": "markdown", + "id": "e5bf0b3c-839f-43de-9da1-cba55ceba995", + "metadata": { + "id": "e5bf0b3c-839f-43de-9da1-cba55ceba995" + }, + "source": [ + "### 4.1. Circuit Execution\n", + "\n", + "The circuit is now sent to execution on a default simulator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc063bfc-de4b-4181-82b1-f805f86baa2e", + "metadata": { + "id": "bc063bfc-de4b-4181-82b1-f805f86baa2e", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import execute\n", + "\n", + "results = execute(qprog).result()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05e682bd-0f1a-4e10-ba0b-e0bf3378fecd", + "metadata": { + "id": "05e682bd-0f1a-4e10-ba0b-e0bf3378fecd", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq.execution import ExecutionDetails\n", + "\n", + "results = results[0].value" + ] + }, + { + "cell_type": "markdown", + "id": "8611351f-1b14-4969-878d-6f022cdfce2a", + "metadata": { + "id": "8611351f-1b14-4969-878d-6f022cdfce2a" + }, + "source": [ + "### 4.2. Presenting the Result's Count" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9c0ee98c-3ffa-4f1d-9cb2-4fada19b08b4", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "9c0ee98c-3ffa-4f1d-9cb2-4fada19b08b4", + "outputId": "dbdec0d4-3bef-487c-ce25-5761628ee8ab", + "tags": [] + }, + "outputs": [], + "source": [ + "results.parsed_counts_of_outputs(\"phase\")[:10]" + ] + }, + { + "cell_type": "markdown", + "id": "41009d2c-4276-409b-b9f4-8dee8103f208", + "metadata": { + "id": "41009d2c-4276-409b-b9f4-8dee8103f208" + }, + "source": [ + "### 4.3. Chosing the Most Probable Solution\n", + "\n", + "Hereby the user will choose the number of eigenvalues they wish to extract from the poll of results. The\n", + "value `number_of_solutions` will determine how many results out of `qpe_results` will be analyzed.\n", + "The `parsed_counts` property is already sorted.\n", + "\n", + "We get the result in the `phase` variable already encoded as fixed point variable in the range [0,1]." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba022acc-738c-4685-a7ff-70ea2c400bfd", + "metadata": { + "id": "ba022acc-738c-4685-a7ff-70ea2c400bfd", + "tags": [] + }, + "outputs": [], + "source": [ + "number_of_solutions = 1 # to be set" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4a54cb17-8c0a-4b00-a3a3-6e276fa92b53", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "4a54cb17-8c0a-4b00-a3a3-6e276fa92b53", + "outputId": "52406be4-77d6-4bc1-e6f5-891113990de4", + "tags": [] + }, + "outputs": [], + "source": [ + "solutions = results.parsed_counts_of_outputs(\"phase\")[:number_of_solutions]\n", + "print(\"Your qubit solution is\", solutions, sep=\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "2f784e6f-d7ed-4cc9-81dd-f6b952d0dc01", + "metadata": { + "id": "2f784e6f-d7ed-4cc9-81dd-f6b952d0dc01" + }, + "source": [ + "### 4.4. Translating into Energy value (Phase)" + ] + }, + { + "cell_type": "markdown", + "id": "d83d16de-2450-4c7a-8093-26bf13d4dce4", + "metadata": { + "id": "d83d16de-2450-4c7a-8093-26bf13d4dce4" + }, + "source": [ + "Map the phase back into the original values, i.e. renormalized into it's original span." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "836084e1-a20d-4a55-93cc-91a40c1d2f53", + "metadata": { + "id": "836084e1-a20d-4a55-93cc-91a40c1d2f53", + "tags": [] + }, + "outputs": [], + "source": [ + "def post_process_phase(phase):\n", + " return (\n", + " (phase * 2 * normalization_coeff) / (1 - (1 / 2**n_qpe))\n", + " ) - normalization_coeff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a5bdb723-b015-4e80-98ea-985901c6c8d7", + "metadata": { + "id": "a5bdb723-b015-4e80-98ea-985901c6c8d7", + "tags": [] + }, + "outputs": [], + "source": [ + "# renormalize into the \"real\" solution -\n", + "if normalize:\n", + " solution = [post_process_phase(value.state[\"phase\"]) for value in solutions]\n", + "else:\n", + " solution = phase" + ] + }, + { + "cell_type": "markdown", + "id": "6c963b82-26a7-4251-bae0-32e66c57fa1d", + "metadata": { + "id": "6c963b82-26a7-4251-bae0-32e66c57fa1d" + }, + "source": [ + "The final results of the Energy (matrix's eigenvlues) is therefore:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "43e8ec8f-2be9-403d-8ae9-9380fb2b08c9", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "43e8ec8f-2be9-403d-8ae9-9380fb2b08c9", + "outputId": "57fe6127-9b33-4cc5-ffcc-a121004cf862", + "tags": [] + }, + "outputs": [], + "source": [ + "print(solution)" + ] + }, + { + "cell_type": "markdown", + "id": "7565aa1f-b8ba-4617-a2ef-79317261dfe7", + "metadata": { + "id": "7565aa1f-b8ba-4617-a2ef-79317261dfe7" + }, + "source": [ + "And the results including the error contributed from the resolution (number of qubits participating in the QPE) are:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79f1c1ba-61fd-438e-a3d5-7606ea95e70f", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "79f1c1ba-61fd-438e-a3d5-7606ea95e70f", + "outputId": "d75f1d8a-8af0-48c8-a552-a37bf9fbf641", + "tags": [] + }, + "outputs": [], + "source": [ + "if normalize:\n", + " energy_resolution = (\n", + " (1 / (2**n_qpe)) * 2 * normalization_coeff / (1 - (1 / 2**n_qpe))\n", + " )\n", + "else:\n", + " energy_resolution = 1 / (2**n_qpe)\n", + "\n", + "print(\"the resolution of result is\", energy_resolution)\n", + "\n", + "for sol in solution:\n", + " print(\n", + " \"the eneregy solution is beteen\",\n", + " sol - energy_resolution,\n", + " \"and\",\n", + " sol + energy_resolution,\n", + " )\n", + "\n", + " ###if zero or exceed the normalization range need to add conditions" + ] + }, + { + "cell_type": "markdown", + "id": "d570c6b0-bd32-40d1-9ebb-c1ee7c8663ad", + "metadata": { + "id": "d570c6b0-bd32-40d1-9ebb-c1ee7c8663ad" + }, + "source": [ + "### 4.4. Find Exact Solution for Comparison" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd9e84a5-d131-4835-bade-13ba01035b44", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "bd9e84a5-d131-4835-bade-13ba01035b44", + "outputId": "7cfc9892-b918-4447-806d-f13493e84053", + "tags": [] + }, + "outputs": [], + "source": [ + "mat = operator.to_matrix()\n", + "w, v = np.linalg.eig(mat)\n", + "print(\"exact result:\", np.real(min(w)))" + ] + }, + { + "cell_type": "markdown", + "id": "703c6ae7-5174-433f-ad9f-78f9864b1914", + "metadata": { + "id": "703c6ae7-5174-433f-ad9f-78f9864b1914" + }, + "source": [ + "### 4.4. Find the Solution's Histogram" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dfc5f725-495b-45d1-9c67-a1daf80a1454", + "metadata": { + "id": "dfc5f725-495b-45d1-9c67-a1daf80a1454", + "tags": [] + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "energy_vec = []\n", + "energy_prob = []\n", + "\n", + "for value, counts in results.parsed_counts_of_outputs(\"phase\"):\n", + " temp = value[1][\"phase\"]\n", + " if normalize:\n", + " temp2 = (\n", + " temp * 2 * normalization_coeff / (1 - (1 / 2**n_qpe))\n", + " ) - normalization_coeff\n", + " else:\n", + " temp2 = temp\n", + " energy_vec.append(temp2)\n", + " energy_prob.append(counts[1] / num_shots)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "993c5b3b-7a05-44f1-9c4e-6651cd50f4cb", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 430 + }, + "id": "993c5b3b-7a05-44f1-9c4e-6651cd50f4cb", + "outputId": "640fb07e-7b78-45ad-958a-c447af80f9be", + "tags": [] + }, + "outputs": [], + "source": [ + "plt.plot(energy_vec, energy_prob, \".\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "9797b512-d41f-47c1-8c0f-4134f0500b80", + "metadata": { + "id": "9797b512-d41f-47c1-8c0f-4134f0500b80" + }, + "source": [ + "## References\n", + "\n", + "[1]: Michael A. Nielsen and Isaac L. Chuang. 2011. Quantum Computation and Quantum Information: 10th Anniversary Edition, Cambridge University Press, New York, NY, USA.\n", + "]\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 +} From 111501456470991310788383c1dd170b0cf44b69 Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Sat, 15 Jun 2024 04:50:33 +0200 Subject: [PATCH 13/18] Delete community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb --- .../HW3/Hisham_Mansour_HW3_VQE.ipynb | 497 ------------------ 1 file changed, 497 deletions(-) delete mode 100644 community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb diff --git a/community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb b/community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb deleted file mode 100644 index a904dd5a..00000000 --- a/community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb +++ /dev/null @@ -1,497 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "fc72d98f-8993-4bd4-a545-23d122f3df71", - "metadata": { - "id": "fc72d98f-8993-4bd4-a545-23d122f3df71" - }, - "source": [ - "# 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." - ] - }, - { - "cell_type": "markdown", - "id": "56eda6d8-76c4-4862-b914-0c4598d67274", - "metadata": { - "id": "56eda6d8-76c4-4862-b914-0c4598d67274" - }, - "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", - "\n", - "## Additional Resources\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", - "\n", - "---\n", - "\n", - "Happy coding and good luck!" - ] - }, - { - "cell_type": "markdown", - "id": "d41e969d-f6a7-4ff7-9660-19ce6c97ba6b", - "metadata": { - "id": "d41e969d-f6a7-4ff7-9660-19ce6c97ba6b" - }, - "source": [ - "### Part 1" - ] - }, - { - "cell_type": "markdown", - "id": "f710d6f4-d40b-42d5-b524-c6acb8059fe2", - "metadata": { - "id": "f710d6f4-d40b-42d5-b524-c6acb8059fe2" - }, - "source": [ - "Given the following Hamiltonian:" - ] - }, - { - "cell_type": "markdown", - "id": "6ba8a6f1-3259-4492-a1ca-3abde7530cd4", - "metadata": { - "id": "6ba8a6f1-3259-4492-a1ca-3abde7530cd4" - }, - "source": [ - "$$\n", - "\\hat{H} = -1.0523 \\cdot (I \\otimes I) + 0.3979 \\cdot (I \\otimes Z) - 0.3979 \\cdot (Z \\otimes I) - 0.0112 \\cdot (Z \\otimes Z) + 0.1809 \\cdot (X \\otimes X)\n", - "$$" - ] - }, - { - "cell_type": "markdown", - "id": "736d275c-9a5a-4c08-b891-3078430dc6c1", - "metadata": { - "id": "736d275c-9a5a-4c08-b891-3078430dc6c1" - }, - "source": [ - "Complete the following code" - ] - }, - { - "cell_type": "code", - "source": [ - "!pip install -U classiq" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "collapsed": true, - "id": "DQOxbZxjrN5r", - "outputId": "ba3dffa0-ff88-4a89-b76f-a0bd6c05f164" - }, - "id": "DQOxbZxjrN5r", - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Collecting classiq\n", - " Downloading classiq-0.42.0-py3-none-any.whl (401 kB)\n", - "\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/401.5 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[91m━━━━━━━━━━━━━━\u001b[0m\u001b[90m╺\u001b[0m\u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m143.4/401.5 kB\u001b[0m \u001b[31m4.2 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m401.5/401.5 kB\u001b[0m \u001b[31m6.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hCollecting ConfigArgParse<2.0.0,>=1.5.3 (from classiq)\n", - " Downloading ConfigArgParse-1.7-py3-none-any.whl (25 kB)\n", - "Collecting Pyomo<6.6,>=6.5 (from classiq)\n", - " Downloading Pyomo-6.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (10.7 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m10.7/10.7 MB\u001b[0m \u001b[31m31.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hCollecting black<25.0,>=24.0 (from classiq)\n", - " Downloading black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.8/1.8 MB\u001b[0m \u001b[31m22.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hCollecting httpx<1,>=0.23.0 (from classiq)\n", - " Downloading httpx-0.27.0-py3-none-any.whl (75 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.6/75.6 kB\u001b[0m \u001b[31m5.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: keyring<24.0.0,>=23.5.0 in /usr/lib/python3/dist-packages (from classiq) (23.5.0)\n", - "Requirement already satisfied: matplotlib<4.0.0,>=3.4.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (3.7.1)\n", - "Collecting networkx<3.0.0,>=2.5.1 (from classiq)\n", - " Downloading networkx-2.8.8-py3-none-any.whl (2.0 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m50.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: numexpr<3.0.0,>=2.7.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.10.0)\n", - "Requirement already satisfied: numpy<2.0.0,>=1.20.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.25.2)\n", - "Collecting packaging<23.0,>=22.0 (from classiq)\n", - " Downloading packaging-22.0-py3-none-any.whl (42 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m42.6/42.6 kB\u001b[0m \u001b[31m2.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: pandas<3.0.0,>=1.4.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.0.3)\n", - "Requirement already satisfied: plotly<6.0.0,>=5.7.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (5.15.0)\n", - "Collecting pydantic<2.0.0,>=1.9.1 (from classiq)\n", - " Downloading pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.1/3.1 MB\u001b[0m \u001b[31m48.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: scipy<2.0.0,>=1.10.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.11.4)\n", - "Collecting sympy<1.11.0,>=1.9.0 (from classiq)\n", - " Downloading sympy-1.10.1-py3-none-any.whl (6.4 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.4/6.4 MB\u001b[0m \u001b[31m54.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: tabulate<1,>=0.8.9 in /usr/local/lib/python3.10/dist-packages (from classiq) (0.9.0)\n", - "Requirement already satisfied: click>=8.0.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (8.1.7)\n", - "Collecting mypy-extensions>=0.4.3 (from black<25.0,>=24.0->classiq)\n", - " Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n", - "Collecting pathspec>=0.9.0 (from black<25.0,>=24.0->classiq)\n", - " Downloading pathspec-0.12.1-py3-none-any.whl (31 kB)\n", - "Requirement already satisfied: platformdirs>=2 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.2.2)\n", - "Requirement already satisfied: tomli>=1.1.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (2.0.1)\n", - "Requirement already satisfied: typing-extensions>=4.0.1 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.11.0)\n", - "Requirement already satisfied: anyio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7.1)\n", - "Requirement already satisfied: certifi in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (2024.2.2)\n", - "Collecting httpcore==1.* (from httpx<1,>=0.23.0->classiq)\n", - " Downloading httpcore-1.0.5-py3-none-any.whl (77 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.9/77.9 kB\u001b[0m \u001b[31m4.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: idna in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7)\n", - "Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (1.3.1)\n", - "Collecting h11<0.15,>=0.13 (from httpcore==1.*->httpx<1,>=0.23.0->classiq)\n", - " Downloading h11-0.14.0-py3-none-any.whl (58 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m3.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.2.1)\n", - "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (0.12.1)\n", - "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (4.51.0)\n", - "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.4.5)\n", - "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (9.4.0)\n", - "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (3.1.2)\n", - "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (2.8.2)\n", - "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2023.4)\n", - "Requirement already satisfied: tzdata>=2022.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2024.1)\n", - "Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from plotly<6.0.0,>=5.7.0->classiq) (8.3.0)\n", - "Collecting ply (from Pyomo<6.6,>=6.5->classiq)\n", - " Downloading ply-3.11-py2.py3-none-any.whl (49 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.6/49.6 kB\u001b[0m \u001b[31m734.3 kB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy<1.11.0,>=1.9.0->classiq) (1.3.0)\n", - "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.7->matplotlib<4.0.0,>=3.4.3->classiq) (1.16.0)\n", - "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio->httpx<1,>=0.23.0->classiq) (1.2.1)\n", - "Installing collected packages: ply, sympy, Pyomo, pydantic, pathspec, packaging, networkx, mypy-extensions, h11, ConfigArgParse, httpcore, black, httpx, classiq\n", - " Attempting uninstall: sympy\n", - " Found existing installation: sympy 1.12\n", - " Uninstalling sympy-1.12:\n", - " Successfully uninstalled sympy-1.12\n", - " Attempting uninstall: pydantic\n", - " Found existing installation: pydantic 2.7.1\n", - " Uninstalling pydantic-2.7.1:\n", - " Successfully uninstalled pydantic-2.7.1\n", - " Attempting uninstall: packaging\n", - " Found existing installation: packaging 24.0\n", - " Uninstalling packaging-24.0:\n", - " Successfully uninstalled packaging-24.0\n", - " Attempting uninstall: networkx\n", - " Found existing installation: networkx 3.3\n", - " Uninstalling networkx-3.3:\n", - " Successfully uninstalled networkx-3.3\n", - "\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", - "torch 2.3.0+cu121 requires nvidia-cublas-cu12==12.1.3.1; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cuda-cupti-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cuda-nvrtc-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cuda-runtime-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cudnn-cu12==8.9.2.26; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cufft-cu12==11.0.2.54; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-curand-cu12==10.3.2.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cusolver-cu12==11.4.5.107; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cusparse-cu12==12.1.0.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-nccl-cu12==2.20.5; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-nvtx-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\u001b[0m\u001b[31m\n", - "\u001b[0mSuccessfully installed ConfigArgParse-1.7 Pyomo-6.5.0 black-24.4.2 classiq-0.42.0 h11-0.14.0 httpcore-1.0.5 httpx-0.27.0 mypy-extensions-1.0.0 networkx-2.8.8 packaging-22.0 pathspec-0.12.1 ply-3.11 pydantic-1.10.15 sympy-1.10.1\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "import classiq\n", - "classiq.authenticate()" - ], - "metadata": { - "id": "jLanwByIe4eJ", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "dea1c702-533c-492a-f2c7-4406c6fdb7f0" - }, - "id": "jLanwByIe4eJ", - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Your user code: LSSS-MJFD\n", - "If a browser doesn't automatically open, please visit this URL from any trusted device: https://auth.classiq.io/activate?user_code=LSSS-MJFD\n" - ] - } - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "19266c11-6acc-4edb-910f-2d0dfe80a6c8", - "metadata": { - "id": "19266c11-6acc-4edb-910f-2d0dfe80a6c8" - }, - "outputs": [], - "source": [ - "from typing import List\n", - "from classiq import *\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", - "])" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "0bb68899-2076-45c0-8868-131f38aa3b78", - "metadata": { - "id": "0bb68899-2076-45c0-8868-131f38aa3b78" - }, - "outputs": [], - "source": [ - "@qfunc\n", - "def main(q: Output[QArray[QBit]], angles: CArray[CReal, 3]) -> None:\n", - " # TODO: Create an ansatz which allows each qubit to have\n", - " # arbitrary rotation\n", - " allocate(2, q)\n", - "\n", - " U(angles[0], angles[1], angles[2], 0, q[0])\n", - " U(angles[0], angles[1], angles[2], 0, q[1])\n", - "\n", - "@cfunc\n", - "def cmain() -> None:\n", - " res = vqe(\n", - " hamiltonian=HAMILTONIAN,\n", - " maximize=False,\n", - " initial_point=[],\n", - " optimizer=Optimizer.COBYLA,\n", - " max_iteration=1000,\n", - " tolerance=0.001,\n", - " step_size=0,\n", - " skip_compute_variance=False,\n", - " alpha_cvar=1.0,\n", - " )\n", - " save({\"result\": res})\n", - "\n", - "#TODO: complete the line, use classical_execution_function\n", - "qmod = create_model(main, classical_execution_function=cmain)\n", - "\n", - "qprog = synthesize(qmod)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "0563c1a8-7aec-4da9-9105-6b16c5c24382", - "metadata": { - "id": "0563c1a8-7aec-4da9-9105-6b16c5c24382" - }, - "outputs": [], - "source": [ - "execution = execute(qprog)\n", - "res = execution.result()\n", - "# execution.open_in_ide()\n", - "vqe_result = res[0].value\n" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "de17cfc0-8e64-4493-b4c2-4a97fc9797a0", - "metadata": { - "scrolled": true, - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "id": "de17cfc0-8e64-4493-b4c2-4a97fc9797a0", - "outputId": "5b400695-8faf-4aae-e8b8-bdc477e211e1" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Optimal energy: -1.0546669921875\n", - "Optimal parameters: {'angles_0': 6.279238566143106, 'angles_1': -0.7105268722399182, 'angles_2': 4.394957787844692}\n", - "Eigenstate: {'00': (1+0j)}\n" - ] - } - ], - "source": [ - "print(f\"Optimal energy: {vqe_result.energy}\")\n", - "print(f\"Optimal parameters: {vqe_result.optimal_parameters}\")\n", - "print(f\"Eigenstate: {vqe_result.eigenstate}\")" - ] - }, - { - "cell_type": "markdown", - "id": "5df11dfc-3e3a-4191-bd47-d522ca3dcbfa", - "metadata": { - "id": "5df11dfc-3e3a-4191-bd47-d522ca3dcbfa" - }, - "source": [ - "Does it similar to the `optimal energy` we calculated in class? \\\n", - "Does it similar to the `total energy` we calculated in class?" - ] - }, - { - "cell_type": "markdown", - "id": "4f0e0bea-b12f-43ad-94e8-100fedf2b57f", - "metadata": { - "id": "4f0e0bea-b12f-43ad-94e8-100fedf2b57f" - }, - "source": [ - "### Part 2" - ] - }, - { - "cell_type": "markdown", - "id": "66882248-de08-4a6e-b33c-647f015f7d79", - "metadata": { - "id": "66882248-de08-4a6e-b33c-647f015f7d79" - }, - "source": [ - "**Now, we want to have a more interesting ansatz in our `main`.** \n", - "Add **one** line of code to the `main` function you created in Part 1 that creates **entanglement** between the two qubits. \n", - "Which gate should you use?" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "bb39be9e-4994-44e5-84d8-c99bc8b77145", - "metadata": { - "id": "bb39be9e-4994-44e5-84d8-c99bc8b77145" - }, - "outputs": [], - "source": [ - "@qfunc\n", - "def main(q: Output[QArray[QBit]], angles: CArray[CReal, 3]) -> None:\n", - " # TODO: Create an ansatz which allows each qubit to have\n", - " # arbitrary rotation\n", - " allocate(2, q)\n", - "\n", - " U(angles[0], angles[1], angles[2], 0, q[0])\n", - " U(angles[0], angles[1], angles[2], 0, q[1])\n", - "\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", - " False,\n", - " [],\n", - " optimizer=Optimizer.COBYLA,\n", - " max_iteration=1000,\n", - " tolerance=0.001,\n", - " step_size=0,\n", - " skip_compute_variance=False,\n", - " alpha_cvar=1.0,\n", - " )\n", - " save({\"result\": res})\n", - "\n", - "#TODO: complete the line, use classical_execution_function\n", - "qmod = create_model(main, classical_execution_function=cmain)\n", - "\n", - "qprog = synthesize(qmod)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "112a1590-283c-4f79-8035-72936561102d", - "metadata": { - "id": "112a1590-283c-4f79-8035-72936561102d" - }, - "outputs": [], - "source": [ - "execution = execute(qprog)\n", - "res = execution.result()\n", - "# execution.open_in_ide()\n", - "vqe_result = res[0].value\n" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "06500e4c-a04b-4cfa-a84d-41f96a0c68eb", - "metadata": { - "collapsed": true, - "jupyter": { - "outputs_hidden": true - }, - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "id": "06500e4c-a04b-4cfa-a84d-41f96a0c68eb", - "outputId": "c406023c-627c-468c-d48c-cddf2d234297" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Optimal energy: -1.84395341796875\n", - "Optimal parameters: {'angles_0': 3.220640081190124, 'angles_1': 0.48857020981030813, 'angles_2': 1.69265245066969}\n", - "Eigenstate: {'10': (0.03125+0j), '11': (0.03125+0j), '01': (0.9990229601966113+0j)}\n" - ] - } - ], - "source": [ - "print(f\"Optimal energy: {vqe_result.energy}\")\n", - "print(f\"Optimal parameters: {vqe_result.optimal_parameters}\")\n", - "print(f\"Eigenstate: {vqe_result.eigenstate}\")" - ] - }, - { - "cell_type": "markdown", - "id": "30a635d7-2f15-4c94-a94b-f4270f17aed8", - "metadata": { - "id": "30a635d7-2f15-4c94-a94b-f4270f17aed8" - }, - "source": [ - "Does it similar to the `optimal energy` we calculated in class? \\\n", - "Does it similar to the `total energy` we calculated in class? \\\n", - "What can we learn about the provided form this result Hamiltonian?" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.16" - }, - "colab": { - "provenance": [] - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file From ec5c3a7eb500bfab00665b0ce1274b98b2704b2a Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Sat, 15 Jun 2024 04:51:10 +0200 Subject: [PATCH 14/18] Add files via upload --- .../HW3/Hisham_Mansour_HW3_VQE.ipynb | 385 ++++++++++++++++++ 1 file changed, 385 insertions(+) create mode 100644 community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb diff --git a/community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb b/community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb new file mode 100644 index 00000000..5b1ddb26 --- /dev/null +++ b/community/QClass_2024/Submissions/HW3/Hisham_Mansour_HW3_VQE.ipynb @@ -0,0 +1,385 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fc72d98f-8993-4bd4-a545-23d122f3df71", + "metadata": { + "id": "fc72d98f-8993-4bd4-a545-23d122f3df71" + }, + "source": [ + "# 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." + ] + }, + { + "cell_type": "markdown", + "id": "56eda6d8-76c4-4862-b914-0c4598d67274", + "metadata": { + "id": "56eda6d8-76c4-4862-b914-0c4598d67274" + }, + "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", + "\n", + "## Additional Resources\n", + "- Classiq Documentation\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", + "\n", + "---\n", + "\n", + "Happy coding and good luck!" + ] + }, + { + "cell_type": "markdown", + "id": "d41e969d-f6a7-4ff7-9660-19ce6c97ba6b", + "metadata": { + "id": "d41e969d-f6a7-4ff7-9660-19ce6c97ba6b" + }, + "source": [ + "### Part 1" + ] + }, + { + "cell_type": "markdown", + "id": "f710d6f4-d40b-42d5-b524-c6acb8059fe2", + "metadata": { + "id": "f710d6f4-d40b-42d5-b524-c6acb8059fe2" + }, + "source": [ + "Given the following Hamiltonian:" + ] + }, + { + "cell_type": "markdown", + "id": "6ba8a6f1-3259-4492-a1ca-3abde7530cd4", + "metadata": { + "id": "6ba8a6f1-3259-4492-a1ca-3abde7530cd4" + }, + "source": [ + "$$\n", + "\\hat{H} = -1.0523 \\cdot (I \\otimes I) + 0.3979 \\cdot (I \\otimes Z) - 0.3979 \\cdot (Z \\otimes I) - 0.0112 \\cdot (Z \\otimes Z) + 0.1809 \\cdot (X \\otimes X)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "id": "736d275c-9a5a-4c08-b891-3078430dc6c1", + "metadata": { + "id": "736d275c-9a5a-4c08-b891-3078430dc6c1" + }, + "source": [ + "Complete the following code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "DQOxbZxjrN5r", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "DQOxbZxjrN5r", + "outputId": "ba3dffa0-ff88-4a89-b76f-a0bd6c05f164" + }, + "outputs": [], + "source": [ + "!pip install -U classiq" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "jLanwByIe4eJ", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "jLanwByIe4eJ", + "outputId": "dea1c702-533c-492a-f2c7-4406c6fdb7f0" + }, + "outputs": [], + "source": [ + "import classiq\n", + "classiq.authenticate()" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "19266c11-6acc-4edb-910f-2d0dfe80a6c8", + "metadata": { + "id": "19266c11-6acc-4edb-910f-2d0dfe80a6c8", + "tags": [] + }, + "outputs": [], + "source": [ + "from typing import List\n", + "from classiq import *\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", + "])" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "0bb68899-2076-45c0-8868-131f38aa3b78", + "metadata": { + "id": "0bb68899-2076-45c0-8868-131f38aa3b78", + "tags": [] + }, + "outputs": [], + "source": [ + "@qfunc\n", + "def main(q: Output[QArray[QBit]], angles: CArray[CReal, 3]) -> None:\n", + " # TODO: Create an ansatz which allows each qubit to have\n", + " # arbitrary rotation\n", + " allocate(2, q)\n", + "\n", + " U(angles[0], angles[1], angles[2], 0, q[0])\n", + " U(angles[0], angles[1], angles[2], 0, q[1])\n", + "\n", + "@cfunc\n", + "def cmain() -> None:\n", + " res = vqe(\n", + " hamiltonian=HAMILTONIAN,\n", + " maximize=False,\n", + " initial_point=[],\n", + " optimizer=Optimizer.COBYLA,\n", + " max_iteration=1000,\n", + " tolerance=0.001,\n", + " step_size=0,\n", + " skip_compute_variance=False,\n", + " alpha_cvar=1.0,\n", + " )\n", + " save({\"result\": res})\n", + "\n", + "#TODO: complete the line, use classical_execution_function\n", + "qmod = create_model(main, classical_execution_function=cmain)\n", + "\n", + "qprog = synthesize(qmod)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0563c1a8-7aec-4da9-9105-6b16c5c24382", + "metadata": { + "id": "0563c1a8-7aec-4da9-9105-6b16c5c24382", + "tags": [] + }, + "outputs": [], + "source": [ + "execution = execute(qprog)\n", + "res = execution.result()\n", + "# execution.open_in_ide()\n", + "vqe_result = res[0].value\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "de17cfc0-8e64-4493-b4c2-4a97fc9797a0", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "de17cfc0-8e64-4493-b4c2-4a97fc9797a0", + "outputId": "5b400695-8faf-4aae-e8b8-bdc477e211e1", + "scrolled": true, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal energy: -1.0583671875\n", + "Optimal parameters: {'angles_0': 6.389624985178057, 'angles_1': -4.0364699123745575, 'angles_2': -2.2358861255687543}\n", + "Eigenstate: {'01': (0.05412658773652741+0j), '10': (0.04419417382415922+0j), '00': (0.997555606219523+0j)}\n" + ] + } + ], + "source": [ + "print(f\"Optimal energy: {vqe_result.energy}\")\n", + "print(f\"Optimal parameters: {vqe_result.optimal_parameters}\")\n", + "print(f\"Eigenstate: {vqe_result.eigenstate}\")" + ] + }, + { + "cell_type": "markdown", + "id": "5df11dfc-3e3a-4191-bd47-d522ca3dcbfa", + "metadata": { + "id": "5df11dfc-3e3a-4191-bd47-d522ca3dcbfa" + }, + "source": [ + "Does it similar to the `optimal energy` we calculated in class? \\\n", + "Does it similar to the `total energy` we calculated in class?" + ] + }, + { + "cell_type": "markdown", + "id": "4f0e0bea-b12f-43ad-94e8-100fedf2b57f", + "metadata": { + "id": "4f0e0bea-b12f-43ad-94e8-100fedf2b57f" + }, + "source": [ + "### Part 2" + ] + }, + { + "cell_type": "markdown", + "id": "66882248-de08-4a6e-b33c-647f015f7d79", + "metadata": { + "id": "66882248-de08-4a6e-b33c-647f015f7d79" + }, + "source": [ + "**Now, we want to have a more interesting ansatz in our `main`.** \n", + "Add **one** line of code to the `main` function you created in Part 1 that creates **entanglement** between the two qubits. \n", + "Which gate should you use?" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "bb39be9e-4994-44e5-84d8-c99bc8b77145", + "metadata": { + "id": "bb39be9e-4994-44e5-84d8-c99bc8b77145", + "tags": [] + }, + "outputs": [], + "source": [ + "@qfunc\n", + "def main(q: Output[QArray[QBit]], angles: CArray[CReal, 3]) -> None:\n", + " # TODO: Create an ansatz which allows each qubit to have\n", + " # arbitrary rotation\n", + " allocate(2, q)\n", + "\n", + " U(angles[0], angles[1], angles[2], 0, q[0])\n", + " U(angles[0], angles[1], angles[2], 0, q[1])\n", + "\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", + " False,\n", + " [],\n", + " optimizer=Optimizer.COBYLA,\n", + " max_iteration=1000,\n", + " tolerance=0.001,\n", + " step_size=0,\n", + " skip_compute_variance=False,\n", + " alpha_cvar=1.0,\n", + " )\n", + " save({\"result\": res})\n", + "\n", + "#TODO: complete the line, use classical_execution_function\n", + "qmod = create_model(main, classical_execution_function=cmain)\n", + "\n", + "qprog = synthesize(qmod)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "112a1590-283c-4f79-8035-72936561102d", + "metadata": { + "id": "112a1590-283c-4f79-8035-72936561102d", + "tags": [] + }, + "outputs": [], + "source": [ + "execution = execute(qprog)\n", + "res = execution.result()\n", + "# execution.open_in_ide()\n", + "vqe_result = res[0].value\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "06500e4c-a04b-4cfa-a84d-41f96a0c68eb", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "06500e4c-a04b-4cfa-a84d-41f96a0c68eb", + "outputId": "c406023c-627c-468c-d48c-cddf2d234297", + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal energy: -1.8535164062499998\n", + "Optimal parameters: {'angles_0': -3.3225105782476008, 'angles_1': 3.360963994777151, 'angles_2': -1.6195325920504093}\n", + "Eigenstate: {'10': (0.09375+0j), '11': (0.08838834764831845+0j), '01': (0.9916644782889019+0j)}\n" + ] + } + ], + "source": [ + "print(f\"Optimal energy: {vqe_result.energy}\")\n", + "print(f\"Optimal parameters: {vqe_result.optimal_parameters}\")\n", + "print(f\"Eigenstate: {vqe_result.eigenstate}\")" + ] + }, + { + "cell_type": "markdown", + "id": "30a635d7-2f15-4c94-a94b-f4270f17aed8", + "metadata": { + "id": "30a635d7-2f15-4c94-a94b-f4270f17aed8" + }, + "source": [ + "Does it similar to the `optimal energy` we calculated in class? \\\n", + "Does it similar to the `total energy` we calculated in class? \\\n", + "What can we learn about the provided form this result Hamiltonian?" + ] + } + ], + "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": 5 +} From eaff5a8037acee9e1b592bf0926d7fbf210df5d2 Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Sat, 15 Jun 2024 04:52:04 +0200 Subject: [PATCH 15/18] Delete community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb --- .../HW2/Hisham_Mansour_HW2_QClass2024.ipynb | 909 ------------------ 1 file changed, 909 deletions(-) delete mode 100644 community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb diff --git a/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb b/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb deleted file mode 100644 index f3e3e17b..00000000 --- a/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb +++ /dev/null @@ -1,909 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "RyYX0oEHP7ww" - }, - "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", - "source": [ - "!pip install -U classiq" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "collapsed": true, - "id": "-xGG1F4dQFYM", - "outputId": "0d119fb0-5ddb-4067-ec41-ff1ead7d6e91" - }, - "execution_count": 1, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Collecting classiq\n", - " Downloading classiq-0.41.2-py3-none-any.whl (398 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m398.1/398.1 kB\u001b[0m \u001b[31m2.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hCollecting ConfigArgParse<2.0.0,>=1.5.3 (from classiq)\n", - " Downloading ConfigArgParse-1.7-py3-none-any.whl (25 kB)\n", - "Collecting Pyomo<6.6,>=6.5 (from classiq)\n", - " Downloading Pyomo-6.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (10.7 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m10.7/10.7 MB\u001b[0m \u001b[31m38.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hCollecting black<25.0,>=24.0 (from classiq)\n", - " Downloading black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.8/1.8 MB\u001b[0m \u001b[31m54.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hCollecting httpx<1,>=0.23.0 (from classiq)\n", - " Downloading httpx-0.27.0-py3-none-any.whl (75 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.6/75.6 kB\u001b[0m \u001b[31m5.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: keyring<24.0.0,>=23.5.0 in /usr/lib/python3/dist-packages (from classiq) (23.5.0)\n", - "Requirement already satisfied: matplotlib<4.0.0,>=3.4.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (3.7.1)\n", - "Collecting networkx<3.0.0,>=2.5.1 (from classiq)\n", - " Downloading networkx-2.8.8-py3-none-any.whl (2.0 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m67.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: numexpr<3.0.0,>=2.7.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.10.0)\n", - "Requirement already satisfied: numpy<2.0.0,>=1.20.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.25.2)\n", - "Collecting packaging<23.0,>=22.0 (from classiq)\n", - " Downloading packaging-22.0-py3-none-any.whl (42 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m42.6/42.6 kB\u001b[0m \u001b[31m2.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: pandas<3.0.0,>=1.4.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.0.3)\n", - "Requirement already satisfied: plotly<6.0.0,>=5.7.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (5.15.0)\n", - "Collecting pydantic<2.0.0,>=1.9.1 (from classiq)\n", - " Downloading pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.1/3.1 MB\u001b[0m \u001b[31m23.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: scipy<2.0.0,>=1.10.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.11.4)\n", - "Collecting sympy<1.11.0,>=1.9.0 (from classiq)\n", - " Downloading sympy-1.10.1-py3-none-any.whl (6.4 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.4/6.4 MB\u001b[0m \u001b[31m50.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: tabulate<1,>=0.8.9 in /usr/local/lib/python3.10/dist-packages (from classiq) (0.9.0)\n", - "Requirement already satisfied: click>=8.0.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (8.1.7)\n", - "Collecting mypy-extensions>=0.4.3 (from black<25.0,>=24.0->classiq)\n", - " Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n", - "Collecting pathspec>=0.9.0 (from black<25.0,>=24.0->classiq)\n", - " Downloading pathspec-0.12.1-py3-none-any.whl (31 kB)\n", - "Requirement already satisfied: platformdirs>=2 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.2.2)\n", - "Requirement already satisfied: tomli>=1.1.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (2.0.1)\n", - "Requirement already satisfied: typing-extensions>=4.0.1 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.11.0)\n", - "Requirement already satisfied: anyio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7.1)\n", - "Requirement already satisfied: certifi in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (2024.2.2)\n", - "Collecting httpcore==1.* (from httpx<1,>=0.23.0->classiq)\n", - " Downloading httpcore-1.0.5-py3-none-any.whl (77 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.9/77.9 kB\u001b[0m \u001b[31m8.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: idna in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7)\n", - "Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (1.3.1)\n", - "Collecting h11<0.15,>=0.13 (from httpcore==1.*->httpx<1,>=0.23.0->classiq)\n", - " Downloading h11-0.14.0-py3-none-any.whl (58 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m2.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.2.1)\n", - "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (0.12.1)\n", - "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (4.51.0)\n", - "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.4.5)\n", - "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (9.4.0)\n", - "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (3.1.2)\n", - "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (2.8.2)\n", - "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2023.4)\n", - "Requirement already satisfied: tzdata>=2022.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2024.1)\n", - "Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from plotly<6.0.0,>=5.7.0->classiq) (8.3.0)\n", - "Collecting ply (from Pyomo<6.6,>=6.5->classiq)\n", - " Downloading ply-3.11-py2.py3-none-any.whl (49 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.6/49.6 kB\u001b[0m \u001b[31m5.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy<1.11.0,>=1.9.0->classiq) (1.3.0)\n", - "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.7->matplotlib<4.0.0,>=3.4.3->classiq) (1.16.0)\n", - "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio->httpx<1,>=0.23.0->classiq) (1.2.1)\n", - "Installing collected packages: ply, sympy, Pyomo, pydantic, pathspec, packaging, networkx, mypy-extensions, h11, ConfigArgParse, httpcore, black, httpx, classiq\n", - " Attempting uninstall: sympy\n", - " Found existing installation: sympy 1.12\n", - " Uninstalling sympy-1.12:\n", - " Successfully uninstalled sympy-1.12\n", - " Attempting uninstall: pydantic\n", - " Found existing installation: pydantic 2.7.1\n", - " Uninstalling pydantic-2.7.1:\n", - " Successfully uninstalled pydantic-2.7.1\n", - " Attempting uninstall: packaging\n", - " Found existing installation: packaging 24.0\n", - " Uninstalling packaging-24.0:\n", - " Successfully uninstalled packaging-24.0\n", - " Attempting uninstall: networkx\n", - " Found existing installation: networkx 3.3\n", - " Uninstalling networkx-3.3:\n", - " Successfully uninstalled networkx-3.3\n", - "\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", - "torch 2.3.0+cu121 requires nvidia-cublas-cu12==12.1.3.1; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cuda-cupti-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cuda-nvrtc-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cuda-runtime-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cudnn-cu12==8.9.2.26; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cufft-cu12==11.0.2.54; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-curand-cu12==10.3.2.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cusolver-cu12==11.4.5.107; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cusparse-cu12==12.1.0.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-nccl-cu12==2.20.5; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-nvtx-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\u001b[0m\u001b[31m\n", - "\u001b[0mSuccessfully installed ConfigArgParse-1.7 Pyomo-6.5.0 black-24.4.2 classiq-0.41.2 h11-0.14.0 httpcore-1.0.5 httpx-0.27.0 mypy-extensions-1.0.0 networkx-2.8.8 packaging-22.0 pathspec-0.12.1 ply-3.11 pydantic-1.10.15 sympy-1.10.1\n" - ] - } - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "id": "30U0hh4OP7w_" - }, - "outputs": [], - "source": [ - "from classiq import *" - ] - }, - { - "cell_type": "code", - "source": [ - "import classiq\n", - "classiq.authenticate()" - ], - "metadata": { - "id": "4PRC6qblRQiF", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "14bd0a31-f7af-412f-a5a8-9f3ec1499b30" - }, - "execution_count": 3, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Your user code: DDHL-KSZZ\n", - "If a browser doesn't automatically open, please visit this URL from any trusted device: https://auth.classiq.io/activate?user_code=DDHL-KSZZ\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "uzy0m10PP7xK" - }, - "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](https://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": 4, - "metadata": { - "id": "026kr-BdP7xN" - }, - "outputs": [], - "source": [ - "@struct\n", - "class PauliTerm:\n", - " pauli: CArray[Pauli]\n", - " coefficient: CReal" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "lixhso1AP7xU" - }, - "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": 5, - "metadata": { - "id": "y68mlr9iP7xY" - }, - "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": "wXd_0OOGP7xa" - }, - "source": [ - "Fill in the missing parts of the following code in order to complete this exercise:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "id": "jP-lzZwSP7xc", - "outputId": "95cea767-0b3d-429d-e691-a5cbda601fac" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/885d568e-ba77-4d86-98c5-3f44c1b97337?version=0.41.2\n" - ] - } - ], - "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", - " evolution_coefficient=3,\n", - " repetitions=4,\n", - " order=2,\n", - " qbv=q,\n", - " )\n", - "\n", - "\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XqDpPGUzP7xj" - }, - "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](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/quantum-types/#syntax).\n", - "See more on quantum expressions under [Numeric assignment](https://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": 7, - "metadata": { - "id": "ZAXVGyKGP7xm", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "24717872-2e6f-42ba-a248-a0092527101a" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/684db799-e58f-47f0-9b03-0f9b96081220?version=0.41.2\n" - ] - } - ], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "@qfunc\n", - "def main(x: Output[QNum], y: Output[QNum],z:Output[QNum],out1: Output[QNum],out2:Output[QNum],out3:Output[QNum]) -> None:\n", - "\n", - " prepare_int(2,x)\n", - " prepare_int(7,y)\n", - " prepare_int(1,z)\n", - " out1 |= (x + y)\n", - " out2 |= (x * y)\n", - " out3 |= (x * y -z)\n", - "\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "HKRsE0MBP7xq" - }, - "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": 45, - "metadata": { - "id": "bpYRgiU7P7xt", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "d45029ce-54ca-4eb4-a6ba-b34c7768caab" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/e5b998ac-60d9-47a3-97da-1c78281caaaa?version=0.41.2\n" - ] - } - ], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "from classiq import QBit, QArray, CArray, CReal, Output, qfunc\n", - "@qfunc\n", - "def main(res:Output[QNum], x:Output[QNum],y:Output[QNum]) -> None:\n", - "# Declare x to be a 2-qubit variable and y to be 3-qubit variable.\n", - "\n", - " # Prepare x and y\n", - " prepare_state([0.5, 0, 0.5, 0], out=x,bound= 0)\n", - " prepare_state([0, 0.25, 0.25, 0.25, 0, 0, 0.25, 0], out=y, bound=0)\n", - "\n", - " # Compute res = x + y\n", - " res |= x + y\n", - "\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "fZjArRSgP7xw" - }, - "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](https://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": 46, - "metadata": { - "id": "p1-jN9k_P7xy", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "1e5cb568-6d52-441b-ea55-8006fc66e7ed" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/cfb7dd19-a0b9-4ebb-a6a8-418c89dc7c54?version=0.41.2\n" - ] - } - ], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "\n", - "@qfunc\n", - "def add_xy(x:QNum, y:QNum, res: Output[QNum]) ->None:\n", - " res |= x + y\n", - "\n", - "\n", - "@qfunc\n", - "def main(res: Output[QNum]) -> None:\n", - " x = QNum('x')\n", - " y = QNum('y')\n", - " z = QNum('z')\n", - " prepare_int(3, x)\n", - " prepare_int(5, y)\n", - " prepare_int(2, z)\n", - "\n", - " temp = QNum('temp')\n", - " within_apply(compute= lambda: add_xy(x, y, temp),\n", - " action= lambda: add_xy(temp, z, res))\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "QlAfKwmFP7x0" - }, - "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](https://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": 47, - "metadata": { - "id": "xVdg75QGP7x4", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "cfb22e39-7a61-4593-f60b-29ff7c011039" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/5902070b-c714-426f-94e3-de96bd709fe4?version=0.41.2\n" - ] - } - ], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "qfunc\n", - "def add_ab(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", - " temp1 = QNum('temp1')\n", - " temp2 = QNum('temp2')\n", - " within_apply(compute = lambda: add_ab(temp1, x, y),\n", - " action = lambda: add_ab(temp2, temp1, z),)\n", - " res |= temp2 + 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" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "K1-qAHJwP7x6" - }, - "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": 48, - "metadata": { - "id": "ugVsWlxdP7x8", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "b161cc81-7016-4e34-8bfd-41cd5b4c6374" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/21573046-4b58-445e-b098-c01f61d6ad7f?version=0.41.2\n" - ] - } - ], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\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" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_7sJv6NUP7x_" - }, - "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](https://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": 49, - "metadata": { - "id": "kosXeVgkP7yC", - "outputId": "cbffe019-d397-42b4-b0df-45898902c57b", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - } - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/3e37cec3-38bf-44ff-839d-78ca1492254d?version=0.41.2\n" - ] - } - ], - "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": "N7uymloXP7yG" - }, - "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": 50, - "metadata": { - "id": "O4GYaZhhP7yI", - "outputId": "b573b2a3-5337-475e-f720-e5ec59e8a6db", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - } - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/85c0ddf4-b334-4146-9e62-22d4700020a9?version=0.41.2\n" - ] - } - ], - "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)) # 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": "Q8Xs_UXuP7yK" - }, - "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": 51, - "metadata": { - "id": "LfhqxNYCP7yN", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "c4c34c5f-4c97-4222-a7d1-35d537c09edb" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/895a5345-9c5a-4282-b996-fc60e830e614?version=0.41.2\n" - ] - } - ], - "source": [ - "from classiq import *\n", - "from classiq.qmod.symbolic import sqrt\n", - "\n", - "prob_list= [\n", - " 1 / 8,\n", - " 1 / 8,\n", - " 1 / 8,\n", - " -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", - "\n", - "# Your code here:\n", - "\n", - "@qfunc\n", - "def main(res: Output[QArray[QBit]]) -> None:\n", - " '''\n", - " x: QArray[QBit] = QArray(\"x\")\n", - "\n", - " allocate(3, x)\n", - " hadamard_transform(x)\n", - "\n", - " lsb = QBit(\"lsb\")\n", - " msb = QNum(\"msb\", 2, False, 0)\n", - "\n", - " bind(x, [lsb, msb])\n", - "\n", - " control(msb == 0, lambda: RY(pi / 3, lsb))\n", - " # msb==1 <==> bit1 bit2 == 01 (binary of decimal 1)\n", - "\n", - " bind([lsb, msb], res)\n", - " '''\n", - " pre_prepared_state(res)\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.8" - }, - "colab": { - "provenance": [] - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file From 434353e74f6c031b881e24c737d934387afaa573 Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Sat, 15 Jun 2024 04:52:39 +0200 Subject: [PATCH 16/18] Add files via upload --- .../HW2/Hisham_Mansour_HW2_QClass2024.ipynb | 737 ++++++++++++++++++ 1 file changed, 737 insertions(+) create mode 100644 community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb diff --git a/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb b/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb new file mode 100644 index 00000000..506c0ac4 --- /dev/null +++ b/community/QClass_2024/Submissions/HW2/Hisham_Mansour_HW2_QClass2024.ipynb @@ -0,0 +1,737 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "RyYX0oEHP7ww" + }, + "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": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "-xGG1F4dQFYM", + "outputId": "0d119fb0-5ddb-4067-ec41-ff1ead7d6e91" + }, + "outputs": [], + "source": [ + "!pip install -U classiq" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "4PRC6qblRQiF", + "outputId": "14bd0a31-f7af-412f-a5a8-9f3ec1499b30" + }, + "outputs": [], + "source": [ + "import classiq\n", + "classiq.authenticate()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "30U0hh4OP7w_", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "uzy0m10PP7xK" + }, + "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.\n", + "\n", + "The builtin struct type `PauliTerm` is defined as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "026kr-BdP7xN", + "tags": [] + }, + "outputs": [], + "source": [ + "@struct\n", + "class PauliTerm:\n", + " pauli: CArray[Pauli]\n", + " coefficient: CReal" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lixhso1AP7xU" + }, + "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": "y68mlr9iP7xY", + "tags": [] + }, + "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": "wXd_0OOGP7xa" + }, + "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/", + "height": 0 + }, + "id": "jP-lzZwSP7xc", + "outputId": "95cea767-0b3d-429d-e691-a5cbda601fac", + "tags": [] + }, + "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", + " evolution_coefficient=3,\n", + " repetitions=4,\n", + " order=2,\n", + " qbv=q,\n", + " )\n", + "\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XqDpPGUzP7xj", + "tags": [] + }, + "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.\n", + "See more on quantum expressions under 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/", + "height": 0 + }, + "id": "ZAXVGyKGP7xm", + "outputId": "24717872-2e6f-42ba-a248-a0092527101a", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "@qfunc\n", + "def main(x: Output[QNum], y: Output[QNum],z:Output[QNum],out1: Output[QNum],out2:Output[QNum],out3:Output[QNum]) -> None:\n", + "\n", + " prepare_int(2,x)\n", + " prepare_int(7,y)\n", + " prepare_int(1,z)\n", + " out1 |= (x + y)\n", + " out2 |= (x * y)\n", + " out3 |= (x * y -z)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "HKRsE0MBP7xq" + }, + "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/", + "height": 0 + }, + "id": "bpYRgiU7P7xt", + "outputId": "d45029ce-54ca-4eb4-a6ba-b34c7768caab", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "from classiq import QBit, QArray, CArray, CReal, Output, qfunc\n", + "@qfunc\n", + "def main(res:Output[QNum], x:Output[QNum],y:Output[QNum]) -> None:\n", + "# Declare x to be a 2-qubit variable and y to be 3-qubit variable.\n", + "\n", + " # Prepare x and y\n", + " prepare_state([0.5, 0, 0.5, 0], out=x,bound= 0)\n", + " prepare_state([0, 0.25, 0.25, 0.25, 0, 0, 0.25, 0], out=y, bound=0)\n", + "\n", + " # Compute res = x + y\n", + " res |= x + y\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "fZjArRSgP7xw", + "tags": [] + }, + "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.\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/", + "height": 0 + }, + "id": "p1-jN9k_P7xy", + "outputId": "1e5cb568-6d52-441b-ea55-8006fc66e7ed", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "\n", + "\n", + "@qfunc\n", + "def add_xy(x:QNum, y:QNum, res: Output[QNum]) ->None:\n", + " res |= x + y\n", + "\n", + "\n", + "@qfunc\n", + "def main(res: Output[QNum],x:Output[QNum],y:Output[QNum],z:Output[QNum]) -> None:\n", + " #x = QNum('x')\n", + " #y = QNum('y')\n", + " #z = QNum('z')\n", + " prepare_int(3, x)\n", + " prepare_int(5, y)\n", + " prepare_int(2, z)\n", + "\n", + " temp = QNum('temp')\n", + " within_apply(compute= lambda: add_xy(x, y, temp),\n", + " action= lambda: add_xy(temp, z, res))\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "show(qprog)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "QlAfKwmFP7x0", + "tags": [] + }, + "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.\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/", + "height": 0 + }, + "id": "xVdg75QGP7x4", + "outputId": "cfb22e39-7a61-4593-f60b-29ff7c011039", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "qfunc\n", + "def add_ab(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", + " temp1 = QNum('temp1')\n", + " temp2 = QNum('temp2')\n", + " within_apply(compute = lambda: add_ab(temp1, x, y),\n", + " action = lambda: add_ab(temp2, temp1, z),)\n", + " res |= temp2 + 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" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "K1-qAHJwP7x6" + }, + "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/", + "height": 0 + }, + "id": "ugVsWlxdP7x8", + "outputId": "b161cc81-7016-4e34-8bfd-41cd5b4c6374", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\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" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "_7sJv6NUP7x_" + }, + "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.\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/", + "height": 0 + }, + "id": "kosXeVgkP7yC", + "outputId": "cbffe019-d397-42b4-b0df-45898902c57b", + "tags": [] + }, + "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": "N7uymloXP7yG" + }, + "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": "O4GYaZhhP7yI", + "outputId": "b573b2a3-5337-475e-f720-e5ec59e8a6db", + "tags": [] + }, + "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)) # 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": "Q8Xs_UXuP7yK" + }, + "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": "LfhqxNYCP7yN", + "outputId": "c4c34c5f-4c97-4222-a7d1-35d537c09edb", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "from classiq.qmod.symbolic import sqrt\n", + "\n", + "prob_list= [\n", + " 1 / 8,\n", + " 1 / 8,\n", + " 1 / 8,\n", + " -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", + "\n", + "# Your code here:\n", + "\n", + "@qfunc\n", + "def main(res: Output[QArray[QBit]]) -> None:\n", + " '''\n", + " x: QArray[QBit] = QArray(\"x\")\n", + "\n", + " allocate(3, x)\n", + " hadamard_transform(x)\n", + "\n", + " lsb = QBit(\"lsb\")\n", + " msb = QNum(\"msb\", 2, False, 0)\n", + "\n", + " bind(x, [lsb, msb])\n", + "\n", + " control(msb == 0, lambda: RY(pi / 3, lsb))\n", + " # msb==1 <==> bit1 bit2 == 01 (binary of decimal 1)\n", + "\n", + " bind([lsb, msb], res)\n", + " '''\n", + " pre_prepared_state(res)\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 +} From e5f04dce9bd611b264fe7333df1a19c69b150e33 Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Sat, 15 Jun 2024 04:54:46 +0200 Subject: [PATCH 17/18] Delete community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb --- .../HW1/Hisham_Mansour_HW1_QClass2024.ipynb | 805 ------------------ 1 file changed, 805 deletions(-) delete mode 100644 community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb diff --git a/community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb b/community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb deleted file mode 100644 index 55323c62..00000000 --- a/community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb +++ /dev/null @@ -1,805 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "XtC66r2Y5_eT" - }, - "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](https://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](https://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](https://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", - "source": [ - "!pip install -U classiq" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "collapsed": true, - "id": "156317w1BFqw", - "outputId": "3dda7746-c565-421d-ec6f-f18a4e7d0047" - }, - "execution_count": 1, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Collecting classiq\n", - " Downloading classiq-0.41.1-py3-none-any.whl (398 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m398.1/398.1 kB\u001b[0m \u001b[31m4.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hCollecting ConfigArgParse<2.0.0,>=1.5.3 (from classiq)\n", - " Downloading ConfigArgParse-1.7-py3-none-any.whl (25 kB)\n", - "Collecting Pyomo<6.6,>=6.5 (from classiq)\n", - " Downloading Pyomo-6.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (10.7 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m10.7/10.7 MB\u001b[0m \u001b[31m19.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hCollecting black<25.0,>=24.0 (from classiq)\n", - " Downloading black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.8/1.8 MB\u001b[0m \u001b[31m29.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hCollecting httpx<1,>=0.23.0 (from classiq)\n", - " Downloading httpx-0.27.0-py3-none-any.whl (75 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.6/75.6 kB\u001b[0m \u001b[31m6.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: keyring<24.0.0,>=23.5.0 in /usr/lib/python3/dist-packages (from classiq) (23.5.0)\n", - "Requirement already satisfied: matplotlib<4.0.0,>=3.4.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (3.7.1)\n", - "Collecting networkx<3.0.0,>=2.5.1 (from classiq)\n", - " Downloading networkx-2.8.8-py3-none-any.whl (2.0 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m31.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: numexpr<3.0.0,>=2.7.3 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.10.0)\n", - "Requirement already satisfied: numpy<2.0.0,>=1.20.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.25.2)\n", - "Collecting packaging<23.0,>=22.0 (from classiq)\n", - " Downloading packaging-22.0-py3-none-any.whl (42 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m42.6/42.6 kB\u001b[0m \u001b[31m2.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: pandas<3.0.0,>=1.4.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (2.0.3)\n", - "Requirement already satisfied: plotly<6.0.0,>=5.7.0 in /usr/local/lib/python3.10/dist-packages (from classiq) (5.15.0)\n", - "Collecting pydantic<2.0.0,>=1.9.1 (from classiq)\n", - " Downloading pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.1/3.1 MB\u001b[0m \u001b[31m34.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: scipy<2.0.0,>=1.10.1 in /usr/local/lib/python3.10/dist-packages (from classiq) (1.11.4)\n", - "Collecting sympy<1.11.0,>=1.9.0 (from classiq)\n", - " Downloading sympy-1.10.1-py3-none-any.whl (6.4 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.4/6.4 MB\u001b[0m \u001b[31m55.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: tabulate<1,>=0.8.9 in /usr/local/lib/python3.10/dist-packages (from classiq) (0.9.0)\n", - "Requirement already satisfied: click>=8.0.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (8.1.7)\n", - "Collecting mypy-extensions>=0.4.3 (from black<25.0,>=24.0->classiq)\n", - " Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n", - "Collecting pathspec>=0.9.0 (from black<25.0,>=24.0->classiq)\n", - " Downloading pathspec-0.12.1-py3-none-any.whl (31 kB)\n", - "Requirement already satisfied: platformdirs>=2 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.2.2)\n", - "Requirement already satisfied: tomli>=1.1.0 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (2.0.1)\n", - "Requirement already satisfied: typing-extensions>=4.0.1 in /usr/local/lib/python3.10/dist-packages (from black<25.0,>=24.0->classiq) (4.11.0)\n", - "Requirement already satisfied: anyio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7.1)\n", - "Requirement already satisfied: certifi in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (2024.2.2)\n", - "Collecting httpcore==1.* (from httpx<1,>=0.23.0->classiq)\n", - " Downloading httpcore-1.0.5-py3-none-any.whl (77 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.9/77.9 kB\u001b[0m \u001b[31m3.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: idna in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (3.7)\n", - "Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from httpx<1,>=0.23.0->classiq) (1.3.1)\n", - "Collecting h11<0.15,>=0.13 (from httpcore==1.*->httpx<1,>=0.23.0->classiq)\n", - " Downloading h11-0.14.0-py3-none-any.whl (58 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m6.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.2.1)\n", - "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (0.12.1)\n", - "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (4.51.0)\n", - "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (1.4.5)\n", - "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (9.4.0)\n", - "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (3.1.2)\n", - "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib<4.0.0,>=3.4.3->classiq) (2.8.2)\n", - "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2023.4)\n", - "Requirement already satisfied: tzdata>=2022.1 in /usr/local/lib/python3.10/dist-packages (from pandas<3.0.0,>=1.4.0->classiq) (2024.1)\n", - "Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from plotly<6.0.0,>=5.7.0->classiq) (8.3.0)\n", - "Collecting ply (from Pyomo<6.6,>=6.5->classiq)\n", - " Downloading ply-3.11-py2.py3-none-any.whl (49 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.6/49.6 kB\u001b[0m \u001b[31m4.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy<1.11.0,>=1.9.0->classiq) (1.3.0)\n", - "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.7->matplotlib<4.0.0,>=3.4.3->classiq) (1.16.0)\n", - "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio->httpx<1,>=0.23.0->classiq) (1.2.1)\n", - "Installing collected packages: ply, sympy, Pyomo, pydantic, pathspec, packaging, networkx, mypy-extensions, h11, ConfigArgParse, httpcore, black, httpx, classiq\n", - " Attempting uninstall: sympy\n", - " Found existing installation: sympy 1.12\n", - " Uninstalling sympy-1.12:\n", - " Successfully uninstalled sympy-1.12\n", - " Attempting uninstall: pydantic\n", - " Found existing installation: pydantic 2.7.1\n", - " Uninstalling pydantic-2.7.1:\n", - " Successfully uninstalled pydantic-2.7.1\n", - " Attempting uninstall: packaging\n", - " Found existing installation: packaging 24.0\n", - " Uninstalling packaging-24.0:\n", - " Successfully uninstalled packaging-24.0\n", - " Attempting uninstall: networkx\n", - " Found existing installation: networkx 3.3\n", - " Uninstalling networkx-3.3:\n", - " Successfully uninstalled networkx-3.3\n", - "\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", - "torch 2.3.0+cu121 requires nvidia-cublas-cu12==12.1.3.1; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cuda-cupti-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cuda-nvrtc-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cuda-runtime-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cudnn-cu12==8.9.2.26; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cufft-cu12==11.0.2.54; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-curand-cu12==10.3.2.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cusolver-cu12==11.4.5.107; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-cusparse-cu12==12.1.0.106; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-nccl-cu12==2.20.5; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\n", - "torch 2.3.0+cu121 requires nvidia-nvtx-cu12==12.1.105; platform_system == \"Linux\" and platform_machine == \"x86_64\", which is not installed.\u001b[0m\u001b[31m\n", - "\u001b[0mSuccessfully installed ConfigArgParse-1.7 Pyomo-6.5.0 black-24.4.2 classiq-0.41.1 h11-0.14.0 httpcore-1.0.5 httpx-0.27.0 mypy-extensions-1.0.0 networkx-2.8.8 packaging-22.0 pathspec-0.12.1 ply-3.11 pydantic-1.10.15 sympy-1.10.1\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "import classiq\n", - "classiq.authenticate()" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "id": "EaDN5EkVC58C", - "outputId": "46134709-44e6-4049-f543-92e6f6641454" - }, - "execution_count": 2, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Your user code: PMKD-TJLQ\n", - "If a browser doesn't automatically open, please visit this URL from any trusted device: https://auth.classiq.io/activate?user_code=PMKD-TJLQ\n" - ] - } - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "id": "DpF2vKUh5_e7" - }, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "\n", - "# Define a quantum function using the @qfunc decorator\n", - "@qfunc\n", - "def foo(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", - " foo(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": 4, - "metadata": { - "id": "UB612BIP5_fE", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "8a173bc3-d74f-44a6-9d0e-403601e3a6bb" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/e76daf18-d5ae-43e2-85bc-44087b930754?version=0.41.1\n" - ] - } - ], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "execute(qprog)\n", - "show(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](https://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](https://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](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/functions#syntax)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "id": "fNOTP83I5_fJ", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "6cb4b516-dc5c-4800-dc96-bcd778c7691f" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/765b971e-b440-4a96-87bb-74df82556089?version=0.41.1\n" - ] - }, - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "ExecutionJob(id='5b958421-8492-4402-9ebb-888191d857f0')" - ] - }, - "metadata": {}, - "execution_count": 7 - } - ], - "source": [ - "from classiq import *\n", - "\n", - "# Define a quantum function using the @qfunc decorator\n", - "@qfunc\n", - "def bell_pair(q_1: QBit, q_2: QBit) -> None:\n", - " H(target=q_1)\n", - " CX(control=q_1,target=q_2)\n", - "\n", - "# Define a main function\n", - "@qfunc\n", - "def main(out_1: Output[QBit], out_2: Output[QBit]) -> None:\n", - " allocate(1, out_1)\n", - " allocate(1, out_2)\n", - " bell_pair(q_1=out_1,q_2=out_2)\n", - "# Your code here:\n", - "\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": 9, - "metadata": { - "id": "Y-c9r6OT5_fO", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "3ab1dc27-a011-4fbe-f435-6e1315fe2ded" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/f7e18847-8cd6-4273-af93-1777965f19ef?version=0.41.1\n" - ] - } - ], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "# Define a quantum function using the @qfunc decorator\n", - "@qfunc\n", - "def bell_pair(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(out: Output[QArray]) -> None:\n", - " allocate(2, out)\n", - " bell_pair(out)\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "execute(qprog)\n", - "show(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](https://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": 11, - "metadata": { - "id": "vFrcPTqi5_fS", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "ebc0c3c4-671a-4c21-feb2-10dbdeaa4df3" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/7c5128dc-3e49-42da-ad3d-ddc9d7414221?version=0.41.1\n" - ] - } - ], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "@qfunc\n", - "def h_transform(q: QArray) -> None:\n", - " repeat(count=q.len, iteration=lambda i: H(target=q[i]))\n", - " #repeat(q.len, lambda i: H(q[i]))\n", - "\n", - "# Define a main function\n", - "@qfunc\n", - "def main(out: Output[QArray]) -> None:\n", - " allocate(10, out)\n", - " h_transform(out)\n", - "\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "execute(qprog)\n", - "show(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](https://en.wikipedia.org/wiki/Closure_(computer_programming)) in classical languages.\n", - "\n", - "See also [Capturing context variables and parameters](https://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](https://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": 12, - "metadata": { - "id": "tD_aBHoU5_fW" - }, - "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" - }, - "outputs": [], - "source": [ - "def unitary(\n", - " elements: CArray[CArray[CReal]],\n", - " target: QArray[QBit],\n", - ") -> None:\n", - " pass" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "id": "6Js8fNbl5_fa", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "e806c96c-489b-41ab-f46f-ea435840ee79" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/350d1e48-e4ce-4745-a207-d1b8535c4690?version=0.41.1\n" - ] - } - ], - "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", - "execute(qprog)\n", - "show(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](https://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": 16, - "metadata": { - "id": "vvMbP91D5_fc", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "d92aadd8-4a5b-41a7-f565-5d0660569da6" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/520223e2-7846-41d9-ba66-1dcb838cf17b?version=0.41.1\n" - ] - } - ], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "'''\n", - "@qfunc\n", - "def h_transform(q: QArray) -> None:\n", - " #repeat(count=res.len, iteration=lambda i: H(target=res[i]))\n", - " apply_to_all(H, q)\n", - "# Define a main function\n", - "@qfunc\n", - "def main(out: Output[QArray]) -> None:\n", - " allocate(10, out)\n", - " h_transform(out)\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", - "\n", - "@qfunc\n", - "def h_transform(q: QArray[QBit]) -> None:\n", - " my_apply_to_all(lambda t: H(t), q)\n", - "\n", - "\n", - "@qfunc\n", - "def main(q: Output[QArray[QBit]]) -> None:\n", - " allocate(10, q)\n", - " h_transform(q)\n", - "\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "execute(qprog)\n", - "show(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](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/quantum-operators/#syntax).\n" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "id": "00trO6SJ5_ff", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "02ef558f-f0ae-47b9-c949-c8e855f537ff" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/45b7fcda-53bb-4980-82d5-0421f1000d4c?version=0.41.1\n" - ] - } - ], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "from classiq.qmod.symbolic import pi\n", - "\n", - "\n", - "@qfunc\n", - "def my_ctry(control_bit: QBit, target_bit: QBit) -> None:\n", - " control(control_bit, lambda: RY(pi / 2, target_bit))\n", - "\n", - "\n", - "@qfunc\n", - "def main(control_bit: Output[QBit], target_bit: Output[QBit]) -> None:\n", - " allocate(1, control_bit)\n", - " allocate(1, target_bit)\n", - " my_ctry(control_bit, target_bit)\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "execute(qprog)\n", - "show(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](https://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](https://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": 19, - "metadata": { - "id": "IohNdRCA5_fi", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 0 - }, - "outputId": "d64d356d-f4dd-4882-9291-1eab312604a7" - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Opening: https://platform.classiq.io/circuit/c34fb3f7-8aa9-4f9d-bda7-84416f49c600?version=0.41.1\n" - ] - } - ], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "@qfunc\n", - "def main(x: Output[QNum], target: Output[QBit]) -> None:\n", - " prepare_int(7, x)\n", - " allocate(1, target)\n", - " control(x == 7, lambda: X(target))\n", - "\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.8" - }, - "colab": { - "provenance": [] - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file From d77af92708ffda39c1857aacfee8ff05176d5835 Mon Sep 17 00:00:00 2001 From: mnshmnsh <145525018+mnshmnsh@users.noreply.github.com> Date: Sat, 15 Jun 2024 04:55:24 +0200 Subject: [PATCH 18/18] Add files via upload --- .../HW1/Hisham_Mansour_HW1_QClass2024.ipynb | 630 ++++++++++++++++++ 1 file changed, 630 insertions(+) create mode 100644 community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb diff --git a/community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb b/community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb new file mode 100644 index 00000000..3689eba1 --- /dev/null +++ b/community/QClass_2024/Submissions/HW1/Hisham_Mansour_HW1_QClass2024.ipynb @@ -0,0 +1,630 @@ +{ + "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 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.\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. 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": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "156317w1BFqw", + "outputId": "3dda7746-c565-421d-ec6f-f18a4e7d0047", + "tags": [] + }, + "outputs": [], + "source": [ + "%pip install -U classiq" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "EaDN5EkVC58C", + "outputId": "46134709-44e6-4049-f543-92e6f6641454", + "tags": [] + }, + "outputs": [], + "source": [ + "import classiq\n", + "classiq.authenticate()" + ] + }, + { + "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 foo(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", + " foo(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": "8a173bc3-d74f-44a6-9d0e-403601e3a6bb", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "execute(qprog)\n", + "show(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.\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 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\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "fNOTP83I5_fJ", + "outputId": "6cb4b516-dc5c-4800-dc96-bcd778c7691f", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Define a quantum function using the @qfunc decorator\n", + "@qfunc\n", + "def bell_pair(q_1: QBit, q_2: QBit) -> None:\n", + " H(target=q_1)\n", + " CX(control=q_1,target=q_2)\n", + "\n", + "# Define a main function\n", + "@qfunc\n", + "def main(out_1: Output[QBit], out_2: Output[QBit]) -> None:\n", + " allocate(1, out_1)\n", + " allocate(1, out_2)\n", + " bell_pair(q_1=out_1,q_2=out_2)\n", + "# Your code here:\n", + "\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": "3ab1dc27-a011-4fbe-f435-6e1315fe2ded", + "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_pair(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(out: Output[QArray]) -> None:\n", + " allocate(2, out)\n", + " bell_pair(out)\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "execute(qprog)\n", + "show(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.\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": "ebc0c3c4-671a-4c21-feb2-10dbdeaa4df3", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "@qfunc\n", + "def h_transform(q: QArray) -> None:\n", + " repeat(count=q.len, iteration=lambda i: H(target=q[i]))\n", + " #repeat(q.len, lambda i: H(q[i]))\n", + "\n", + "# Define a main function\n", + "@qfunc\n", + "def main(out: Output[QArray]) -> None:\n", + " allocate(10, out)\n", + " h_transform(out)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "execute(qprog)\n", + "show(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.\n", + "\n", + "See also 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.\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": "e806c96c-489b-41ab-f46f-ea435840ee79", + "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", + "execute(qprog)\n", + "show(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.\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": "d92aadd8-4a5b-41a7-f565-5d0660569da6", + "tags": [] + }, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "'''\n", + "@qfunc\n", + "def h_transform(q: QArray) -> None:\n", + " #repeat(count=res.len, iteration=lambda i: H(target=res[i]))\n", + " apply_to_all(H, q)\n", + "# Define a main function\n", + "@qfunc\n", + "def main(out: Output[QArray]) -> None:\n", + " allocate(10, out)\n", + " h_transform(out)\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", + "\n", + "@qfunc\n", + "def h_transform(q: QArray[QBit]) -> None:\n", + " my_apply_to_all(lambda t: H(t), q)\n", + "\n", + "\n", + "@qfunc\n", + "def main(q: Output[QArray[QBit]]) -> None:\n", + " allocate(10, q)\n", + " h_transform(q)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "execute(qprog)\n", + "show(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.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "00trO6SJ5_ff", + "outputId": "02ef558f-f0ae-47b9-c949-c8e855f537ff", + "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_ctry(control_bit: QBit, target_bit: QBit) -> None:\n", + " control(control_bit, lambda: RY(pi / 2, target_bit))\n", + "\n", + "\n", + "@qfunc\n", + "def main(control_bit: Output[QBit], target_bit: Output[QBit]) -> None:\n", + " allocate(1, control_bit)\n", + " allocate(1, target_bit)\n", + " my_ctry(control_bit, target_bit)\n", + "\n", + "qmod = create_model(main)\n", + "qprog = synthesize(qmod)\n", + "execute(qprog)\n", + "show(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.\n", + "\n", + "In QMOD this generalization is available as a native statement - control.\n", + "\n", + "See also control.\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/", + "height": 0 + }, + "id": "IohNdRCA5_fi", + "outputId": "d64d356d-f4dd-4882-9291-1eab312604a7", + "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(7, x)\n", + " allocate(1, target)\n", + " control(x == 7, 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 +}