diff --git a/tutorials/ieee_workshop.ipynb b/tutorials/ieee_workshop.ipynb new file mode 100644 index 000000000..3d7d1f96b --- /dev/null +++ b/tutorials/ieee_workshop.ipynb @@ -0,0 +1,2083 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Quantum Cloud, Near-Time Compute, and Qiskit Runtime\n", + "
\n", + "
\n", + "\n", + "jessieyu@us.ibm.com" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "You can find a copy of this presentation at\n", + "\n", + "https://github.com/Qiskit-Partners/qiskit-runtime/tree/main/tutorials/ieee_workshop.ipynb" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Agenda\n", + "\n", + "- Introduction to Qiskit\n", + "- Introduction to IBM Quantum\n", + "- Variational Quantum Algorithms\n", + "- What is Qiskit Runtime\n", + "- Running a Qiskit Runtime program\n", + "- Uploading a Qiskit Runtime program\n", + "- Invoking Qiskit Runtime API directly\n", + "- Exercise" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Introduction to Qiskit\n", + "\n", + "Qiskit is a Python-based, open source software development toolkit (SDK) for working with quantum computers. It can be used at the level of circuits, algorithms, and application modules.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Installing Qiskit\n", + "\n", + "*Command:* `pip install Qiskit`\n", + "\n", + "*Python version:* 3.6+\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Typical Qiskit Workflow\n", + "\n", + "**Build**: Design a quantum circuit(s) that represents the problem you are considering.\n", + "\n", + "**Compile**: Compile circuits for a specific quantum backend, e.g., a quantum system or classical simulator.\n", + "\n", + "**Run**: Run the compiled circuits on the specified quantum backend.\n", + "\n", + "**Analyze**: Compute summary statistics and visualize the results of the experiments.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "#### Step 1: Build the Circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
     ┌───┐     ┌─┐   \n",
+       "q_0: ┤ H ├──■──┤M├───\n",
+       "     └───┘┌─┴─┐└╥┘┌─┐\n",
+       "q_1: ─────┤ X ├─╫─┤M├\n",
+       "          └───┘ ║ └╥┘\n",
+       "c: 2/═══════════╩══╩═\n",
+       "                0  1 
" + ], + "text/plain": [ + " ┌───┐ ┌─┐ \n", + "q_0: ┤ H ├──■──┤M├───\n", + " └───┘┌─┴─┐└╥┘┌─┐\n", + "q_1: ─────┤ X ├─╫─┤M├\n", + " └───┘ ║ └╥┘\n", + "c: 2/═══════════╩══╩═\n", + " 0 1 " + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from qiskit import QuantumCircuit\n", + "\n", + "# Create a quantum circuit with 2 qubits and 2 classical bits\n", + "circuit = QuantumCircuit(2, 2)\n", + "\n", + "# Add a Hadamard gate on qubit 0\n", + "circuit.h(0)\n", + "\n", + "# Add a CX (CNOT) gate on control qubit 0 and target qubit 1\n", + "circuit.cx(0, 1)\n", + "\n", + "# Measure qubits 0 and 1 onto classical bits 0 and 1\n", + "circuit.measure([0, 1], [0, 1])\n", + "\n", + "# Draw the circuit\n", + "circuit.draw()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "#### Step 2: Compile the Circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "from qiskit import transpile\n", + "from qiskit.providers.aer import AerSimulator\n", + "\n", + "# Use a local simulator\n", + "simulator = AerSimulator()\n", + "\n", + "# Compile the circuit down to low-level instructions supported by the backend\n", + "compiled_circuit = transpile(circuit, simulator)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "#### Step 3: Run the Circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# Execute the circuit on the qasm simulator\n", + "# shots defines the number of executions\n", + "job = simulator.run(compiled_circuit, shots=1000)\n", + "\n", + "# Grab results from the job\n", + "result = job.result()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "#### Step 4: Analyze and Visualize the Result" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from qiskit.visualization import plot_histogram\n", + "\n", + "# Get summarized counts of qubit measurements\n", + "counts = result.get_counts()\n", + "\n", + "# Plot a histogram\n", + "# \"00\" means both qubits were measured 0; \"11\" means both were measured 1.\n", + "plot_histogram(counts)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Introduction to IBM Quantum\n", + "\n", + "Offers access to cloud-based quantum computing services\n", + "\n", + "- quantum processors\n", + "- simulators\n", + "- experiments\n", + "- tutorials\n", + "- **runtime**" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Using Qiskit to access IBM Quantum services\n", + "\n", + "Qiskit is designed to work with different providers. A _provider_ is any entity that provides quantum-related services that can be accessed using Qiskit. The most common service is quantum processors. `AQT`, `Honeywell`, and `IBM` are example of companies that provide access to their quantum processors through Qiskit.\n", + "\n", + "Since `Runtime` is currently an IBM-only service, this tutorial will focus on using IBM Quantum services.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "Before you can access IBM Quantum services, you need an IBM Quantum account. \n", + "You can sign up for an account at https://quantum-computing.ibm.com/." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "Once you have an account, you can grab your API token\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "#### Initializing Your Account in Qiskit" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# Import the module needed to access IBM Quantum\n", + "from qiskit import IBMQ\n", + "\n", + "# Load your IBM Quantum account or enable the account if it's not previously saved.\n", + "provider = IBMQ.load_account()\n", + "# provider = IBMQ.enable_account(MY_TOKEN)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "IBM Quantum provider uses the syntax:\n", + "\n", + "```\n", + "provider.SERVICE.METHOD()\n", + "```\n", + "\n", + "where SERVICE might be one of {backend, runtime, etc}\n", + "\n", + "- Use `provider.backend` to target a quantum processor or simulator for running circuits\n", + "- Use `provider.runtime` to target a higher level runtime program\n", + "\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "#### Running a Circuit on IBM Quantum Backend" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# Select a backend to run the circuit\n", + "backend = provider.backend.ibmq_qasm_simulator\n", + "\n", + "# Compile the circuit for this backend\n", + "compiled_circuit = transpile(circuit, backend)\n", + "\n", + "# Run the circuit on the backend\n", + "job = backend.run(compiled_circuit)\n", + "\n", + "# Get the result\n", + "result = job.result()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "image/png": "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++67j61bt7J161buu+8+zj77bMaMGUNTUxPPPvssAPfff//edSSpr6vq6QLUc6qqqrjppps4++yzaWlp4aKLLmLatGlcd9111NXVcd5553HjjTdy9913U1VVxbBhw5g3bx4Aw4YN49prr+WMM84A4LrrrmPYsGEAfOYzn2HmzJkcfvjhHH/88XvXkaS+ziknh/CUE0l9y7333svHPvYxWlpauPjii/n0pz/dbr+77rqL888/n1//+tfU1dWxa9cuPvjBD9LY2Mhhhx3GnDlzOOuss3j++ed55zvfyVNPPcWAAQM499xz252vfahxyokk9XEtLS185CMf4Z577qGpqYk77riDpqamP+m3fft25syZw/Tp0/e2zZ07F4DHHnuM+++/n0984hO89NJLAFx99dX87ne/49FHH+Whhx7innvu6Z4d6qMMTUnqA4rOq7722mv51Kc+xZFHHrm3rampiTe84Q0AjBgxgqOPPprGxkaOOuooXv/61wNwxBFHUFtby5o1a7pnh/ooQ1OS+oAi86oXL17M6tWreetb3/qy9pqaGu6++252797NypUrWbRo0ctGvwP8/ve/58c//jFvfOMbD95O9AMOBJKkfuCll17iqquuanfg3UUXXcQTTzxBXV0dxx9/PGeeeSYDBgzYu3z37t285z3v4YorrmDixIndWHXfY2hKUh+wr3nV27dvZ+nSpZx11lkArF+/nvPOO4+7776buro6vv71r+/te+aZZzJ58uS9ny+99FImTZrElVdeedD3o6/z9Kwk9QH7mlf9ile8gk2bNrFq1SpWrVrFa17zmr2B+fzzz/Pcc88BpbnTVVVVex/McM011/CHP/yBG264oSd2q8/xSFOS+oAi86o7snHjRs4++2wOO+wwxowZw+233w6Ujla/8IUv8KpXvYra2loAPvrRj3LxxRd3yz71Rc7TdJ6mJKkV52lKktQFDE1JkgoyNCVJKsjQlCSpIEfPdoFLbujpCnQwzL2ypyuQ1Nt4pClJUkGGpiRJBRmakiQVZGhKklSQoSlJUkGGpiRJBTnlRNIhx2li/VN3TBPzSFOSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCjI0JUkqyNCUJKkgQ1OSpIIMTUmSCur20IyIyyJiZUS8EBGLIuJ1BdebERG7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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot the result\n", + "# \"00\" means both qubits were measured 0; \"11\" means both were measured 1.\n", + "plot_histogram(result.get_counts())\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Variational Quantum Algorithms\n", + "\n", + "Variational Quantum Algorithms (VQA) use a classical optimizer to train a parameterized quantum circuit to approximate solutions for a given problem. \n", + "\n", + "VQA's typically need fewer gates and qubits. In turn, they are more resistant to noise.\n", + "\n", + "Therefore, they are well suited to handle near-term quantum computer constraints." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "VQA's are typically iterative. Each iteration involves both quantum and classical processing. \n", + "\n", + "Output (a measurement) from one iteration is sent to the classical optimizer which generates input (a parameter) for the next iteration:\n", + "\n", + "
\n", + "\n", + "
" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Running a VQA Prior to the Qiskit Runtime\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Qiskit Runtime\n", + "\n", + "Qiskit Runtime is a new execution model. \n", + "\n", + "It reduces I/O overhead for applications, such as VQA's, that need many iterations that use both quantum and classical processing. \n", + "\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Qiskit Runtime Benefits\n", + "\n", + "This year, the Qiskit Runtime contributed to a **120x** speedup in simulating lithium hydride when compared to a previous simulation from in 2017.\n", + "\n", + "Beyond performance, you can also create larger applications using smaller, pre-built programs.\n", + "\n", + "Qiskit Runtime programs can be commercialized or shared freely in the cloud." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Defining a Qiskit Runtime Program\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "**source**: Python code that uses Qiskit to do quantum/classical processing\n", + "\n", + "**metadata**: Documentation that describes what the program does" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "#### Example: sample-program" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "import random\n", + "\n", + "from qiskit import transpile\n", + "from qiskit.circuit.random import random_circuit\n", + "\n", + "def prepare_circuits(backend):\n", + " \"\"\"Generate a random circuit.\"\"\"\n", + " circuit = random_circuit(num_qubits=5, depth=4, measure=True,\n", + " seed=random.randint(0, 1000))\n", + " return transpile(circuit, backend)\n", + "\n", + "\n", + "def main(backend, user_messenger, iterations):\n", + " \"\"\"Main entry point of the program.\"\"\"\n", + " for it in range(iterations):\n", + " qc = prepare_circuits(backend)\n", + " result = backend.run(qc).result()\n", + " user_messenger.publish({\"iteration\": it, \"counts\": result.get_counts()})\n", + "\n", + " return \"All done!\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "#### sample-program Metadata\n", + "\n", + "```\n", + "{\n", + " \"name\": \"sample-program\",\n", + " \"description\": \"A sample runtime program.\",\n", + " \"max_execution_time\": 300,\n", + " \"version\": \"1.0\",\n", + " \"backend_requirements\": {\"min_num_qubits\": 5},\n", + " \"parameters\": [\n", + " {\"name\": \"iterations\", \"description\": \"Number of iterations to run. Each iteration generates and runs a random circuit.\", \"type\": \"int\", \"required\": True}\n", + " ],\n", + " \"return_values\": [\n", + " {\"name\": \"-\", \"description\": \"A string that says 'All done!'.\", \"type\": \"string\"}\n", + " ],\n", + " \"interim_results\": [\n", + " {\"name\": \"iteration\", \"description\": \"Iteration number.\", \"type\": \"int\"},\n", + " {\"name\": \"counts\", \"description\": \"Histogram data of the circuit result.\", \"type\": \"dict\"}\n", + " ]\n", + "}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Finding and Running Programs" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "Since programs are now stored in the cloud, you can browse and run previously published programs.\n", + "\n", + "Using Qiskit (0.29+), you can search by program ID or browse the entire catalog. \n", + "\n", + "You can also list available programs on the IBM Quantum website. " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Finding by Program ID" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "sample-program:\n", + " Name: sample-program\n", + " Description: A sample runtime program.\n", + " Version: 1.0\n", + " Creation date: 2021-07-02T13:45:13.000000\n", + " Max execution time: 300\n", + " Input parameters:\n", + " - iterations:\n", + " Description: Number of iterations to run. Each iteration generates and runs a random circuit.\n", + " Type: int\n", + " Required: True\n", + " Interim results:\n", + " - iteration:\n", + " Description: Iteration number.\n", + " Type: int\n", + " - counts:\n", + " Description: Histogram data of the circuit result.\n", + " Type: dict\n", + " Returns:\n", + " - -:\n", + " Description: A string that says 'All done!'.\n", + " Type: string\n" + ] + } + ], + "source": [ + "# Print the metadata of a runtime program\n", + "print(provider.runtime.program(\"sample-program\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Listing All Programs" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "==================================================\n", + "vqe:\n", + " Name: vqe\n", + " Description: Variational Quantum Eigensolver (VQE) to find the minimal eigenvalue of a Hamiltonian.\n", + " Version: 1.1\n", + " Creation date: 2021-08-12T07:06:50.000000\n", + " Max execution time: 18000\n", + " Input parameters:\n", + " - ansatz:\n", + " Description: A parameterized quantum circuit preparing the ansatz wavefunction for the VQE. It is assumed that all qubits are initially in the 0 state.\n", + " Type: QuantumCircuit\n", + " Required: True\n", + " - operator:\n", + " Description: The Hamiltonian whose smallest eigenvalue we're trying to find.\n", + " Type: PauliSumOp\n", + " Required: True\n", + " - optimizer:\n", + " Description: The classical optimizer used in to update the parameters in each iteration. Can be either any of Qiskit's optimizer classes. If a dictionary, only SPSA and QN-SPSA are supported and the dictionary must specify the name and options of the optimizer, e.g. ``{'name': 'SPSA', 'maxiter': 100}``.\n", + " Type: Union[Optimizer, dict]\n", + " Required: True\n", + " - initial_parameters:\n", + " Description: Initial parameters of the ansatz. Can be an array or the string ``'random'`` to choose random initial parameters.\n", + " Type: Union[numpy.ndarray, str]\n", + " Required: True\n", + " - aux_operators:\n", + " Description: A list of operators to be evaluated at the final, optimized state.\n", + " Type: List[PauliSumOp]\n", + " Required: False\n", + " - shots:\n", + " Description: The number of shots used for each circuit evaluation. Defaults to 1024.\n", + " Type: int\n", + " Required: False\n", + " - measurement_error_mitigation:\n", + " Description: Whether to apply measurement error mitigation in form of a complete measurement fitter to the measurements. Defaults to False.\n", + " Type: bool\n", + " Required: False\n", + " - initial_layout:\n", + " Description: Initial position of virtual qubits on the physical qubits of the quantum device. Default is None.\n", + " Type: list or dict\n", + " Required: False\n", + " Interim results:\n", + " none\n", + " Returns:\n", + " - optimizer_evals:\n", + " Description: The number of steps of the optimizer.\n", + " Type: int\n", + " - optimizer_time:\n", + " Description: The total time taken by the optimizer.\n", + " Type: float\n", + " - optimal_value:\n", + " Description: The smallest value found during the optimization. Equal to the ``eigenvalue`` attribute.\n", + " Type: float\n", + " - optimal_point:\n", + " Description: The optimal parameter values found during the optimization.\n", + " Type: np.ndarray\n", + " - optimal_parameters:\n", + " Description: Not supported at the moment, therefore ``None``.\n", + " Type: NoneType\n", + " - cost_function_evals:\n", + " Description: The number of cost function (energy) evaluations\n", + " Type: int\n", + " - eigenstate:\n", + " Description: The square root of sampling probabilities for each computational basis state of the circuit with optimal parameters.\n", + " Type: dict\n", + " - eigenvalue:\n", + " Description: The estimated eigenvalue.\n", + " Type: complex\n", + " - aux_operator_eigenvalues:\n", + " Description: The expectation values of the auxiliary operators at the optimal state.\n", + " Type: np.ndarray\n", + " - optimizer_history:\n", + " Description: A dictionary containing information about the optimization process: the value objective function, parameters, and a timestamp.\n", + " Type: dict\n", + "==================================================\n", + "circuit-runner:\n", + " Name: circuit-runner\n", + " Description: A runtime program that takes one or more circuits, compiles them, executes them, and optionally applies measurement error mitigation.\n", + " Version: 1.0\n", + " Creation date: 2021-07-02T13:46:10.000000\n", + " Max execution time: 14400\n", + " Input parameters:\n", + " - circuits:\n", + " Description: A circuit or a list of circuits.\n", + " Type: A QuantumCircuit or a list of QuantumCircuits.\n", + " Required: True\n", + " - shots:\n", + " Description: Number of repetitions of each circuit, for sampling. Default: 1024.\n", + " Type: int\n", + " Required: False\n", + " - initial_layout:\n", + " Description: Initial position of virtual qubits on physical qubits.\n", + " Type: dict or list\n", + " Required: False\n", + " - layout_method:\n", + " Description: Name of layout selection pass ('trivial', 'dense', 'noise_adaptive', 'sabre')\n", + " Type: string\n", + " Required: False\n", + " - routing_method:\n", + " Description: Name of routing pass ('basic', 'lookahead', 'stochastic', 'sabre').\n", + " Type: string\n", + " Required: False\n", + " - translation_method:\n", + " Description: Name of translation pass ('unroller', 'translator', 'synthesis').\n", + " Type: string\n", + " Required: False\n", + " - seed_transpiler:\n", + " Description: Sets random seed for the stochastic parts of the transpiler.\n", + " Type: int\n", + " Required: False\n", + " - optimization_level:\n", + " Description: How much optimization to perform on the circuits (0-3). Higher levels generate more optimized circuits. Default is 1.\n", + " Type: int\n", + " Required: False\n", + " - init_qubits:\n", + " Description: Whether to reset the qubits to the ground state for each shot.\n", + " Type: bool\n", + " Required: False\n", + " - rep_delay:\n", + " Description: Delay between programs in seconds.\n", + " Type: float\n", + " Required: False\n", + " - transpiler_options:\n", + " Description: Additional compilation options.\n", + " Type: dict\n", + " Required: False\n", + " - measurement_error_mitigation:\n", + " Description: Whether to apply measurement error mitigation. Default is False.\n", + " Type: bool\n", + " Required: False\n", + " Interim results:\n", + " none\n", + " Returns:\n", + " - -:\n", + " Description: Circuit execution results.\n", + " Type: RunnerResult object\n", + "==================================================\n", + "sample-program:\n", + " Name: sample-program\n", + " Description: A sample runtime program.\n", + " Version: 1.0\n", + " Creation date: 2021-07-02T13:45:13.000000\n", + " Max execution time: 300\n", + " Input parameters:\n", + " - iterations:\n", + " Description: Number of iterations to run. Each iteration generates and runs a random circuit.\n", + " Type: int\n", + " Required: True\n", + " Interim results:\n", + " - iteration:\n", + " Description: Iteration number.\n", + " Type: int\n", + " - counts:\n", + " Description: Histogram data of the circuit result.\n", + " Type: dict\n", + " Returns:\n", + " - -:\n", + " Description: A string that says 'All done!'.\n", + " Type: string\n", + "==================================================\n", + "quantum-kernel-alignment:\n", + " Name: quantum-kernel-alignment\n", + " Description: Quantum kernel alignment algorithm that learns, on a given dataset, a quantum kernel maximizing the SVM classification margin.\n", + " Version: 1\n", + " Creation date: 2021-05-06T14:56:53.000000\n", + " Max execution time: 28800\n", + " Input parameters:\n", + " - feature_map:\n", + " Description: An instance of FeatureMap in dictionary format used to map classical data into a quantum state space.\n", + " Type: dict\n", + " Required: True\n", + " - data:\n", + " Description: NxD array of training data, where N is the number of samples and D is the feature dimension.\n", + " Type: numpy.ndarray\n", + " Required: True\n", + " - labels:\n", + " Description: Nx1 array of +/-1 labels of the N training samples.\n", + " Type: numpy.ndarray\n", + " Required: True\n", + " - initial_kernel_parameters:\n", + " Description: Initial parameters of the quantum kernel. If not specified, an array of randomly generated numbers is used.\n", + " Type: numpy.ndarray\n", + " Required: False\n", + " - maxiters:\n", + " Description: Number of SPSA optimization steps. Default is 1.\n", + " Type: int\n", + " Required: False\n", + " - C:\n", + " Description: Penalty parameter for the soft-margin support vector machine. Default is 1.\n", + " Type: float\n", + " Required: False\n", + " - initial_layout:\n", + " Description: Initial position of virtual qubits on the physical qubits of the quantum device. Default is None.\n", + " Type: list or dict\n", + " Required: False\n", + " Interim results:\n", + " none\n", + " Returns:\n", + " - aligned_kernel_parameters:\n", + " Description: The optimized kernel parameters found from quantum kernel alignment.\n", + " Type: numpy.ndarray\n", + " - aligned_kernel_matrix:\n", + " Description: The aligned quantum kernel matrix evaluated with the optimized kernel parameters on the training data.\n", + " Type: numpy.ndarray\n" + ] + } + ], + "source": [ + "provider.runtime.pprint_programs(refresh=True)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Using the IBM Quantum Website\n", + "\n", + "" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Running a Program \n", + "\n", + "Step 1 of 2: defining inputs, options, and callback" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# Define program inputs in a dictionary\n", + "runtime_inputs = {\n", + " 'iterations': 2\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# Alternatively, define program inputs in a namespace\n", + "params = provider.runtime.program(\"sample-program\").parameters()\n", + "params.iterations = 2" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# Define program options (more on backend selection later...)\n", + "options = {'backend_name': 'ibmq_qasm_simulator'}" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# Define interim result callback (optional)\n", + "def interim_result_callback(job_id, interim_result):\n", + " print(f\"interim result: {interim_result}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Running a Program \n", + "\n", + "Step 2 of 2: executing and getting results" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "c4t0trbk1sj3cl16qsag\n" + ] + } + ], + "source": [ + "# Run program\n", + "job = provider.runtime.run(program_id=\"sample-program\",\n", + " options=options,\n", + " inputs=runtime_inputs,\n", + " callback=interim_result_callback\n", + " )\n", + "print(job.job_id())" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "interim result: {'iteration': 0, 'counts': {'01110': 41, '01000': 39, '00010': 36, '00100': 32, '00110': 41, '00111': 90, '00011': 87, '00000': 28, '01010': 33, '01111': 101, '01001': 87, '00101': 108, '01100': 32, '01101': 95, '01011': 83, '00001': 91}}\n", + "interim result: {'iteration': 1, 'counts': {'11111': 7, '01111': 19, '01010': 178, '11010': 162, '11001': 249, '01001': 229, '11000': 79, '01000': 101}}\n", + "All done!\n" + ] + } + ], + "source": [ + "# Get job result\n", + "result = job.result()\n", + "print(result)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Backend Selection\n", + "\n", + "At this time, Qiskit Runtime is only available on `ibmq_qasm_simulator` for open-access users. It is available on select backends for premium users. " + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[,\n", + " ]" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "premium_provider = IBMQ.get_provider(project='terra')\n", + "\n", + "# Use input_allowed=\"runtime\" to select backends that support runtime\n", + "premium_provider.backends(input_allowed='runtime')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Job Interaction\n", + "\n", + "\n", + "When you run a published program, the execution instance becomes a job. \n", + "\n", + "Using Qiskit, you can reference and interact with your job.\n", + "\n", + "You can also list and interact with your jobs on the IBM Quantum website. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "Note that a **runtime job** is an instance of `qiskit.providers.ibmq.runtime.RuntimeJob`. It is not the same as a traditional circuit job and therefore has different methods/attributes.\n", + "\n", + "\n", + "Runtime job restrictions:\n", + "\n", + "- Cannot exceed max execution time\n", + "- Consumes \"fair share\"\n", + "- 35GB of memory per execution" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Referencing Jobs" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Job c4t0trbk1sj3cl16qsag is an execution instance of runtime program sample-program.\n", + "This job ran on backend ibmq_qasm_simulator and had input parameters {'iterations': 2}\n" + ] + } + ], + "source": [ + "retrieved_job = provider.runtime.job(job.job_id())\n", + "print(f\"Job {retrieved_job.job_id()} is an execution instance of runtime program {retrieved_job.program_id}.\")\n", + "print(f\"This job ran on backend {retrieved_job.backend()} and had input parameters {retrieved_job.inputs}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "c4t0trbk1sj3cl16qsag\n", + "c4t0tbjk1sj3cl16qs60\n" + ] + } + ], + "source": [ + "retrieved_jobs = provider.runtime.jobs(limit=2)\n", + "for rjob in retrieved_jobs:\n", + " print(rjob.job_id())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Summary of job operations" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "- `job_id()`, `backend()`, `inputs`, `program_id`, `creation_date`: metadata of job execution\n", + "
\n", + "\n", + "- `result()`, `error_messages()`, `logs()`, `status()`: returns job execution output and status\n", + "
\n", + "\n", + "- `stream_results`, `cancel_result_streaming()`: (re)enables and disable streaming interim results\n", + "
\n", + "\n", + "- `cancel()`: cancels the job" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "Or you can use the IBM Quantum website:\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Writing, Uploading, and Testing a Qiskit Runtime Program\n", + "\n", + "Like the example we saw earlier, we will now write a new program and upload it to the cloud. \n", + "\n", + "We will write the metadata and source code. We will then test it after upload and show the optional step of making the program publicly available.\n", + "
\n", + "\n", + "\n", + "**Note**: Only select accounts can upload runtime programs presently. A future release will support all accounts." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Defining Program Metadata" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "metadata = {\n", + " \"name\": \"ieee-workshop\",\n", + " \"description\": \"Exploring the equator of a Bloch sphere using input RZ angles and returning the x measurements.\",\n", + " \"max_execution_time\": 300,\n", + " \"version\": \"1.0\",\n", + " \"parameters\": [\n", + " {\"name\": \"angles\", \"description\": \"A list of angles to rotate around the z axis.\", \"type\": \"numpy array or list\", \"required\": True}\n", + " ],\n", + " \"return_values\": [\n", + " {\"name\": \"-\", \"description\": \"Combined measurements.\", \"type\": \"list\"}\n", + " ],\n", + " \"interim_results\": [\n", + " {\"name\": \"angle\", \"description\": \"Angle used for the rotation.\", \"type\": \"float\"},\n", + " {\"name\": \"counts\", \"description\": \"Histogram data of the circuit result.\", \"type\": \"dict\"}\n", + " ]\n", + "}\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Writing Source Code\n", + "\n", + "Step 1: Prepare the circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from qiskit.circuit import QuantumCircuit, Parameter\n", + "\n", + "def prepare_circuits():\n", + " theta = Parameter('θ')\n", + " qc = QuantumCircuit(1, 1)\n", + " qc.h(0)\n", + " qc.rz(theta, 0)\n", + " qc.h(0)\n", + " qc.measure(0, 0)\n", + " return qc\n", + "\n", + " \n", + "circ = prepare_circuits()\n", + "circ.draw('mpl')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Writing Source Code\n", + "\n", + "Step 2: Write the main function" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "from qiskit import transpile\n", + "\n", + "def main(backend, user_messenger, angles):\n", + " all_counts = []\n", + " \n", + " # Get the parameterized circuit\n", + " circ = prepare_circuit()\n", + " \n", + " # Get the parameter variable\n", + " param = circ.parameters[0]\n", + "\n", + " # For each input angle\n", + " for theta_val in angles:\n", + " # Set the parameter value\n", + " bound_circ = circ.bind_parameters({param: theta_val})\n", + " # Run the circuit\n", + " job = backend.run(transpile(bound_circ, backend=backend))\n", + " # Get counts\n", + " counts = job.result().get_counts()\n", + " # Publish interim result\n", + " user_messenger.publish({\"angle\": theta_val, \"counts\": counts})\n", + " # Aggregate counts\n", + " all_counts.append(counts)\n", + " \n", + " # Return combined measurements\n", + " return all_counts" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "Note that the `backend` here is an instance of `qiskit.providers.ibmq.runtime.ProgramBackend`, **not** an `IBMQBackend` and does not have the same methods. You cannot, for example, use this backend to retrieve previously executed jobs." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Uploading Your Program" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "runtime_program = \"\"\"\n", + "from qiskit.circuit import QuantumCircuit, Parameter\n", + "from qiskit import transpile\n", + "\n", + "def prepare_circuits():\n", + " theta = Parameter('θ')\n", + " qc = QuantumCircuit(1, 1)\n", + " qc.h(0)\n", + " qc.rz(theta, 0)\n", + " qc.h(0)\n", + " qc.measure(0, 0)\n", + " return qc\n", + "\n", + "def main(backend, user_messenger, angles):\n", + " circ = prepare_circuits()\n", + " param = circ.parameters[0]\n", + " all_counts = []\n", + " for theta_val in angles:\n", + " bound_circ = circ.bind_parameters({param: theta_val})\n", + " job = backend.run(transpile(bound_circ, backend=backend))\n", + " counts = job.result().get_counts()\n", + " user_messenger.publish({\"angle\": theta_val, \"counts\": counts})\n", + " all_counts.append(counts)\n", + " return all_counts \n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ieee-workshop\n" + ] + } + ], + "source": [ + "program_id = provider.runtime.upload_program(\n", + " name=\"ieee-workshop\",\n", + " data=runtime_program.encode(),\n", + " metadata=metadata\n", + ")\n", + "print(program_id)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# Alternatively, you can choose files\n", + "\n", + "# program_id = provider.runtime.upload_program(\n", + "# name=\"ieee-workshop\"\n", + "# data=\"ieee_workshop.py\"\n", + "# metadata=\"ieee_workshop.json\"\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ieee-workshop:\n", + " Name: ieee-workshop\n", + " Description: Exploring the equator of a Bloch sphere using input RZ angles and returning the x measurements.\n", + " Version: 1.0\n", + " Creation date: 2021-09-09T13:41:12.000000\n", + " Max execution time: 300\n", + " Input parameters:\n", + " - angles:\n", + " Description: A list of angles to rotate around the z axis.\n", + " Type: numpy array or list\n", + " Required: True\n", + " Interim results:\n", + " - angle:\n", + " Description: Angle used for the rotation.\n", + " Type: float\n", + " - counts:\n", + " Description: Histogram data of the circuit result.\n", + " Type: dict\n", + " Returns:\n", + " - -:\n", + " Description: Combined measurements.\n", + " Type: list\n" + ] + } + ], + "source": [ + "# Let's make sure the program was uploaded properly.\n", + "\n", + "print(provider.runtime.program(program_id))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Testing Your Program\n", + "\n", + "You can test your program using a local simulator or a real backend. It is faster to test the program locally, but it requires a slightly different test case variant because the cloud service handles serialization automatically. \n", + "\n", + "Once uploaded, you can test your program using Qiskit or the IBM Quantum website. \n", + "\n", + "We will focus on cloud testing using Qiskit here.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "#### Testing Uploaded Program Using Qiskit" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "c4t0tu24nm9h1e1cchd0\n", + "interim result: {'angle': 0.0, 'counts': {'0': 1024}}\n", + "interim result: {'angle': 0.5711986642890533, 'counts': {'1': 72, '0': 952}}\n", + "interim result: {'angle': 1.1423973285781066, 'counts': {'0': 714, '1': 310}}\n", + "interim result: {'angle': 1.7135959928671598, 'counts': {'0': 441, '1': 583}}\n", + "interim result: {'angle': 2.284794657156213, 'counts': {'1': 851, '0': 173}}\n", + "interim result: {'angle': 2.8559933214452666, 'counts': {'0': 23, '1': 1001}}\n", + "interim result: {'angle': 3.4271919857343196, 'counts': {'0': 27, '1': 997}}\n", + "interim result: {'angle': 3.998390650023373, 'counts': {'0': 169, '1': 855}}\n", + "interim result: {'angle': 4.569589314312426, 'counts': {'0': 449, '1': 575}}\n", + "interim result: {'angle': 5.140787978601479, 'counts': {'1': 293, '0': 731}}\n", + "interim result: {'angle': 5.711986642890533, 'counts': {'1': 79, '0': 945}}\n", + "interim result: {'angle': 6.283185307179586, 'counts': {'0': 1024}}\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "\n", + "# Define interim result callback\n", + "def interim_result_callback(job_id, interim_result):\n", + " print(f\"interim result: {interim_result}\")\n", + " \n", + "# Define program inputs\n", + "theta_range = np.linspace(0, 2 * np.pi, 12)\n", + "runtime_inputs = {\"angles\": theta_range}\n", + "\n", + "# Define options\n", + "options = {'backend_name': 'ibmq_qasm_simulator'}\n", + "\n", + "# Run program\n", + "job = provider.runtime.run(program_id=\"ieee-workshop\",\n", + " options=options,\n", + " inputs=runtime_inputs,\n", + " callback=interim_result_callback\n", + " )\n", + "print(job.job_id())\n", + "final_result = job.result()" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "fig = plt.figure(figsize=(8,6))\n", + "ax = fig.add_subplot(111)\n", + "\n", + "ax.plot(theta_range, list(map(lambda c: c.get('0', 0), final_result)), '.-', label='0')\n", + "ax.plot(theta_range, list(map(lambda c: c.get('1', 0), final_result)), '.-', label='1')\n", + "\n", + "ax.set_xticks([i * np.pi / 2 for i in range(5)])\n", + "ax.set_xticklabels(['0', r'$\\frac{\\pi}{2}$', r'$\\pi$', r'$\\frac{3\\pi}{2}$', r'$2\\pi$'], fontsize=14)\n", + "ax.set_xlabel('θ', fontsize=14)\n", + "ax.set_ylabel('Counts', fontsize=14)\n", + "ax.legend(fontsize=14)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "#### Making the Program Public (Optional)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# Make the program public now that we know it's working\n", + "provider.runtime.set_program_visibility(program_id=program_id, public=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "#### Deleting the Program (Optional)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# Delete the program\n", + "provider.runtime.delete_program(\"ieee-workshop\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Invoking Qiskit Runtime API directly\n", + "\n", + "You can communicate with the Qiskit Runtime API directly using basic HTTP requests without Qiskit. This can be useful, for example, if you want to integrate your non-Python application with Qiskit Runtime." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "Qiskit Runtime API documentation can be found here: https://runtime-us-east.quantum-computing.ibm.com/openapi/" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Authenticating with the Service" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# You'll need to pass your API token in the header of every call\n", + "\n", + "import os\n", + "import requests\n", + "import json\n", + "\n", + "api_token = os.environ.get(\"QE_TOKEN\")\n", + "\n", + "headers = {\n", + " 'Authorization': f'Bearer {api_token}',\n", + " 'Content-Type': 'application/json'\n", + "}\n", + "\n", + "RUNTIME_API_URL = \"https://runtime-us-east.quantum-computing.ibm.com/\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Listing Programs" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Qiskit Runtime Programs:\n", + "- vqe: Variational Quantum Eigensolver (VQE) to find the minimal eigenvalue of a Hamiltonian. \n", + "- circuit-runner: A runtime program that takes one or more circuits, compiles them, executes them, and optionally applies measurement error mitigation. \n", + "- sample-program: A sample runtime program. \n", + "- quantum-kernel-alignment: Quantum kernel alignment algorithm that learns, on a given dataset, a quantum kernel maximizing the SVM classification margin. \n" + ] + } + ], + "source": [ + "response = requests.get(RUNTIME_API_URL + 'programs' , headers=headers)\n", + "\n", + "if response.status_code != 200:\n", + " raise ValueError(f\"Unexpected status code: {response.status_code}\")\n", + "\n", + "list_of_programs = response.json() \n", + "print(f'Qiskit Runtime Programs:')\n", + "\n", + "for program in list_of_programs:\n", + " print(f'- {program[\"name\"]}: {program[\"description\"]} ')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Running sample-program" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Job: c4t0tvjk1sj3cl16qsf0\n" + ] + } + ], + "source": [ + "# Prepare program input\n", + "runtime_inputs = {\"iterations\": 2}\n", + "\n", + "# Prepare request parameters\n", + "params = json.dumps({\n", + " \"programId\": \"sample-program\",\n", + " \"hub\": \"ibm-q\",\n", + " \"group\": \"open\",\n", + " \"project\": \"main\",\n", + " \"backend\": \"ibmq_qasm_simulator\",\n", + " \"params\": [\n", + " json.dumps(runtime_inputs)\n", + " ]\n", + "})\n", + "\n", + "# Send the request\n", + "response = requests.post(RUNTIME_API_URL + 'jobs', data=params, headers=headers)\n", + "\n", + "if response.status_code != 200:\n", + " raise ValueError(f\"Unexpected status code: {response.status_code}\")\n", + "\n", + "job_id = response.json()['id']\n", + "print(f\"Job: {job_id}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for the final result\n", + "Waiting for the final result\n", + "Final Result: All done!\n" + ] + } + ], + "source": [ + "# You are going to get a 204 status code while the Qiskit program is still running.\n", + "\n", + "import time\n", + "\n", + "while True:\n", + " response = requests.get(RUNTIME_API_URL + 'jobs/'+ job_id +'/results', headers=headers)\n", + "\n", + " if response.status_code == 200:\n", + " print(f'Final Result: {response.text}')\n", + " break\n", + " \n", + " elif response.status_code == 204:\n", + " print(f'Waiting for the final result')\n", + " time.sleep(3)\n", + " \n", + " else:\n", + " print(f'Error:{response.status_code}')\n", + " break" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Exercise: Running sample-program" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "from qiskit import IBMQ\n", + "\n", + "provider = IBMQ.load_account()\n", + "\n", + "program_inputs = {'iterations': 2}\n", + "options = {'backend_name': \"ibmq_qasm_simulator\"}\n", + "\n", + "job = provider.runtime.run(program_id=\"sample-program\",\n", + " options=options,\n", + " inputs=program_inputs,\n", + " )\n", + "print(f\"job id: {job.job_id()}\")\n", + "print(f\"\\nFinal result: {job.result()}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "To sign up for an IBM Quantum account: https://quantum-computing.ibm.com/." + ] + } + ], + "metadata": { + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python 3", + "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.7.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tutorials/images/api_token.png b/tutorials/images/api_token.png new file mode 100644 index 000000000..48516d145 Binary files /dev/null and b/tutorials/images/api_token.png differ diff --git a/tutorials/images/ibmq_services.png b/tutorials/images/ibmq_services.png new file mode 100644 index 000000000..3461775ee Binary files /dev/null and b/tutorials/images/ibmq_services.png differ diff --git a/tutorials/images/main_function.png b/tutorials/images/main_function.png new file mode 100644 index 000000000..16335b579 Binary files /dev/null and b/tutorials/images/main_function.png differ diff --git a/tutorials/images/program_jobs.png b/tutorials/images/program_jobs.png new file mode 100644 index 000000000..d8c924cc1 Binary files /dev/null and b/tutorials/images/program_jobs.png differ diff --git a/tutorials/images/qva_loop.png b/tutorials/images/qva_loop.png new file mode 100644 index 000000000..5dc578e2e Binary files /dev/null and b/tutorials/images/qva_loop.png differ diff --git a/tutorials/images/runtime_api.png b/tutorials/images/runtime_api.png new file mode 100644 index 000000000..74e4d0c77 Binary files /dev/null and b/tutorials/images/runtime_api.png differ diff --git a/tutorials/images/runtime_programs.png b/tutorials/images/runtime_programs.png new file mode 100644 index 000000000..5facd9a52 Binary files /dev/null and b/tutorials/images/runtime_programs.png differ diff --git a/tutorials/images/sample_program.png b/tutorials/images/sample_program.png new file mode 100644 index 000000000..b2d3599f6 Binary files /dev/null and b/tutorials/images/sample_program.png differ diff --git a/tutorials/images/vqa_pre_runtime.png b/tutorials/images/vqa_pre_runtime.png new file mode 100644 index 000000000..5a17a86b3 Binary files /dev/null and b/tutorials/images/vqa_pre_runtime.png differ diff --git a/tutorials/images/vqa_with_runtime.png b/tutorials/images/vqa_with_runtime.png new file mode 100644 index 000000000..3506790b2 Binary files /dev/null and b/tutorials/images/vqa_with_runtime.png differ