Skip to main contentIBM Quantum Documentation

Hello world

This Hello world example creates a simple quantum program and runs it on a quantum system. Begin with following the Install and set up instructions if you haven't already, including the steps to Set up to use IBM Quantum™ Platform.

We recommend that you use the Jupyter(opens in a new tab) development environment to interact with quantum computers. Be sure to install the recommended extra visualization support (pip install qiskit[visualization]), and note that zsh users need to put 'qiskit[visualization]' in single quotes.

To learn about quantum computing in general, check out the Basics of quantum information course(opens in a new tab) in IBM Quantum Learning.

The four steps to writing a quantum program are

  1. Map the problem to a quantum-native format

  2. Optimize the circuits and operators

  3. Execute using a quantum primitive function

  4. Analyze the results

Step 1. Map the problem to a quantum-native format

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 object, then add instructions to it in sequence.

The following code cell creates a circuit that produces a Bell state, which is a specific two-qubit entangled state.

Note: bit ordering

The Qiskit SDK uses the LSb 0 bit numbering where the nthn^{th} digit has value 1n1 \ll n or 2n2^n. Because we usually write numbers on paper with the most significant digits to the left and the least significant digits to the right (in the Hindu-Arabic system used in most of the world), this has the consequence that the bits are labeled with indices increasing from right to left. This LSb 0 convention makes mathematics easier and is the most commonly used for modern digital electronics, although the opposite convention MSb 0 is also found in some domains. Converting the ithi^{th} index between LSb 0 and MSb 0 conventions on an nn-bit register is as simple as ini1i \rightarrow n-i-1. This differs across authors and software packages, so be aware! For more details, see the Bit-ordering in the Qiskit SDK topic.

[2] :
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator
# Create a new circuit with two qubits
qc = QuantumCircuit(2)
# Add a Hadamard gate to qubit 0
# Perform a controlled-X gate on qubit 1, controlled by qubit 0, 1)
# Return a drawing of the circuit using MatPlotLib ("mpl"). This is the
# last line of the cell, so the drawing appears in the cell output.
# Remove the "mpl" argument to get a text drawing.


<Figure size 287.294x200.667 with 1 Axes>

See QuantumCircuit in the documentation for all available operations.

The following code cell uses the quantum_info package to create six two-qubit Pauli operators. The ZZ operator means Z on qubit 0 and Z on qubit 1. If the state is entangled, then the correlation between qubit 0 and qubit 1 is one.

[3] :
# Set up six different observables.
observables_labels = ["ZZ", "ZI", "IZ", "XX", "XI"]
observables = [SparsePauliOp(label) for label in observables_labels]

To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as instruction set architecture (ISA) circuits and observables) before being submitted to the Qiskit Runtime primitives. See the transpilation documentation for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations. Consequently, transpilation options referring to those tasks will no longer have any effect. By default, all primitives except Sampler V2 still optimize the input circuits. To bypass all optimization, set optimization_level=0.

Exception: When you initialize the Qiskit Runtime Service with the Q-CTRL channel strategy (example below), abstract circuits are still supported.

service = QiskitRuntimeService(channel="ibm_cloud", channel_strategy="q-ctrl")

Step 2. Optimize the circuits and operators

Even though the circuit and operators for this example are quite simple, we still need to convert its instructions into those of a backend device's Instruction Set Architecture (ISA). This ensures the circuit complies with the constraints of a device (namely its native basis gates and qubit connectivity).

[5] :
# If you did not previously save your credentials, use the following line instead:
# service = QiskitRuntimeService(channel="ibm_quantum", token="<MY_IBM_QUANTUM_TOKEN>")
service = QiskitRuntimeService()
# Use the following code instead if you want to run on a simulator:
# from qiskit_ibm_runtime.fake_provider import FakeCairoV2
# backend = FakeCairoV2()
# Run on the least-busy backend you have access to
backend = service.least_busy(simulator=False, operational=True)
# Convert to an ISA circuit and layout-mapped observables.
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit =
isa_circuit.draw('mpl', idle_wires=False)


<Figure size 506.997x200.667 with 1 Axes>

Step 3. Execute using a quantum primitive function

Quantum computers can produce random results, so you'll often want to collect a sample of the outputs by running the circuit many times. You can estimate the value of the observable using the Estimator class. Estimator is one of our two primitives; 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 what's known as a primitive unified bloc (PUB).

[3] :
# Construct the Estimator instance we want to use.
estimator = Estimator(backend)
estimator.options.resilience_level = 1
estimator.options.default_shots = 5000
observables = [
    observable.apply_layout(isa_circuit.layout) for observable in observables
# One pub, with one circuit to run against five different observables.
job =[(isa_circuit, observables)])
# This is the result of the entire submission.  We submitted one Pub,
# so this contains one inner result (and some metadata of its own).
job_result = job.result()
# This is the result from our single pub, which had five observables,
# so contains information on all five.
pub_result = job.result()[0]


qiskit_runtime_service.__init__:INFO:2024-03-11 20:15:06,834: Default instance: ibm-q-internal/deployed/default
base_primitive._run:INFO:2024-03-11 20:15:30,536: Submitting job using options {'options': {'default_shots': 5000}, 'version': 2, 'support_qiskit': True, 'resilience_level': 1} 20:15:30,537: Instance selected: ibm-q-internal/live-data/live-data-demo

Step 4. Analyze the results

You might need to run pip install matplotlib if you do not already have it installed.

The values property is a list of expectation values for each of the observables we provided.

[4] :
# Plot the result
from matplotlib import pyplot as plt
data = observables_labels
values =
errors =
plt.errorbar(observables_labels, values, yerr=errors, fmt="o")


<ErrorbarContainer object of 3 artists>
<Figure size 640x480 with 1 Axes>

Here we see that for qubits 0 and 1, the independent values of both X and Z are 0, while the correlations are 1. This is a hallmark of quantum entanglement.

Next steps

Was this page helpful?
Report a bug or request content on GitHub.