diff --git a/tutorials/Classiq_tutorial/Qmod_tutorial_part1.ipynb b/tutorials/Classiq_tutorial/Qmod_tutorial_part1.ipynb index c58fff28..789dbdad 100644 --- a/tutorials/Classiq_tutorial/Qmod_tutorial_part1.ipynb +++ b/tutorials/Classiq_tutorial/Qmod_tutorial_part1.ipynb @@ -11,8 +11,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In this tutorial, we will learn the basics of modeling quantum algorithms using the Qmod language and its accompanied function library.\\\n", - "We will learn to use functions, operators, quantum variables, and quantum types. \n", + "In this tutorial, we will learn the basics of the Qmod language and its accompanied function library.\\\n", + "We will learn to use quantum variables, functions and operators.\n", "\n", "Let's begin with a simple code example:" ] @@ -97,7 +97,8 @@ "4. The `Output` modifier:\\\n", " The `Output` modifier indicates that a quantum variable is not initialized outside the scope of the function, and hence must be initialized inside the scope of the function.\\\n", " For example, in the above `main` function definition, `q` is declared with the `Output` modifier, so `main` expects it to not yet be initialized when called. `foo`, on the other hand, declares its input `q` without the modifier, hence it is essential to initialize `q` before passing it to `foo` (see the call to `allocate` in the code).\n", - " - Since `main` is the quantum entry point, all of its inputs must be declared with the `Output` modifier. Please take a moment to think about it: suppose that we would decalre an input `x` to `main` without the `Output` modifier. It follows that `x` must have been initialized before calling `main`, and was passed to main already initialized, but it would be impossible because `main` is the origin of any quantum logic - all its external interfaces are classical." + " - Since `main` is the quantum entry point, all of its inputs must be declared with the `Output` modifier. Please take a moment to think about it: suppose that we would decalre an input `x` to `main` without the `Output` modifier. It follows that `x` must have been initialized before calling `main`, and was passed to main already initialized, but it would be impossible because `main` is the origin of any quantum logic - all its external interfaces are classical.\n", + " - Other functions can declare their inputs with or without the `Output` modifier depending on wether or not they expect them to be initialized when called." ] }, { @@ -105,14 +106,183 @@ "metadata": {}, "source": [ "### Exercise #0\n", - "Rewrite the above model, so that `q` is initilized inside `foo`.\n", - "Hint: " + "Rewrite the above model, so that `q` is initilized inside `foo`.\\\n", + "Solution is provided in the end of the notebook.\\\n", + "Hint: it only requires to move one line of code and add the `Output` modifier in the correct place." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'q': 1}: 1066, {'q': 0}: 982]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here\n", + "...\n", + "\n", + "# execute the model to see that we get similar results\n", + "qmod = create_model(main)\n", + "job = execute(synthesize(qmod))\n", + "job.get_sample_result().parsed_counts" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Quantum Arrays\n", + "After we have familiarized with the `QBit` varible type (which is simply a single qubit), it is a good timing to introduce the quantum array type `QArray`. Let's do it through an exercise. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise #1 - Preparing a Bell Pair" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this exercise, we will prepare the famous $|+\\rangle$ [Bell state](https://en.wikipedia.org/wiki/Bell_state) into a 2-qubit [Quantum array](https://docs.classiq.io/latest/qmod-reference/language-reference/quantum-types/#quantum-arrays).\\\n", + "Recall that $|+\\rangle$ represents the state $\\frac{1}{\\sqrt{2}} (|00\\rangle + |11\\rangle)$.\\\n", + "Instructions:\n", + "1. Declare a quantum variable `qarr` of type `QArray`, and initilize it by allocating to it 2 qubits. Don't forget to use the `Output` modifier.\n", + "2. Apply a Hadamard gate on the first qubit of `qarr`. Qmod counts from 0, so the first entry of `qarr` is `qarr[0]`.\n", + "3. Apply `CX` (controlled-NOT gate), with the `control` parameter being `qarr[0]` and the `target` parameter being `qarr[1]`.\n", + "\n", + "Synthesize and execute your model to assure that $|00\\rangle$ and $|11\\rangle$ are the only states to be measured, and that they are measured roughly equally.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import *\n", + "\n", + "# Your code here:\n", + "...\n", + "\n", + "# execute and inspect the results\n", + "qmod = create_model(main)\n", + "job = execute(synthesize(qmod))\n", + "job.get_sample_result().parsed_counts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Solutions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Solution - Excercise #0" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'q': 0}: 1039, {'q': 1}: 1009]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import *\n", + "\n", + "# rewrite the model, initializing q inside foo\n", + "@qfunc\n", + "def foo(q: Output[QBit]) -> None:\n", + " allocate(1,q)\n", + " X(q)\n", + " H(q)\n", + "\n", + "@qfunc\n", + "def main(q: Output[QBit]) -> None:\n", + " foo(q)\n", + "\n", + "# execute the model to see that we get similar results\n", + "qmod = create_model(main)\n", + "job = execute(synthesize(qmod))\n", + "job.get_sample_result().parsed_counts" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Solution - Exercise #1" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'qarr': [1, 1]}: 1045, {'qarr': [0, 0]}: 1003]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import *\n", + "\n", + "\n", + "@qfunc\n", + "def bell(qarr: QArray[QBit, 2]) -> None:\n", + " H(qarr[0])\n", + " CX(qarr[0], qarr[1])\n", + "\n", + "\n", + "@qfunc\n", + "def main(qarr: Output[QArray]) -> None:\n", + " allocate(2, qarr)\n", + " bell(qarr)\n", + "\n", + "# execute and inspect the results\n", + "qmod = create_model(main)\n", + "job = execute(synthesize(qmod))\n", + "job.get_sample_result().parsed_counts" + ] } ], "metadata": {