Running Multiple Circuits on Hardware
This tutorial shows how a quantum circuit can be run on actual quantum hardware. This requires a valid IBM Quantum Token as well as a service-crn for available quantum backend instances. Please make sure you have sufficient time available to execute the code on the quantum hardware.
Import all Necessary Libraries
[1]:
from NoisyCircuits.QuantumCircuit import QuantumCircuit as nqc
from NoisyCircuits.utils.CreateNoiseModel import GetNoiseModel
from NoisyCircuits.RunOnHardware import RunOnHardware
import os
import numpy as np
import json
import matplotlib.pyplot as plt
2026-03-06 15:48:29,140 INFO util.py:154 -- Missing packages: ['ipywidgets']. Run `pip install -U ipywidgets`, then restart the notebook server for rich notebook output.
Define all Necessary Parameters
[ ]:
api_json = json.load(open(os.path.join(os.path.expanduser("~"), "ibm_api.json"), "r"))
token = api_json["apikey"] # Replace with your Token
service_crn = api_json["service-crn"] # Replace with your Service CRN
backend_name = "ibm_fez"
shots = 2048
verbose = False
jsonize = True
num_qubits = 2
num_trajectories = 500
qpu = "heron" # Only possible option for IBM backends at the moment
num_cores = 50
sim_backend = "pennylane" # Choose between "pennylane", "qulacs" and "qiskit"
Get the Noise Model
[3]:
noise_model = GetNoiseModel(backend_name, token, service_crn).get_noise_model()
Warning: Found relaxation time anomaly for qubit 72 with $T_2 \geq 2T_1$. Setting $T_2 = 2T_1$.
Build all Quantum Circuits
[4]:
circuit = nqc(num_qubits=num_qubits,
noise_model=noise_model,
num_cores=num_cores,
backend_qpu_type=qpu,
num_trajectories=num_trajectories,
sim_backend=sim_backend,
jsonize=jsonize,
verbose=verbose)
# List to store all probabilities from Pure State Simulation
probs_pure_list = []
# List to store all probabilities from MCWF Simulations
probs_sim_list = []
Successfully switched backend to pennylane.
2026-03-06 15:48:49,455 INFO worker.py:2007 -- Started a local Ray instance.
/Users/adam-ukj7r05xnu2fywx/miniconda3/envs/NoisyCircuits/lib/python3.10/site-packages/ray/_private/worker.py:2046: FutureWarning: Tip: In future versions of Ray, Ray will no longer override accelerator visible devices env var if num_gpus=0 or num_gpus=None (default). To enable this behavior and turn off this error message, set RAY_ACCEL_ENV_VAR_OVERRIDE_ON_ZERO=0
warnings.warn(
[5]:
hardware_runner = RunOnHardware(
token=token,
backend=backend_name,
shots=shots
)
qiskit_runtime_service._discover_account:WARNING:2026-03-06 15:48:50,211: Loading account with the given token. A saved account will not be used.
qiskit_runtime_service.__init__:WARNING:2026-03-06 15:48:53,034: Instance was not set at service instantiation. Free and trial plan instances will be prioritized. Based on the following filters: (tags: None, region: us-east, eu-de), and available plans: (open), the available account instances are: Open_Sys. If you need a specific instance set it explicitly either by using a saved account with a saved default instance or passing it in directly to QiskitRuntimeService().
qiskit_runtime_service.backends:WARNING:2026-03-06 15:48:53,036: Loading instance: Open_Sys, plan: open
Circuit 1: SWAP States
[6]:
circuit.refresh()
circuit.RY(1.4, 0)
circuit.RY(2.5, 1)
circuit.SWAP(0, 1)
circuit.draw_circuit(style="text")
┌───┐┌────┐┌──────────┐┌────┐┌────┐ ┌────┐ ┌────┐ ┌───────┐┌───┐
q_0: ┤ X ├┤ √X ├┤ Rz(-1.4) ├┤ √X ├┤ √X ├─■─┤ √X ├─■─┤ √X ├─■─┤ Rx(π) ├┤ X ├
├───┤├────┤├──────────┤├────┤├────┤ │ ├────┤ │ ├────┤ │ └───────┘└───┘
q_1: ┤ X ├┤ √X ├┤ Rz(-2.5) ├┤ √X ├┤ √X ├─■─┤ √X ├─■─┤ √X ├─■───────────────
└───┘└────┘└──────────┘└────┘└────┘ └────┘ └────┘
[7]:
hardware_runner.create_circuits(
circuit=circuit,
measure_qubits=list(range(num_qubits))
)
[8]:
probs_pure_list.append(circuit.run_pure_state(list(range(num_qubits))))
probs_sim_list.append(circuit.execute(list(range(num_qubits))))
Circuit 2: Parameterized Circuit
Set up a parameterized circuit with different set of parameters
[ ]:
parameter_set = [np.random.uniform(-2*np.pi, 2*np.pi, size=8) for _ in range(2)]
[2026-03-06 15:49:20,127 E 404821 405340] core_worker_process.cc:842: Failed to establish connection to the metrics exporter agent. Metrics will not be exported. Exporter agent status: RpcError: Running out of retries to initialize the metrics agent. rpc_code: 14
[10]:
for circuit_num, params in enumerate(parameter_set):
circuit.refresh()
circuit.H(0)
circuit.H(1)
for i in range(len(params)//2):
for j in range(num_qubits):
circuit.RY(params[2*i+j], j)
circuit.CZ(0, 1)
circuit.draw_circuit(style="text")
probs_pure_list.append(circuit.run_pure_state(list(range(num_qubits))))
probs_sim_list.append(circuit.execute(list(range(num_qubits))))
hardware_runner.create_circuits(circuit=circuit, measure_qubits=list(range(num_qubits)))
┌────┐┌─────────┐┌────┐┌───┐┌────┐ ┌────────────┐┌────┐ ┌───┐┌────┐»
q_0: ┤ √X ├┤ Rz(π/2) ├┤ √X ├┤ X ├┤ √X ├─┤ Rz(5.9209) ├┤ √X ├─■─┤ X ├┤ √X ├»
├────┤├─────────┤├────┤├───┤├────┤┌┴────────────┤├────┤ │ ├───┤├────┤»
q_1: ┤ √X ├┤ Rz(π/2) ├┤ √X ├┤ X ├┤ √X ├┤ Rz(-0.8332) ├┤ √X ├─■─┤ X ├┤ √X ├»
└────┘└─────────┘└────┘└───┘└────┘└─────────────┘└────┘ └───┘└────┘»
« ┌─────────────┐┌────┐ ┌───┐┌────┐ ┌────────────┐┌────┐ ┌───┐┌────┐»
«q_0: ┤ Rz(0.55698) ├┤ √X ├─■─┤ X ├┤ √X ├─┤ Rz(5.8255) ├┤ √X ├─■─┤ X ├┤ √X ├»
« └┬────────────┤├────┤ │ ├───┤├────┤┌┴────────────┤├────┤ │ ├───┤├────┤»
«q_1: ─┤ Rz(-2.851) ├┤ √X ├─■─┤ X ├┤ √X ├┤ Rz(0.22728) ├┤ √X ├─■─┤ X ├┤ √X ├»
« └────────────┘└────┘ └───┘└────┘└─────────────┘└────┘ └───┘└────┘»
« ┌────────────┐┌────┐
«q_0: ┤ Rz(5.6758) ├┤ √X ├─■─
« ├────────────┤├────┤ │
«q_1: ┤ Rz(4.3392) ├┤ √X ├─■─
« └────────────┘└────┘
┌────┐┌─────────┐┌────┐┌───┐┌────┐┌─────────────┐┌────┐ ┌───┐┌────┐»
q_0: ┤ √X ├┤ Rz(π/2) ├┤ √X ├┤ X ├┤ √X ├┤ Rz(-3.0417) ├┤ √X ├─■─┤ X ├┤ √X ├»
├────┤├─────────┤├────┤├───┤├────┤├─────────────┤├────┤ │ ├───┤├────┤»
q_1: ┤ √X ├┤ Rz(π/2) ├┤ √X ├┤ X ├┤ √X ├┤ Rz(-4.4452) ├┤ √X ├─■─┤ X ├┤ √X ├»
└────┘└─────────┘└────┘└───┘└────┘└─────────────┘└────┘ └───┘└────┘»
« ┌─────────────┐┌────┐ ┌───┐┌────┐┌────────────┐┌────┐ ┌───┐┌────┐»
«q_0: ┤ Rz(-2.3893) ├┤ √X ├─■─┤ X ├┤ √X ├┤ Rz(5.2782) ├┤ √X ├─■─┤ X ├┤ √X ├»
« ├─────────────┤├────┤ │ ├───┤├────┤├───────────┬┘├────┤ │ ├───┤├────┤»
«q_1: ┤ Rz(-4.5959) ├┤ √X ├─■─┤ X ├┤ √X ├┤ Rz(6.076) ├─┤ √X ├─■─┤ X ├┤ √X ├»
« └─────────────┘└────┘ └───┘└────┘└───────────┘ └────┘ └───┘└────┘»
« ┌────────────┐┌────┐
«q_0: ┤ Rz(-1.994) ├┤ √X ├─■─
« ├───────────┬┘├────┤ │
«q_1: ┤ Rz(-1.95) ├─┤ √X ├─■─
« └───────────┘ └────┘
Setup the Circuits for Submission
[11]:
hardware_runner.setup_circuits()
qiskit_runtime_service.backends:WARNING:2026-03-06 15:49:42,528: Using instance: Open_Sys, plan: open
qiskit_runtime_service.backends:WARNING:2026-03-06 15:49:43,350: Using instance: Open_Sys, plan: open
qiskit_runtime_service.backends:WARNING:2026-03-06 15:49:43,968: Using instance: Open_Sys, plan: open
Submit the Circuits
[12]:
job_id = hardware_runner.run()
qiskit_runtime_service.backends:WARNING:2026-03-06 15:49:45,335: Using instance: Open_Sys, plan: open
Job ID: d6lej2obfi7c73a2ceb0
Query Job Status
[14]:
hardware_runner.status()
[14]:
'DONE'
Job Cancellation
In the event the job hasn’t already been completed, they can be cancelled.
[ ]:
hardware_runner.cancel()
Get Results
[15]:
probs_hardware_list = hardware_runner.get_results()
Compare Results
To compare the results we use the Battacharyya Coefficient defined for discrete probability distributions by: \begin{equation} BC(p, q) = \sum_{i=1}^N \sqrt{p_i q_i} \end{equation}
[16]:
def battacharyya_coefficient(p, q):
return np.sum(np.sqrt(p * q))
[19]:
for i in range(len(probs_pure_list)):
print("Fidelity between Pure State Simulation and MCWF Simulation Results:\t", battacharyya_coefficient(probs_pure_list[i], probs_sim_list[i]))
print("Fidelity between Pure State Simulation and Hardware Results:\t", battacharyya_coefficient(probs_pure_list[i], probs_hardware_list[i]))
print("Fidelity between MCWF Simulation and Hardware Results:\t", battacharyya_coefficient(probs_sim_list[i], probs_hardware_list[i]))
print("----------------------------------------------------------------------------------------------")
Fidelity between Pure State Simulation and MCWF Simulation Results: 0.9964907327425298
Fidelity between Pure State Simulation and Hardware Results: 0.9999492692239413
Fidelity between MCWF Simulation and Hardware Results: 0.996015383159569
----------------------------------------------------------------------------------------------
Fidelity between Pure State Simulation and MCWF Simulation Results: 0.9958387556303563
Fidelity between Pure State Simulation and Hardware Results: 0.9944099073651047
Fidelity between MCWF Simulation and Hardware Results: 0.9994129921498147
----------------------------------------------------------------------------------------------
Fidelity between Pure State Simulation and MCWF Simulation Results: 0.9945292416842664
Fidelity between Pure State Simulation and Hardware Results: 0.9897188030740816
Fidelity between MCWF Simulation and Hardware Results: 0.9954703694328254
----------------------------------------------------------------------------------------------
Shutdown Circuit
[20]:
circuit.shutdown()
Download this Notebook - /examples/run_multiple_on_hardware.ipynb