{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "552b1077",
      "metadata": {},
      "source": [
        "---\n",
        "title: Run your first circuit on hardware\n",
        "description: Get started using Qiskit with IBM Quantum hardware in this Hello World example\n",
        "---\n",
        "\n",
        "# Run your first circuit on hardware\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7cc19a86-a234-4220-bb4f-d66d3834e0c3",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "{/*\n",
        "  DO NOT EDIT THIS CELL!!!\n",
        "  This cell's content is generated automatically by a script. Anything you add\n",
        "  here will be removed next time the notebook is run. To add new content, create\n",
        "  a new cell before or after this one.\n",
        "  */}\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Package versions\">\n",
        "    The code on this page was developed using the following requirements.\n",
        "    We recommend using these versions or newer.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.4.0\n",
        "    qiskit-ibm-runtime~=0.46.1\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1a3c196d-545d-417f-b34e-fa422aa9a394",
      "metadata": {},
      "source": [
        "This example contains two parts. You will first create a simple \"Hello world\" quantum program and run it on a quantum processing unit (QPU).  Because actual quantum research requires much more robust programs, in the second section ([Scale to large numbers of qubits](#scale-to-large-numbers-of-qubits)), you will scale the simple program up to utility level.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7b65f7e0",
      "metadata": {},
      "source": [
        "## Install and authenticate\n",
        "\n",
        "1. If you have not already installed Qiskit, find instructions in the [Quickstart](/docs/guides/quick-start) guide.\n",
        "\n",
        "   * Install Qiskit Runtime to run jobs on quantum hardware:\n",
        "\n",
        "     ```bash\n",
        "     pip install qiskit-ibm-runtime\n",
        "     ```\n",
        "\n",
        "   * Set up an environment to run Jupyter notebooks locally:\n",
        "\n",
        "     ```bash\n",
        "     pip install jupyter\n",
        "     ```\n",
        "\n",
        "2. Set up your authentication for access to quantum hardware through the free [Open Plan](/docs/guides/plans-overview#open-plan).\n",
        "\n",
        "   (If you were emailed an invitation to join an account, follow the [steps for invited users](/docs/guides/cloud-setup-invited) instead.)\n",
        "\n",
        "   * Go to [IBM Quantum Platform](/) to log in or create an account.\n",
        "     <Admonition type=\"note\" title=\"Important\">\n",
        "       If you connect through a proxy server, you must use Qiskit Runtime v0.44.0 or later.\n",
        "     </Admonition>\n",
        "\n",
        "   * Generate your API key (also called an *API token*) on the [dashboard](/), then copy it to a secure location.\n",
        "\n",
        "   * Go to the [Instances](/instances) page and find the instance you want to use. Hover over its CRN and click to copy it.\n",
        "\n",
        "   * Save your credentials locally with this code:\n",
        "\n",
        "     ```python\n",
        "     from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "     QiskitRuntimeService.save_account(\n",
        "         token=\"<your-api-key>\", # Use the 44-character API_KEY you created and saved from the IBM Quantum Platform Home dashboard\n",
        "         instance=\"<CRN>\", # Optional\n",
        "     )\n",
        "     ```\n",
        "\n",
        "3. Now you can use this Python code any time you want to authenticate to the Qiskit Runtime Service:\n",
        "   ```python\n",
        "   from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "   # Run every time you need the service\n",
        "   service = QiskitRuntimeService()\n",
        "   ```\n",
        "\n",
        "<Admonition type=\"info\" title=\"Not using a trusted Python environment?\">\n",
        "  If you are using a public computer or other unsecured environment, follow the [manual authentication instructions](/docs/guides/cloud-setup-untrusted) instead to keep your authentication credentials safe.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "80471a0a",
      "metadata": {},
      "source": [
        "## Create and run a simple quantum program\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "85fe979e",
      "metadata": {
        "raw_mimetype": "text/restructuredtext"
      },
      "source": [
        "The four steps to writing a quantum program using Qiskit patterns are:\n",
        "\n",
        "1. Map the problem to a quantum-native format.\n",
        "\n",
        "2. Optimize the circuits and operators.\n",
        "\n",
        "3. Execute using a quantum primitive function.\n",
        "\n",
        "4. Analyze the results.\n",
        "\n",
        "### Step 1. Map the problem to a quantum-native format\n",
        "\n",
        "In a quantum program, *quantum circuits* are the native format in which to represent quantum instructions, and *operators* represent the observables to be measured. When creating a circuit, you'll usually create a new [`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#quantumcircuit-class) object, then add instructions to it in sequence.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "21f7a26c",
      "metadata": {},
      "source": [
        "The following code cell creates a circuit that produces a *Bell state,* which is a state wherein two qubits are fully entangled with each other.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Note: bit ordering\">\n",
        "  The Qiskit SDK uses the LSb 0 bit numbering where the $n^{th}$ digit has value $1 \\ll n$ or $2^n$. For more details, see the [Bit-ordering in the Qiskit SDK](/docs/guides/bit-ordering) topic.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "930ca3b6",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/hello-world/extracted-outputs/930ca3b6-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit_ibm_runtime import EstimatorOptions\n",
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "from matplotlib import pyplot as plt\n",
        "# Uncomment the next line if you want to use a simulator:\n",
        "# from qiskit_ibm_runtime.fake_provider import FakeBelemV2\n",
        "\n",
        "\n",
        "# Create a new circuit with two qubits\n",
        "qc = QuantumCircuit(2)\n",
        "\n",
        "# Add a Hadamard gate to qubit 0\n",
        "qc.h(0)\n",
        "\n",
        "# Perform a controlled-X gate on qubit 1, controlled by qubit 0\n",
        "qc.cx(0, 1)\n",
        "\n",
        "# Return a drawing of the circuit using MatPlotLib (\"mpl\").\n",
        "# These guides are written by using Jupyter notebooks, which\n",
        "# display the output of the last line of each cell.\n",
        "# If you're running this in a script, use `print(qc.draw())` to\n",
        "# print a text drawing.\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0c957de9",
      "metadata": {
        "raw_mimetype": "text/restructuredtext"
      },
      "source": [
        "See [`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#quantumcircuit-class) in the documentation for all available operations.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f3ef4248-7938-44c1-85f1-edc997f0edcd",
      "metadata": {},
      "source": [
        "When creating quantum circuits, you must also consider what type of data you want returned after execution. Qiskit provides two ways to return data: you can obtain sampling output for a set of qubits you choose to measure, or you can obtain the expectation value of an observable. Prepare your workload to measure your circuit in one of these two ways with Qiskit primitives (explained in detail in [Step 3](#step-3-execute-using-the-quantum-primitives)).\n",
        "\n",
        "This example measures expectation values by using the `qiskit.quantum_info` submodule, which is specified by using operators (mathematical objects used to represent an action or process that changes a quantum state). The following code cell creates six two-qubit Pauli operators: `IZ`, `IX`, `ZI`, `XI`, `ZZ`, and `XX`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "c57b261c-b757-4432-beab-61b526c98a41",
      "metadata": {
        "tags": []
      },
      "outputs": [],
      "source": [
        "# Set up six different observables.\n",
        "\n",
        "observables_labels = [\"IZ\", \"IX\", \"ZI\", \"XI\", \"ZZ\", \"XX\"]\n",
        "observables = [SparsePauliOp(label) for label in observables_labels]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "47150779",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Operator Notation\">\n",
        "  Here, something like the `ZZ` operator is a shorthand for the tensor product $Z\\otimes Z$, which means measuring Z on qubit 1 and Z on qubit 0 together, and obtaining information about the correlation between qubit 1 and qubit 0. Expectation values like this are also typically written as $\\langle Z_1 Z_0 \\rangle$.\n",
        "\n",
        "  If the state is entangled, then the measurement of $\\langle Z_1 Z_0 \\rangle$ should be different from the measurement of $\\langle I_1 \\otimes Z_0 \\rangle \\langle Z_1 \\otimes I_0 \\rangle$. For the specific entangled state created by our circuit described above, the measurement of $\\langle Z_1 Z_0 \\rangle$ should be 1 and the measurement of $\\langle I_1 \\otimes Z_0 \\rangle \\langle Z_1 \\otimes I_0 \\rangle$ should be zero.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "83bf9151-3bc9-40d2-8615-31570238b08e",
      "metadata": {},
      "source": [
        "<span id=\"optimize\" />\n",
        "\n",
        "### Step 2. Optimize the circuits and operators\n",
        "\n",
        "When executing circuits on a device, it is important to optimize the set of instructions that the circuit contains and minimize the overall depth (roughly the number of instructions) of the circuit. This ensures that you obtain the best results possible by reducing the effects of error and noise. Additionally, the circuit's instructions must conform to a backend device's [Instruction Set Architecture (ISA)](/docs/guides/transpile#instruction-set-architecture) and must consider the device's basis gates and qubit connectivity.\n",
        "\n",
        "The following code instantiates a real device to submit a job to and transforms the circuit and observables to match that backend's ISA. It requires that you have already [saved your credentials](/docs/guides/cloud-setup)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "9a901271",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/hello-world/extracted-outputs/9a901271-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "service = QiskitRuntimeService()\n",
        "\n",
        "backend = service.least_busy(simulator=False, operational=True)\n",
        "\n",
        "# Convert to an ISA circuit and layout-mapped observables.\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_circuit = pm.run(qc)\n",
        "\n",
        "isa_circuit.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9acac1d4",
      "metadata": {},
      "source": [
        "### Step 3. Execute using the quantum primitives\n",
        "\n",
        "Quantum computers can produce random results, so you usually collect a sample of the outputs by running the circuit many times. You can estimate the value of the observable by using the `Estimator` class. `Estimator` is one of two [primitives](/docs/guides/get-started-with-estimator); the other is `Sampler`, which can be used to get data from a quantum computer.  These objects possess a `run()` method that executes the selection of circuits, observables, and parameters (if applicable), using a [primitive unified bloc (PUB)](/docs/guides/get-started-with-sampler).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "62c4ca44",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> Job ID: d8286mfoha1c73bl8hrg\n"
          ]
        }
      ],
      "source": [
        "# Construct the Estimator instance.\n",
        "\n",
        "estimator = Estimator(mode=backend)\n",
        "estimator.options.resilience_level = 1\n",
        "estimator.options.default_shots = 5000\n",
        "\n",
        "mapped_observables = [\n",
        "    observable.apply_layout(isa_circuit.layout) for observable in observables\n",
        "]\n",
        "\n",
        "# One pub, with one circuit to run against five different observables.\n",
        "job = estimator.run([(isa_circuit, mapped_observables)])\n",
        "\n",
        "# Use the job ID to retrieve your job data later\n",
        "print(f\">>> Job ID: {job.job_id()}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "47479e76",
      "metadata": {},
      "source": [
        "After a job is submitted, you can wait until either the job is completed within your current python instance, or use the `job_id` to retrieve the data at a later time.  (See the [section on retrieving jobs](/docs/guides/monitor-job#retrieve-job-results-at-a-later-time) for details.)\n",
        "\n",
        "After the job completes, examine its output through the job's `result()` attribute.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "792d2f01",
      "metadata": {},
      "outputs": [],
      "source": [
        "# This is the result of the entire submission.  You submitted one Pub,\n",
        "# so this contains one inner result (and some metadata of its own).\n",
        "job_result = job.result()\n",
        "\n",
        "# This is the result from our single pub, which had six observables,\n",
        "# so contains information on all six.\n",
        "pub_result = job.result()[0]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "48317a25",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Alternative: run the example using a simulator\">\n",
        "  When you run your quantum program on a real device, your workload must wait in a queue before it runs. To save time, you can instead use the following code to run this small workload on the [`fake_provider`](../api/qiskit-ibm-runtime/fake-provider) with the Qiskit Runtime local testing mode. Note that this is only possible for a small circuit. When you scale up in the next section, you will need to use a real device.\n",
        "\n",
        "  ```python\n",
        "\n",
        "  # Use the following code instead if you want to run on a simulator:\n",
        "\n",
        "  from qiskit_ibm_runtime.fake_provider import FakeBelemV2\n",
        "  backend = FakeBelemV2()\n",
        "  estimator = Estimator(backend)\n",
        "\n",
        "  # Convert to an ISA circuit and layout-mapped observables.\n",
        "\n",
        "  pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "  isa_circuit = pm.run(qc)\n",
        "  mapped_observables = [\n",
        "      observable.apply_layout(isa_circuit.layout) for observable in observables\n",
        "  ]\n",
        "\n",
        "  job = estimator.run([(isa_circuit, mapped_observables)])\n",
        "  result = job.result()\n",
        "\n",
        "  # This is the result of the entire submission.  You submitted one Pub,\n",
        "  # so this contains one inner result (and some metadata of its own).\n",
        "\n",
        "  job_result = job.result()\n",
        "\n",
        "  # This is the result from our single pub, which had five observables,\n",
        "  # so contains information on all five.\n",
        "\n",
        "  pub_result = job.result()[0]\n",
        "  ```\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d200d1f8",
      "metadata": {},
      "source": [
        "### Step 4. Analyze the results\n",
        "\n",
        "The analyze step is typically where you might post-process your results using, for example, measurement error mitigation or zero noise extrapolation (ZNE). You might feed these results into another workflow for further analysis or prepare a plot of the key values and data. In general, this step is specific to your problem.  For this example, plot each of the expectation values that were measured for our circuit.\n",
        "\n",
        "The expectation values and standard deviations for the observables you specified to Estimator are accessed through the job result's `PubResult.data.evs` and `PubResult.data.stds` attributes. To obtain the results from Sampler, use the `PubResult.data.meas.get_counts()` function, which will return a `dict` of measurements in the form of bitstrings as keys and counts as their corresponding values. For more information, see the [Sampler quickstart](/docs/guides/get-started-with-sampler) guide.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "87143fcc",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/hello-world/extracted-outputs/87143fcc-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Plot the result\n",
        "\n",
        "values = pub_result.data.evs\n",
        "\n",
        "errors = pub_result.data.stds\n",
        "\n",
        "# plotting graph\n",
        "plt.plot(observables_labels, values, \"-o\")\n",
        "plt.xlabel(\"Observables\")\n",
        "plt.ylabel(\"Values\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e6a9ba84",
      "metadata": {},
      "source": [
        "Notice that for qubits 0 and 1, the independent expectation values of both X and Z are 0, while the correlations (`XX` and `ZZ`) are 1. This is a hallmark of quantum entanglement.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0bc582d8",
      "metadata": {},
      "source": [
        "## Scale to large numbers of qubits\n",
        "\n",
        "In quantum computing, utility-scale work is crucial for making progress in the field. Such work requires computations to be done on a much larger scale; working with circuits that might use over 100 qubits and over 1000 gates. This example demonstrates how you can accomplish utility-scale work on IBM® QPUs by creating and analyzing a 100-qubit GHZ state.  It uses the Qiskit patterns workflow and ends by measuring the expectation value $\\langle Z_0 Z_i \\rangle $ for each qubit.\n",
        "\n",
        "### Step 1. Map the problem\n",
        "\n",
        "Write a function that returns a `QuantumCircuit` that prepares an $n$-qubit GHZ state (essentially an extended Bell state), then use that function to prepare a 100-qubit GHZ state and collect the observables to be measured.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "2ac02692",
      "metadata": {},
      "outputs": [],
      "source": [
        "def get_qc_for_n_qubit_GHZ_state(n: int) -> QuantumCircuit:\n",
        "    \"\"\"This function will create a qiskit.QuantumCircuit (qc) for an n-qubit GHZ state.\n",
        "\n",
        "    Args:\n",
        "        n (int): Number of qubits in the n-qubit GHZ state\n",
        "\n",
        "    Returns:\n",
        "        QuantumCircuit: Quantum circuit that generate the n-qubit GHZ state, assuming all qubits start in the 0 state\n",
        "    \"\"\"\n",
        "    if isinstance(n, int) and n >= 2:\n",
        "        qc = QuantumCircuit(n)\n",
        "        qc.h(0)\n",
        "        for i in range(n - 1):\n",
        "            qc.cx(i, i + 1)\n",
        "    else:\n",
        "        raise Exception(\"n is not a valid input\")\n",
        "    return qc\n",
        "\n",
        "\n",
        "# Create a new circuit with 100 qubits in the GHZ state\n",
        "n = 100\n",
        "qc = get_qc_for_n_qubit_GHZ_state(n)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5b3d0d74",
      "metadata": {},
      "source": [
        "Next, map to the operators of interest. This example uses the `ZZ` operators between qubits to examine the behavior as they get farther apart.  Increasingly inaccurate (corrupted) expectation values between distant qubits would reveal the level of noise present.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "863a4ec9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# ZZII...II, ZIZI...II, ... , ZIII...IZ\n",
        "operator_strings = [\n",
        "    \"Z\" + \"I\" * i + \"Z\" + \"I\" * (n - 2 - i) for i in range(n - 1)\n",
        "]\n",
        "\n",
        "operators = [SparsePauliOp(operator) for operator in operator_strings]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a0b462ce",
      "metadata": {},
      "source": [
        "### Step 2. Optimize the problem for execution on quantum hardware\n",
        "\n",
        "The following code transforms the circuit and observables to match the backend's ISA. It requires that you have already [saved your credentials](/docs/guides/cloud-setup)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "428f05e7",
      "metadata": {},
      "outputs": [],
      "source": [
        "service = QiskitRuntimeService()\n",
        "\n",
        "backend = service.least_busy(\n",
        "    simulator=False, operational=True, min_num_qubits=100\n",
        ")\n",
        "pm = generate_preset_pass_manager(optimization_level=1, backend=backend)\n",
        "\n",
        "isa_circuit = pm.run(qc)\n",
        "isa_operators_list = [op.apply_layout(isa_circuit.layout) for op in operators]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2d2b5065",
      "metadata": {},
      "source": [
        "### Step 3. Execute on hardware\n",
        "\n",
        "Submit the job and enable error suppression by using a technique to reduce errors called [dynamical decoupling](/docs/api/qiskit-ibm-runtime/options-dynamical-decoupling-options). The resilience level specifies how much resilience to build against errors. Higher levels generate more accurate results, at the expense of longer processing times.  For further explanation of the options set in the following code, see [Configure error mitigation for Qiskit Runtime](/docs/guides/error-mitigation-and-suppression-techniques).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "3aaa5025",
      "metadata": {},
      "outputs": [],
      "source": [
        "options = EstimatorOptions()\n",
        "options.resilience_level = 1\n",
        "options.dynamical_decoupling.enable = True\n",
        "options.dynamical_decoupling.sequence_type = \"XY4\"\n",
        "\n",
        "# Create an Estimator object\n",
        "estimator = Estimator(backend, options=options)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "b4c3d3e7-0a0f-4023-8948-1082e225f46c",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "d828aeo0bvlc73d1vs20\n"
          ]
        }
      ],
      "source": [
        "# Submit the circuit to Estimator\n",
        "job = estimator.run([(isa_circuit, isa_operators_list)])\n",
        "job_id = job.job_id()\n",
        "print(job_id)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0bc64091",
      "metadata": {},
      "source": [
        "### Step 4. Post-process results\n",
        "\n",
        "After the job completes, plot the results and notice that $\\langle Z_0 Z_i \\rangle$ decreases with increasing $i$, even though in an ideal simulation all $\\langle Z_0 Z_i \\rangle$ should be 1.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "de91ebd0",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/hello-world/extracted-outputs/de91ebd0-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# data\n",
        "data = list(range(1, len(operators) + 1))  # Distance between the Z operators\n",
        "result = job.result()[0]\n",
        "values = result.data.evs  # Expectation value at each Z operator.\n",
        "values = [\n",
        "    v / values[0] for v in values\n",
        "]  # Normalize the expectation values to evaluate how they decay with distance.\n",
        "\n",
        "# plotting graph\n",
        "plt.plot(data, values, marker=\"o\", label=\"100-qubit GHZ state\")\n",
        "plt.xlabel(\"Distance between qubits $i$\")\n",
        "plt.ylabel(r\"$\\langle Z_i Z_0 \\rangle / \\langle Z_1 Z_0 \\rangle $\")\n",
        "plt.legend()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0afc307c",
      "metadata": {},
      "source": [
        "The previous plot shows that as the distance between qubits increases, the signal decays because of the presence of noise.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e7c24c81",
      "metadata": {},
      "source": [
        "## Next steps\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recommendations\">\n",
        "  * Try one of these tutorials:\n",
        "    * [Ground-state energy estimation of the Heisenberg chain with VQE](/docs/tutorials/spin-chain-vqe)\n",
        "    * Solve optimization problems using [QAOA](/docs/tutorials/quantum-approximate-optimization-algorithm)\n",
        "    * Train [quantum kernel](/docs/tutorials/quantum-kernel-training) models for machine learning tasks\n",
        "  * Find detailed installation instructions in the [Install Qiskit](/docs/guides/install-qiskit) guide.\n",
        "  * If you prefer not to install Qiskit locally, read about options to use Qiskit in an [online development environment](/docs/guides/online-lab-environments).\n",
        "  * To save multiple account credentials or to specify other account options, see detailed instructions in the [Save your login credentials](/docs/guides/save-credentials#save-your-access-credentials) guide.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "celltoolbar": "Raw Cell Format",
    "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"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "state": {},
        "version_major": 2,
        "version_minor": 0
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}