{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Example: QAOA as QiskitPattern\n", "\n", "This tutorial will be demonstation of creating QAOA as QiskitPattern as well as migration guide on how you can replicate IBM Quantum QAOA custom runtime program.\n", "\n", "Let's first get information on what is QAOA runtime program and what inputs and outputs it has. We will not be implementing full set of input/outputs, but we will cover most important ones. Later on we can recover full functionality if needed.\n", "\n", "**Description**: Qiskit Runtime QAOA program.\n", "\n", "\n", "**Inputs**:\n", "\n", "| name | type | description |\n", "| ---- | ---- | ----------- |\n", "|initial_point|[array,string]|Initial parameters of the ansatz. Can be an array or the string ``'random'`` to choose random initial parameters. The type must be numpy.ndarray or str.|\n", "|operator|object|The cost Hamiltonian, consisting of Pauli I and Z operators, whose smallest eigenvalue we're trying to find. The type must be a PauliSumOp.|\n", "|method|str|The classical optimizer used to update the parameters in each iteration. Per default, COBYLA|\n", "|ansatz|QuantumCircuit|Ansatz for optimization|\n", "\n", "**Return values**\n", "\n", "| name | type | description |\n", "| ---- | ---- | ----------- |\n", "|optimal_point|array|The optimal parameter values found during the optimization.|\n", "|optimal_value|number|The smallest value found during the optimization. Equal to the ``eigenvalue`` attribute.|\n", "\n", "We will also add optional `QiskitRuntimeService` as an argument to use that to access real devices.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With that information we can start drafting our pattern implementation in `qaoa.py` file.\n", "\n", "What our pattern should do:\n", "\n", "1. parse input arguments\n", "2. create run_qaoa function that accepts estimator instance, creates VQE and runs calculation\n", "3. decide which sampler to use and run vqe\n", " - if runtime service was passed then create a session and run `run_qaoa` function\n", " - if runtime service was not passed then use stantard qiskit sampler\n", "4. save results from qaoa\n", "\n", "Roughly our QAOA pattern will look like this. Full code can be found in [qaoa.py](./source_files/qaoa/qaoa.py) file.\n", "\n", "```python\n", "# qaoa.py\n", "\n", "import ...\n", "\n", "def run_qaoa(\n", " ansatz: QuantumCircuit,\n", " estimator: BaseEstimator,\n", " operator: PauliSumOp,\n", " initial_point: np.array,\n", " method: str\n", "):\n", " return minimize(cost_func, initial_point, args=(ansatz, operator, estimator), method=method)\n", "\n", "\n", "arguments = get_arguments()\n", "service = arguments.get(\"service\")\n", "operator = arguments.get(\"operator\")\n", "initial_point = arguments.get(\"initial_point\")\n", "ansatz = arguments.get(\"ansatz\", 1)\n", "...\n", "if service is not None:\n", " # if we have service we need to open a session and create sampler\n", " service = arguments.get(\"service\") \n", " backend = arguments.get(\"backend\", \"ibmq_qasm_simulator\")\n", " with Session(service=service, backend=backend) as session:\n", " estimator = Estimator(session=session, options=options)\n", "else:\n", " # if we do not have a service let's use standart local sampler\n", " estimator = QiskitEstimator()\n", "\n", "result = run_qaoa(ansatz, estimator, operator, initial_point, \"COBYLA\")\n", " \n", "save_result({\n", " \"optimal_point\": result.x.tolist(),\n", " \"optimal_value\": result.fun\n", "})\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "At this point we have our pattern implemented. Now we need to actually run it. But before let's prepare input arguments from our QAOA pattern." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
┌─────────────┐ ┌──────────────┐ ┌──────────────┐\n", "q_0: ┤ U3(π/2,0,π) ├─■──────────────────────────────■──────────────────────────────■──────────────────────────────■─────────────┤ Rx(2.0*β[0]) ├─■──────────────■──────────────────────────────■──────────────────────────────■─────────────┤ Rx(2.0*β[1]) ├\n", " ├─────────────┤ │ZZ(2.0*γ[0]) ┌──────────────┐ │ │ │ └──────────────┘ │ZZ(2.0*γ[1]) │ ┌──────────────┐ │ │ └──────────────┘\n", "q_1: ┤ U3(π/2,0,π) ├─■─────────────┤ Rx(2.0*β[0]) ├─┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────■──────────────┼─────────────┤ Rx(2.0*β[1]) ├─┼──────────────────────────────┼─────────────────────────────\n", " ├─────────────┤ └──────────────┘ │ZZ(2.0*γ[0]) ┌──────────────┐ │ │ │ZZ(2.0*γ[1]) ├──────────────┤ │ │ \n", "q_2: ┤ U3(π/2,0,π) ├────────────────────────────────■─────────────┤ Rx(2.0*β[0]) ├─┼──────────────────────────────┼─────────────────────────────────────────────■─────────────┤ Rx(2.0*β[1]) ├─┼──────────────────────────────┼─────────────────────────────\n", " ├─────────────┤ └──────────────┘ │ZZ(2.0*γ[0]) ┌──────────────┐ │ └──────────────┘ │ZZ(2.0*γ[1]) ┌──────────────┐ │ \n", "q_3: ┤ U3(π/2,0,π) ├───────────────────────────────────────────────────────────────■─────────────┤ Rx(2.0*β[0]) ├─┼────────────────────────────────────────────────────────────────────────────■─────────────┤ Rx(2.0*β[1]) ├─┼─────────────────────────────\n", " ├─────────────┤ └──────────────┘ │ZZ(2.0*γ[0]) ┌──────────────┐ └──────────────┘ │ZZ(2.0*γ[1]) ┌──────────────┐\n", "q_4: ┤ U3(π/2,0,π) ├──────────────────────────────────────────────────────────────────────────────────────────────■─────────────┤ Rx(2.0*β[0]) ├──────────────────────────────────────────────────────────────────────────────■─────────────┤ Rx(2.0*β[1]) ├\n", " └─────────────┘ └──────────────┘ └──────────────┘" ], "text/plain": [ " ┌─────────────┐ ┌──────────────┐ ┌──────────────┐\n", "q_0: ┤ U3(π/2,0,π) ├─■──────────────────────────────■──────────────────────────────■──────────────────────────────■─────────────┤ Rx(2.0*β[0]) ├─■──────────────■──────────────────────────────■──────────────────────────────■─────────────┤ Rx(2.0*β[1]) ├\n", " ├─────────────┤ │ZZ(2.0*γ[0]) ┌──────────────┐ │ │ │ └──────────────┘ │ZZ(2.0*γ[1]) │ ┌──────────────┐ │ │ └──────────────┘\n", "q_1: ┤ U3(π/2,0,π) ├─■─────────────┤ Rx(2.0*β[0]) ├─┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────■──────────────┼─────────────┤ Rx(2.0*β[1]) ├─┼──────────────────────────────┼─────────────────────────────\n", " ├─────────────┤ └──────────────┘ │ZZ(2.0*γ[0]) ┌──────────────┐ │ │ │ZZ(2.0*γ[1]) ├──────────────┤ │ │ \n", "q_2: ┤ U3(π/2,0,π) ├────────────────────────────────■─────────────┤ Rx(2.0*β[0]) ├─┼──────────────────────────────┼─────────────────────────────────────────────■─────────────┤ Rx(2.0*β[1]) ├─┼──────────────────────────────┼─────────────────────────────\n", " ├─────────────┤ └──────────────┘ │ZZ(2.0*γ[0]) ┌──────────────┐ │ └──────────────┘ │ZZ(2.0*γ[1]) ┌──────────────┐ │ \n", "q_3: ┤ U3(π/2,0,π) ├───────────────────────────────────────────────────────────────■─────────────┤ Rx(2.0*β[0]) ├─┼────────────────────────────────────────────────────────────────────────────■─────────────┤ Rx(2.0*β[1]) ├─┼─────────────────────────────\n", " ├─────────────┤ └──────────────┘ │ZZ(2.0*γ[0]) ┌──────────────┐ └──────────────┘ │ZZ(2.0*γ[1]) ┌──────────────┐\n", "q_4: ┤ U3(π/2,0,π) ├──────────────────────────────────────────────────────────────────────────────────────────────■─────────────┤ Rx(2.0*β[0]) ├──────────────────────────────────────────────────────────────────────────────■─────────────┤ Rx(2.0*β[1]) ├\n", " └─────────────┘ └──────────────┘ └──────────────┘" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "\n", "from qiskit.circuit.library import QAOAAnsatz\n", "from qiskit.quantum_info import SparsePauliOp\n", "\n", "from qiskit_ibm_runtime import QiskitRuntimeService\n", "\n", "\n", "operator = SparsePauliOp.from_list(\n", " [(\"IIIZZ\", 1), (\"IIZIZ\", 1), (\"IZIIZ\", 1), (\"ZIIIZ\", 1)]\n", ")\n", "ansatz = QAOAAnsatz(operator, reps=2)\n", "ansatz = ansatz.decompose(reps=3)\n", "ansatz.draw(fold=-1)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'initial_point': None,\n", " 'ansatz':