diff --git a/samples/azure-quantum/check-ghz/CheckGHZ-qci-qsharp.ipynb b/samples/azure-quantum/check-ghz/CheckGHZ-qci-qsharp.ipynb new file mode 100644 index 000000000000..75c86da84f97 --- /dev/null +++ b/samples/azure-quantum/check-ghz/CheckGHZ-qci-qsharp.ipynb @@ -0,0 +1,220 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Getting started with Integrated Hybrid Computing\n", + "In this sample, you will discover how to blend classical and quantum instructions in the same program, all fully processed by the quantum computing backend.\n", + "You can learn more about integrated hybrid computing at https://aka.ms/AQ/Hybrid/Docs\n", + "\n", + "## Connect to the Azure Quantum workspace\n", + "First, find the resource ID of your Azure Quantum workspace. You can copy/paste this from the top-right corner of your Quantum Workspace page in the Azure Portal.\n", + "\n", + "Next, you can run `%azure.connect` to connect to the workspace and display the list of provisioned targets that support execution of Q# programs. If you are prompted to login, be sure to use the same account you used to create your Azure Quantum workspace." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "%azure.connect \"/subscriptions/subscriptionId/resourceGroups/resourceGroupName/providers/Microsoft.Quantum/Workspaces/workspaceName\" location=\"westus\"" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Select a target and opt-in to use integrated hybrid computing\n", + "First, we select the target the program is intended to be run on using the `%azure.target` command. This information is used by Q# compiler to check the program can be run on the specified target taking into consideration its capabilities.\n", + "\n", + "Since integrated hybrid computing is an opt-in feature, we run the `%azure.target-capability` command to opt into it.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%azure.target qci.simulator\n", + "%azure.target-capability AdaptiveExecution" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Define the CheckGHZ operation\n", + "\n", + "This program prepares a Greenberger–Horne–Zeilinger (GHZ) state and counts the number of times qubit measurements are not perfectly correlated out of 10 attempts. Unlike in noiseless simulations, non-perfect correlations can occur when programs run on real quantum devices which are subject to the effects of noise.\n", + "\n", + "In the CheckGHZ() operation, we can see two capabilities of integrated hybrid computing being demonstrated:\n", + "1. **Branching** based on qubit measurements, which allows programs to execute different quantum operations or classical instructions depending on the results yielded by qubit measurements.\n", + "```Q#\n", + " if not (r0 == r1 and r1 == r2)\n", + "```\n", + "2. **Classical compute** performed in real time by the quantum machine itself.\n", + "```Q#\n", + " set mismatch += 1;\n", + "```\n", + "### ❕ Please note that you will see a warning displayed (QS5028)\n", + "It can be ignored for the purposes of this sample. It will be addressed in a subsequent release of the Quantum Development Kit." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "microsoft": {}, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "open Microsoft.Quantum.Intrinsic;\n", + "open Microsoft.Quantum.Measurement;\n", + "\n", + "operation CheckGHZ() : Int {\n", + " use q = Qubit[3];\n", + " mutable mismatch = 0;\n", + " for _ in 1..10 {\n", + " // Prepare the GHZ state.\n", + " H(q[0]);\n", + " CNOT(q[0], q[1]);\n", + " CNOT(q[1], q[2]);\n", + "\n", + " // Measures and resets the 3 qubits\n", + " let (r0, r1, r2) = (MResetZ(q[0]), MResetZ(q[1]), MResetZ(q[2]));\n", + "\n", + " // Adjusts classical value based on qubit measurement results\n", + " if not (r0 == r1 and r1 == r2) {\n", + " set mismatch += 1;\n", + " }\n", + " }\n", + " return mismatch;\n", + "}" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Submit the program\n", + "If the job has not been completed after the client times out (300 seconds), you can query the status using `%azure.status` followed by querying the output using `%azure.output`.
\n", + "\n", + "If the kernel was restarted after the program had been submitted, you will have to use `%azure.status ` to get the status of the job and `%azure.output ` to retrieve the results.
\n", + "You can also check the status of the job under the **Job management** section on the left side menu of the portal.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%azure.execute CheckGHZ shots=50 timeout=300 poll=10" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%azure.status" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Understanding the results\n", + "Each item in the histogram represents the correlation mismatch count and the corresponding frequency the mismatch count was observed out of the number of shots that were run.
\n", + "The histogram values can range from 0 (no correlation mismatch occurred) to 10 (all correlations checks were a mismatch)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%azure.output" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## ↗ Learning more about Integrated Hybrid Computing\n", + "Now that you have run this sample, you can further learn and experiment with other samples available in the gallery.\n", + "\n", + "To learn more, please refer to our [online documentation](https://aka.ms/AQ/Hybrid/Docs)." + ] + } + ], + "metadata": { + "kernel_info": { + "name": "iqsharp" + }, + "kernelspec": { + "display_name": "Q#", + "language": "qsharp", + "name": "iqsharp" + }, + "language_info": { + "file_extension": ".qs", + "mimetype": "text/x-qsharp", + "name": "qsharp", + "version": "0.27" + }, + "nteract": { + "version": "nteract-front-end@1.0.0" + }, + "vscode": { + "interpreter": { + "hash": "5928ddfb481d60843a3b943727ce04da7552e01006ad87377dd54780c5247bec" + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/samples/azure-quantum/check-ghz/CheckGHZ.ipynb b/samples/azure-quantum/check-ghz/CheckGHZ-quantinuum-qsharp.ipynb similarity index 100% rename from samples/azure-quantum/check-ghz/CheckGHZ.ipynb rename to samples/azure-quantum/check-ghz/CheckGHZ-quantinuum-qsharp.ipynb diff --git a/samples/azure-quantum/check-ghz/README.md b/samples/azure-quantum/check-ghz/README.md index 76c9072b5d47..3e060ae73ddb 100644 --- a/samples/azure-quantum/check-ghz/README.md +++ b/samples/azure-quantum/check-ghz/README.md @@ -16,3 +16,8 @@ products: This sample illustrates how to blend classical and quantum instructions using a simple Q# program. This sample is available in the notebook samples gallery in Azure Quantum workspaces in the Azure Portal. For an example of how to run these notebooks in Azure, see [this getting started guide](https://docs.microsoft.com/azure/quantum/get-started-jupyter-notebook?tabs=tabid-ionq). + +## Manifest + +- [CheckGHZ-quantinuum-qsharp.ipynb](./CheckGHZ-quantinuum-qsharp.ipynb): Azure Quantum notebook for running a program that blends classical and quantum on the Quantinuum simulator +- [CheckGHZ-qci-qsharp.ipynb](./CheckGHZ-qci-qsharp.ipynb): Azure Quantum notebook for running a program that blends classical and quantum on the QCI simulator diff --git a/samples/azure-quantum/three-qubit-repetition-code/README.md b/samples/azure-quantum/three-qubit-repetition-code/README.md index 844e06b2a36e..5230dc97d251 100644 --- a/samples/azure-quantum/three-qubit-repetition-code/README.md +++ b/samples/azure-quantum/three-qubit-repetition-code/README.md @@ -16,3 +16,8 @@ products: This sample demonstrates how to create a 3 qubit repetition code that can be used to detect and correct bit flip errors. It leverages integrated hybrid computing features to count the number of times a bit flip error occurred while the state of a qubit register is coherent. + +## Manifest + +- [TQRP-quantinuum-qsharp.ipynb](./TQRP-quantinuum-qsharp.ipynb): Azure Quantum notebook for running a 3-qubit repetition code on the Quantinuum simulator +- [TQRP-qci-qsharp.ipynb](./TQRP-qci-qsharp.ipynb): Azure Quantum notebook for running a 3-qubit repetition code on the QCI simulator diff --git a/samples/azure-quantum/three-qubit-repetition-code/TQRP-qci-qsharp.ipynb b/samples/azure-quantum/three-qubit-repetition-code/TQRP-qci-qsharp.ipynb new file mode 100644 index 000000000000..2847c331a2d6 --- /dev/null +++ b/samples/azure-quantum/three-qubit-repetition-code/TQRP-qci-qsharp.ipynb @@ -0,0 +1,402 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Three qubit repetition code\n", + "This sample demonstrates how to implement a 3 qubit repetition code that can be used to detect and correct bit flip errors. It leverages integrated hybrid computing features to count the number of times a bit flip occurred while qubits are coherent.\n", + "\n", + "Find more about integrated quantum computing at https://aka.ms/AQ/Hybrid/Docs\n", + "\n", + "In this sample we will:\n", + "1. Implement a 3 qubit repetition code.\n", + "2. Detect and correct bit flip errors.\n", + "3. Use classical compute to count the number of times a bit flip occurred.\n", + "## Connect to the Azure Quantum workspace\n", + "First, find the resource ID of your Azure Quantum workspace. You can copy/paste this from the top-right corner of your Quantum Workspace page in Azure Portal.\n", + "\n", + "Next, you can run `%azure.connect` to connect to the workspace and display the list of provisioned targets that support execution of Q# programs. If you are prompted to login, be sure to use the same account you used to create your Azure Quantum workspace." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "%azure.connect \"/subscriptions/subscriptionId/resourceGroups/resourceGroupName/providers/Microsoft.Quantum/Workspaces/workspaceName\" location=\"westus\"" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Select a target and opt-in to use integrated hybrid computing\n", + "Now, we select the target the program is intended to be run on using the `%azure.target` command. This information is used by the Q# compiler to check the program can be run on the specified target taking into consideration its capabilities.\n", + "\n", + "Since integrated hybrid computing is an opt-in feature, we run the `%azure.target-capability` command to opt into it.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%azure.target qci.simulator\n", + "%azure.target-capability AdaptiveExecution" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Open the required Q# namespaces\n", + "Open the Q# namespaces that provide the necessary operations to implement this sample.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "open Microsoft.Quantum.Intrinsic;\n", + "open Microsoft.Quantum.Math;\n", + "open Microsoft.Quantum.Measurement;" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Implement a repetition code\n", + "The following operation is used to create a repetition code using a 3 qubit register." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "operation Encode(register : Qubit[]) : Unit is Adj {\n", + " CNOT(register[0], register[1]);\n", + " CNOT(register[0], register[2]);\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Measure a bit flip error syndrome\n", + "The following operation measures a bit flip error syndrome by checking the parities between qubits 0 and 1, and between qubits 1 and 2.\n", + "\n", + "This operation uses a 2 qubit auxiliary register and leverages two integrated hybrid computing capabilities: mid-program qubit measurement and qubit re-use. For some programs, these features reduce the number of qubits needed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "operation MeasureBitFlipSyndrome(encodedRegister : Qubit[], auxiliaryRegister : Qubit[]) : (Result, Result)\n", + "{\n", + " // Measure the bit flip syndrome by checking the parities between qubits 0 and 1, and between qubits 1 and 2.\n", + " ResetAll(auxiliaryRegister);\n", + " CNOT(encodedRegister[0], auxiliaryRegister[0]);\n", + " CNOT(encodedRegister[1], auxiliaryRegister[0]);\n", + " CNOT(encodedRegister[1], auxiliaryRegister[1]);\n", + " CNOT(encodedRegister[2], auxiliaryRegister[1]);\n", + " let parity01 = MResetZ(auxiliaryRegister[0]);\n", + " let parity12 = MResetZ(auxiliaryRegister[1]);\n", + " return (parity01, parity12);\n", + "}\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Use the bit flip error syndrome to revert bit flips\n", + "The following operation reverts a bit flip in a specific qubit in the register depending on the provided error syndrome. It returns a boolean that represents whether any a bit flip was reverted on any of the qubits\n.", + "\n", + "This operation uses another integrated hybrid computing capability, branching based on qubit measurements. As we can observe, a different quantum operation is performed depending on the measurement results received as parameters." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "operation RevertBitFlip(register : Qubit[], parity01 : Result, parity12 : Result) : Bool\n", + "{\n", + " if (parity01 == One and parity12 == Zero) {\n", + " X(register[0]);\n", + " }\n", + " elif (parity01 == One and parity12 == One) {\n", + " X(register[1]);\n", + " }\n", + " elif (parity01 == Zero and parity12 == One) {\n", + " X(register[2]);\n", + " }\n", + "\n", + " return parity01 == One or parity12 == One;\n", + "}\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Implement an operation that could introduce bit flips\n", + "In order to test our repetition code, we can apply an operation to our encoded qubit register that is equivalent to applying an identity operation.\n", + "To achieve this, we can apply a few rotations about the x-axis such that after applying them the qubit register is in the same state it was originally in.\n", + "Since the `Rx` operation has a $2\\pi$ period, applying a $\\frac{\\pi}{2}$ rotation 4 times should return the qubit to its original state (given that it is not possible to measure the difference between states $|\\psi〉$ and $-|\\psi〉$).\n", + "Note that since the qubit register represents a repetition code, rotations are applied to each qubit in the register.\n", + "\n", + "When running this operation on real quantum devices or noisy simulators, unitended bit flips could occur, and we want our program to detect and correct them.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "operation ApplyRotationalIdentity(register : Qubit[]) : Unit is Adj\n", + "{\n", + " let theta = PI() * 0.5;\n", + " for i in 1 .. 4 {\n", + " for qubit in register\n", + " {\n", + " Rx(theta, qubit);\n", + " }\n", + " }\n", + "}\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Create a program to test our repetition code\n", + "Now that we have implemented all the building blocks, we will integrate them all into a single program that we can submit to a quantum device or simulator.\n", + "\n", + "Our program will do the following:\n", + "1. Initialize a qubit into a superposition state $|-〉$.\n", + "2. Create 3 qubit repetition code.\n", + "3. Apply several quantum operations to the encoded qubit register, performing bit flip detection and correction between each quantum operation.\n", + "4. Decode the qubit register and measure it in the computational basis.\n", + "5. As output, return a boolean representing whether the qubit measurement was the expected one and an integer representing the number of times a bit flip occurred.\n", + "\n", + "This program uses two more integrated hybrid computing features: classical compute during coherence time and additional output data types (boolean and integer).\n", + "### ❕ Please note that you will see a warning displayed (QS5028)\n", + "It can be ignored for the purposes of this sample. It will be addressed in a subsequent release of the Quantum Development Kit." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "operation ThreeQubitRepetitionCode() : (Bool, Int) {\n", + " // Use two qubit registers, one for encoding and an auxiliary one for syndrome measurements.\n", + " use encodedRegister = Qubit[3];\n", + " use auxiliaryRegister = Qubit[2];\n", + "\n", + " // Initialize the first qubit in the register to a |-〉 state.\n", + " H(encodedRegister[0]);\n", + " Z(encodedRegister[0]);\n", + "\n", + " // Apply several unitary operations to the encoded qubits performing bit flip detection and correction between\n", + " // each application.\n", + " mutable bitFlipCount = 0;\n", + " within {\n", + " // The 3 qubit register is used as a repetition code.\n", + " Encode(encodedRegister);\n", + " }\n", + " apply {\n", + " let iterations = 5;\n", + " for _ in 1 .. iterations {\n", + " // Apply a sequence of rotations to the encoded register that effectively perform an identity operation.\n", + " ApplyRotationalIdentity(encodedRegister);\n", + "\n", + " // Measure the bit flip error syndrome, revert the bit flip if needed, and increase the count if a bit flip occurred.\n", + " let (parity01, parity12) = MeasureBitFlipSyndrome(encodedRegister, auxiliaryRegister);\n", + " let bitFlipReverted = RevertBitFlip(encodedRegister, parity01, parity12);\n", + " if (bitFlipReverted) {\n", + " set bitFlipCount += 1;\n", + " }\n", + " }\n", + " }\n", + "\n", + " // Transform the qubit to the |1〉 state and measure it in the computational basis.\n", + " H(encodedRegister[0]);\n", + " let result = MResetZ(encodedRegister[0]) == One;\n", + " ResetAll(encodedRegister);\n", + "\n", + " // The output of the program is a boolean-integer tuple where the boolean represents whether the qubit\n", + " // measurement result was the expected one and the integer represents the number of times bit flips occurred\n", + " // throughout the program.\n", + " return (result, bitFlipCount);\n", + "}\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Submit the three qubit repetition code program\n", + "If the job has not been completed after the client times out (300 seconds), you can query the status using `%azure.status` followed by querying the output using `%azure.output`.
\n", + "\n", + "If the kernel was restarted after the program had been submitted, you will have to use `%azure.status ` to get the status of the job and `%azure.output ` to retrieve the results.
\n", + "You can also check the status of the job under the **Job management** section on the left side menu of the portal.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%azure.execute ThreeQubitRepetitionCode shots=50 timeout=300 poll=10" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "%azure.status" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Understanding the results\n", + "Each item in the histogram is a boolean-integer tuple representing whether the qubit measurement was the expected one and the number of times bit flip occurred throughout program execution. Associated to an item in the histogram is the frequency of that particular output.
\n", + "\n", + "For example:\n", + "- A `(true, 0)` output means that the qubit was measured in the expected state and no bit flips occurred.\n", + "- A `(true, 2)` output means that the qubit was measured in the expected state and bit flips occurred twice.\n", + "- A `(false, 1)` output means that the qubit was **not** measured in the expected state and bit flips occurred once.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "%azure.output" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## ↗ Learning more about Integrated Hybrid Computing\n", + "Now that you have run this sample, you can further learn and experiment with other samples available in the gallery.\n", + "\n", + "To learn more, please refer to our [online documentation](https://aka.ms/AQ/Hybrid/Docs)." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Q#", + "language": "qsharp", + "name": "iqsharp" + }, + "language_info": { + "file_extension": ".qs", + "mimetype": "text/x-qsharp", + "name": "qsharp", + "version": "0.14" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/samples/azure-quantum/three-qubit-repetition-code/ThreeQubitRepetitionCode.ipynb b/samples/azure-quantum/three-qubit-repetition-code/TQRP-quantinuum-qsharp.ipynb similarity index 100% rename from samples/azure-quantum/three-qubit-repetition-code/ThreeQubitRepetitionCode.ipynb rename to samples/azure-quantum/three-qubit-repetition-code/TQRP-quantinuum-qsharp.ipynb