Débuter avec les primitives
La version bêta d'un nouveau modèle d'exécution est désormais disponible. Le modèle d'exécution dirigée offre plus de flexibilité pour personnaliser ton workflow d'atténuation des erreurs. Consulte le guide Modèle d'exécution dirigée pour plus d'informations.
Bien que cette documentation utilise les primitives de Qiskit Runtime, qui te permettent d'utiliser les backends IBM®, les primitives peuvent être exécutées avec n'importe quel fournisseur en utilisant les primitives backend à la place. De plus, tu peux utiliser les primitives de référence pour exécuter sur un simulateur statevector local. Consulte Simulation exacte avec les primitives Qiskit pour les détails.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-runtime
Les étapes décrites dans ce sujet expliquent comment configurer les primitives, explorer les options disponibles pour les paramétrer, et les invoquer dans un programme.
Pour utiliser les portes fractionnelles nouvellement prises en charge, définis use_fractional_gates=True lors de la demande d'un backend à partir d'une instance QiskitRuntimeService. Par exemple :
service = QiskitRuntimeService()
fractional_gate_backend = service.least_busy(use_fractional_gates=True)
Note que cette fonctionnalité est expérimentale et pourrait changer à l'avenir.
Versions des packages
Le code sur cette page a été développé avec les dépendances suivantes. Nous recommandons d'utiliser ces versions ou des versions plus récentes.
qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
Débuter avec Estimator
1. Initialiser le compte
Comme Qiskit Runtime Estimator est un service géré, tu dois d'abord initialiser ton compte. Tu peux ensuite sélectionner le QPU que tu souhaites utiliser pour calculer la valeur d'espérance.
Suis les étapes du sujet Installation et configuration si tu n'as pas encore de compte.
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
print(backend.name)
ibm_torino
2. Créer un circuit et un observable
Tu as besoin d'au moins un circuit et un observable comme entrées pour la primitive Estimator.
from qiskit.circuit.library import qaoa_ansatz
from qiskit.quantum_info import SparsePauliOp
entanglement = [tuple(edge) for edge in backend.coupling_map.get_edges()]
observable = SparsePauliOp.from_sparse_list(
[("ZZ", [i, j], 0.5) for i, j in entanglement],
num_qubits=backend.num_qubits,
)
circuit = qaoa_ansatz(observable, reps=2)
# the circuit is parametrized, so we will define the parameter values for execution
param_values = [0.1, 0.2, 0.3, 0.4]
print(f">>> Observable: {observable.paulis}")
>>> Observable: ['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...', ...]
Le circuit et l'observable doivent être transformés pour n'utiliser que les instructions prises en charge par le QPU (appelées circuits à architecture d'ensemble d'instructions (ISA)). Nous allons utiliser le transpileur pour ce faire.
from qiskit.transpiler import generate_preset_pass_manager
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)
print(f">>> Circuit ops (ISA): {isa_circuit.count_ops()}")
>>> Circuit ops (ISA): OrderedDict([('rz', 3826), ('sx', 1601), ('cz', 968)])
3. Initialiser Qiskit Runtime Estimator
Lors de l'initialisation d'Estimator, utilise le paramètre mode pour spécifier le mode dans lequel tu souhaites l'exécuter. Les valeurs possibles sont des objets batch, session ou backend pour les modes d'exécution par lot, session et job, respectivement. Pour plus d'informations, consulte Introduction aux modes d'exécution de Qiskit Runtime.
from qiskit_ibm_runtime import EstimatorV2 as Estimator
estimator = Estimator(mode=backend)
4. Invoquer Estimator et obtenir les résultats
Ensuite, invoque la méthode run() pour calculer les valeurs d'espérance pour les circuits d'entrée et les observables. Le circuit, l'observable et les ensembles de valeurs de paramètres optionnels sont fournis sous forme de tuples primitive unified bloc (PUB).
job = estimator.run([(isa_circuit, isa_observable, param_values)])
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job Status: {job.status()}")
>>> Job ID: d5k96c4jt3vs73ds5smg
>>> Job Status: QUEUED
result = job.result()
print(f">>> {result}")
print(f" > Expectation value: {result[0].data.evs}")
print(f" > Metadata: {result[0].metadata}")
>>> PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(), dtype=float64>), stds=np.ndarray(<shape=(), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(), dtype=float64>)), metadata={'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32})], metadata={'dynamical_decoupling': {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False}, 'version': 2})
> Expectation value: 25.8930784649363
> Metadata: {'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}
Débuter avec Sampler
1. Initialiser le compte
Comme Qiskit Runtime Sampler est un service géré, tu dois d'abord initialiser ton compte. Tu peux ensuite sélectionner le QPU que tu souhaites utiliser pour calculer la valeur d'espérance.
Suis les étapes du sujet Installation et configuration si tu n'as pas encore de compte configuré.
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
2. Créer un circuit
Tu as besoin d'au moins un circuit comme entrée pour la primitive Sampler.
import numpy as np
from qiskit.circuit.library import efficient_su2
circuit = efficient_su2(127, entanglement="linear")
circuit.measure_all()
# The circuit is parametrized, so we will define the parameter values for execution
param_values = np.random.rand(circuit.num_parameters)
Utilise le transpileur pour obtenir un circuit ISA.
from qiskit.transpiler import generate_preset_pass_manager
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)
print(f">>> Circuit ops (ISA): {isa_circuit.count_ops()}")
>>> Circuit ops (ISA): OrderedDict([('sx', 3089), ('rz', 3036), ('cz', 1092), ('measure', 127), ('barrier', 1)])
3. Initialiser le Qiskit Runtime Sampler
Lors de l'initialisation du Sampler, utilise le paramètre mode pour spécifier le mode dans lequel tu souhaites l'exécuter. Les valeurs possibles sont des objets batch, session ou backend pour les modes d'exécution par lot, session et job, respectivement. Pour plus d'informations, consulte Introduction aux modes d'exécution de Qiskit Runtime. Note que les utilisateurs du plan Open ne peuvent pas soumettre de jobs de session.
from qiskit_ibm_runtime import SamplerV2 as Sampler
sampler = Sampler(mode=backend)
4. Invoquer le Sampler et obtenir les résultats
Ensuite, invoque la méthode run() pour générer la sortie. Le circuit et les ensembles de valeurs de paramètres optionnels sont fournis sous forme de tuples primitive unified bloc (PUB).
job = sampler.run([(isa_circuit, param_values)])
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job Status: {job.status()}")
>>> Job ID: d5k96rsjt3vs73ds5tig
>>> Job Status: QUEUED
result = job.result()
# Get results for the first (and only) PUB
pub_result = result[0]
print(
f"First ten results for the 'meas' output register: {pub_result.data.meas.get_bitstrings()[:10]}"
)
First ten results for the 'meas' output register: ['0101001101010000011001110001011000010010001100001000100110011111011110000010110001101000110011101010000100011011000110101111000', '0100111000000100110001100100000101111000111001101000110111101110110010010100001101001111001010011101010000010011000110000010001', '0101111101111111010011010101000000110100000010000010011101100011100011001100000100100001000101000000100001010101010011001101100', '1100110101111111001110010000010100101010101010001000001100100110011111010000000010001000110111010000010101100000100000110111001', '0010000001111001111010100100010111101000101000100000101100001000011100000100011010110110100011100110001001110110111101010011000', '0101110000001000100100010010100100111000010100000000010010000000010110010010000110000001110110010100000111001110100100111101100', '0100011111101001000111110011011101101101110101110001010111011101111110011101001000000001110000011110000101010000001010000100000', '0001010101011000110100000100111111100001011000111110000011000111001101010000010001001100000110000000100000110101010010101110010', '0100011010001110011110000110100101100100101001001111010100100101010100010000000010100000101010110010000000001000010101011111110', '0000011000000111000001000101111111110110101100110000001100010010011101011100001010000100011010001010001101000000000000010001001']
Débuter avec les primitives backend
Contrairement aux primitives propres à un fournisseur, les primitives backend sont des implémentations génériques utilisables avec n'importe quel objet backend, à condition qu'il implémente l'interface Backend.
- La primitive Sampler peut être exécutée avec n'importe quel fournisseur en utilisant
qiskit.primitives.BackendSamplerV2. - La primitive Estimator peut être exécutée avec n'importe quel fournisseur en utilisant
qiskit.primitives.BackendEstimatorV2.
Certains fournisseurs implémentent les primitives nativement. Consulte la page de l'écosystème Qiskit pour les détails.
Exemple : BackendEstimator
from qiskit.primitives import BackendEstimatorV2
from <some_qiskit_provider> import QiskitProvider
provider = QiskitProvider()
backend = provider.get_backend('backend_name')
estimator = BackendEstimatorV2(backend)
Exemple : BackendSampler
from qiskit.primitives import BackendSamplerV2
from <some_qiskit_provider> import QiskitProvider
provider = QiskitProvider()
backend = provider.get_backend('backend_name')
sampler = BackendSamplerV2(backend)
Similitudes et différences entre les primitives backend et Runtime
-
Les entrées et sorties de
qiskit.primitives.BackendSamplerV2etqiskit.primitives.BackendEstimatorV2suivent le même format PUB que les primitives dans Qiskit Runtime. Consulte Entrées et sorties des primitives pour les détails. Des différences peuvent néanmoins apparaître dans les champs des métadonnées retournées. -
La classe
qiskit.primitives.BackendEstimatorV2n'offre pas d'implémentations d'atténuation des erreurs de mesure ou de porte intégrées, car les primitives backend sont conçues pour s'exécuter localement sur la machine de l'utilisateur. -
La classe
qiskit.primitives.BackendSamplerV2nécessite un backend qui prend en charge l'optionmemory. -
Les interfaces des primitives backend exposent des
Optionspersonnalisées pourSamplerV2etEstimatorV2qui diffèrent des implémentations Runtime.
Prochaines étapes
- Apprends à tester localement avant d'exécuter sur des ordinateurs quantiques.
- Consulte des exemples détaillés de primitives.
- Pratique avec les primitives en suivant la leçon sur les fonctions de coût dans IBM Quantum Learning.
- Apprends à transpiler localement dans la section Transpiler.
- Essaie le guide Comparer les paramètres du transpileur.
- Apprends à utiliser les options des primitives.
- Consulte l'API pour les options de Sampler et Estimator.
- Lis Migrer vers les primitives V2.