Comment envoyer un circuit avec Qiskit à Azure Quantum

Découvrez comment envoyer un circuit quantique Qiskit à l’aide du azure-quantumPython package. Vous pouvez envoyer des circuits Qiskit à Azure Quantum à l’aide du notebook Azure Quantum, qui dispose d’un package intégré azure-quantumPython , ou à partir de votre ordinateur local.

Pour plus d’informations, consultez la page Circuits quantiques.

Notes

Le Kit de développement Microsoft Quantum (QDK classique) ne sera plus pris en charge après le 30 juin 2024. Si vous êtes un développeur QDK existant, nous vous recommandons de passer au nouveau Kit de développement Azure Quantum (QDK moderne) pour continuer à développer des solutions quantiques. Pour plus d’informations, consultez Migrer votre code Q# vers le QDK moderne.

Prérequis

Pour plus d’informations sur l’installation, consultez Installation du QDK moderne sur VS Code.

  • Un espace de travail Azure Quantum dans votre abonnement Azure. Pour créer un espace de travail, consultez Créer un espace de travail Azure Quantum.

  • Un Python environnement avec Python et Pip installé.

  • VS Code avec le kit de développement Azure Quantum, Pythonet les extensions Jupyter installées .

  • Package Azure Quantum azure-quantum avec la balise [qiskit] et les qsharp packages et ipykernel .

    python -m pip install --upgrade azure-quantum[qiskit] qsharp ipykernel 
    

    Notes

    Si le noyau ipykernel Jupyter Python n’est pas détecté, VS Code vous invite à l’installer.

Création d’un notebook Jupyter

  1. Dans VS Code, sélectionnez Afficher > la palette de commandes, puis Créer : nouveau Jupyter Notebook.
  2. En haut à droite, VS Code détecte et affiche la version de Python et l’environnement virtuel Python qui a été sélectionné pour le notebook. Si vous avez plusieurs Python environnements, vous devrez peut-être sélectionner un noyau à l’aide du sélecteur de noyau en haut à droite. Si aucun environnement n’a été détecté, consultez Notebooks Jupyter dans VS Code pour plus d’informations sur l’installation.

Charger les importations requises

Dans la première cellule de votre notebook, exécutez le code suivant pour charger les importations requises :

import azure.quantum
from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
from azure.quantum.qiskit import AzureQuantumProvider

Se connecter au service Azure Quantum

Pour vous connecter au service Azure Quantum, vous avez besoin de l’ID de ressource et de l’emplacement de votre espace de travail Azure Quantum. Connectez-vous à votre compte Azure, https://portal.azure.com, accédez à votre espace de travail Azure Quantum, puis copiez les valeurs de l’en-tête.

Procédure de récupération de l’ID de ressource et de l’emplacement à partir d’un espace de travail Azure Quantum

Ajoutez une nouvelle cellule et utilisez vos informations de compte pour créer Workspace des objets et AzureQuantumProvider pour vous connecter à votre espace de travail Azure Quantum.

workspace = Workspace(  
    resource_id = "", # Add the resourceID of your workspace
    location = "" # Add the location of your workspace (for example "westus")
    )

provider = AzureQuantumProvider(workspace)

Liste de tous les serveurs principaux

Vous pouvez maintenant imprimer tous les serveurs principaux d’informatique quantique disponibles dans votre espace de travail :

print("This workspace's targets:")
for backend in provider.backends():
    print("- " + backend.name())
This workspace's targets:
- ionq.qpu
- ionq.qpu.aria-1
- ionq.simulator
- microsoft.estimator
- quantinuum.hqs-lt-s1
- quantinuum.hqs-lt-s1-apival
- quantinuum.hqs-lt-s2
- quantinuum.hqs-lt-s2-apival
- quantinuum.hqs-lt-s1-sim
- quantinuum.hqs-lt-s2-sim
- quantinuum.qpu.h1-1
- quantinuum.sim.h1-1sc
- quantinuum.sim.h1-1e
- rigetti.sim.qvm
- rigetti.qpu.ankaa-2

Exécuter un circuit simple

Tout d’abord, créez un circuit Qiskit simple à exécuter.

# Create a Quantum Circuit acting on the q register
circuit = QuantumCircuit(3, 3)
circuit.name = "Qiskit Sample - 3-qubit GHZ circuit"
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure([0,1,2], [0, 1, 2])

# Print out the circuit
circuit.draw()
     ┌───┐          ┌─┐      
q_0: ┤ H ├──■───────┤M├──────
     └───┘┌─┴─┐     └╥┘┌─┐   
q_1: ─────┤ X ├──■───╫─┤M├───
          └───┘┌─┴─┐ ║ └╥┘┌─┐
q_2: ──────────┤ X ├─╫──╫─┤M├
               └───┘ ║  ║ └╥┘
c: 3/════════════════╩══╩══╩═
                     0  1  2 

Sélectionnez un target pour exécuter votre programme

Exécuter sur le simulateur IonQ

Avant d’exécuter sur du matériel réel, nous allons tester le circuit dans le simulateur. Utilisez get_backend pour créer un Backend objet pour se connecter au serveur principal du simulateur IonQ :

simulator_backend = provider.get_backend("ionq.simulator")

Les back-ends IonQ prennent en charge les portes d’un ensemble de portes défini, qui sont compilées pour s’exécuter de façon optimale sur le matériel. Si votre circuit contient des portes qui ne figurent pas dans cette liste, vous devez transpiler dans le pris en charge gateset à l’aide de la transpile fonction fournie par Qiskit :

from qiskit import transpile
circuit = transpile(circuit, simulator_backend)

La fonction transpile retourne un nouvel objet de circuit dans lequel les portes sont décomposées en portes prises en charge sur le back-end spécifié.

Vous pouvez maintenant exécuter le programme par le biais du service Azure Quantum et obtenir le résultat. La cellule suivante envoie un travail qui exécute le circuit avec 100 captures :

job = simulator_backend.run(circuit, shots=100)
job_id = job.id()
print("Job id", job_id)
Job id 00000000-0000-0000-0000-000000000000

Pour attendre la fin du travail et retourner les résultats, exécutez :

result = job.result()
print(result)
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='00000000-0000-0000-0000-000000000000', success=True, results=[ExperimentResult(shots=100, success=True, meas_level=2, data=ExperimentResultData(counts={'000': 50, '111': 50}, probabilities={'000': 0.5, '111': 0.5}), header=QobjExperimentHeader(meas_map='[0, 1, 2]', name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits='3', qiskit='True'))])

Comme le résultat est un objet natif du package Qiskit, vous pouvez utiliser result.get_counts et plot_histogram de Qiskit pour visualiser les résultats. Pour vous assurer que toutes les étiquettes bitstring possibles sont représentées, ajoutez-les à counts.

counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
{'000': 50, '001': 0, '010': 0, '011': 0, '100': 0, '101': 0, '110': 0, '111': 50}

Résultat du circuit Qiskit sur le Simulateur IonQ

Estimer le coût du travail

Avant d’exécuter un travail sur le QPU, vous pouvez estimer le coût de son exécution. Pour estimer le coût d’exécution d’un travail sur le processeur quantique, vous pouvez utiliser la méthode estimate_cost :

backend = provider.get_backend("ionq.qpu")
cost = backend.estimate_cost(circuit, shots=1024)

print(f"Estimated cost: {cost.estimated_total}")

Le coût estimé est affiché en USD.

Pour obtenir les dernières informations tarifaires, consultez Tarifs IonQ, ou recherchez votre espace de travail et consultez les options tarifaires sous l’onglet « Fournisseur » de votre espace de travail via : aka.ms/aq/myworkspaces.

Exécuter sur la QPU IonQ

Pour vous connecter à du matériel réel (une unité de processeur quantique ( QPU), indiquez simplement le nom du target"ionq.qpu" à la get_backend méthode :

qpu_backend = provider.get_backend("ionq.qpu")

Envoyez le circuit pour qu’il s’exécute sur Azure Quantum, obtenez les résultats et exécutez plot_histogram pour tracer les résultats.

Notes

Le temps nécessaire à l’exécution d’un circuit sur la QPU peut varier en fonction des durées de file d’attente actuelles.

# Submit the circuit to run on Azure Quantum
job = qpu_backend.run(circuit, shots=1024)
job_id = job.id()
print("Job id", job_id)

# Get the job results (this method waits for the Job to complete):
result = job.result()
print(result)
counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
Job id 00000000-0000-0000-0000-000000000000
Job Status: job has successfully run
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='00000000-0000-0000-0000-000000000000', success=True, results=[ExperimentResult(shots=1024, success=True, meas_level=2, data=ExperimentResultData(counts={'0': 505, '1': 6, '2': 1, '3': 1, '4': 1, '5': 10, '6': 11, '7': 488}, probabilities={'0': 0.4932, '1': 0.0059, '2': 0.001, '3': 0.001, '4': 0.001, '5': 0.0098, '6': 0.0117, '7': 0.4766}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits='3', qiskit='True'))])
{'000': 505, '001': 6, '010': 1, '011': 1, '100': 1, '101': 10, '110': 11, '111': 488}

Résultat du circuit Qiskit sur la QPU IonQ

Important

L’envoi de plusieurs circuits sur un seul travail n’est pas actuellement pris en charge. Une solution de contournement consiste à appeler la méthode backend.run pour envoyer chaque circuit de manière asynchrone, puis à extraire les résultats de chaque travail. Par exemple :

jobs = []
for circuit in circuits:
    jobs.append(backend.run(circuit, shots=N))

results = []
for job in jobs:
    results.append(job.result())

Prérequis

Créer un notebook dans votre espace de travail

  1. Connectez-vous au Portail Azure et sélectionnez l’espace de travail que vous avez créé à l’étape précédente.
  2. Dans le panneau de gauche, sélectionnez Notebooks.
  3. Cliquez sur Mes notebooks, puis sur Ajouter nouveau.
  4. Tapez un nom pour le fichier, par exemple Qiskit.ipynb, puis cliquez sur Créer le fichier.

Quand votre nouveau notebook s’ouvre, il crée automatiquement le code de la première cellule, en fonction de vos informations d’abonnement et d’espace de travail.

from azure.quantum import Workspace
workspace = Workspace ( 
    resource_id = "", # Add your resource_id 
    location = ""  # Add your workspace location (for example, "westus") 
)

Notes

Sauf indication contraire, vous devez exécuter chaque cellule dans l’ordre de création pour éviter les problèmes de compilation.

Cliquez sur l’icône triangulaire « lecture » à gauche de la cellule pour exécuter le code.

Charger les importations requises

Vous devez d’abord importer des modules supplémentaires.

Cliquez sur + Code pour ajouter une nouvelle cellule, puis ajoutez et exécutez le code suivant :

from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
from azure.quantum.qiskit import AzureQuantumProvider

Se connecter au service Azure Quantum

Ensuite, créez un AzureQuantumProvider objet à l’aide de l’objet Workspace de la cellule précédente pour vous connecter à votre espace de travail Azure Quantum. Ajoutez une nouvelle cellule avec le code suivant :

provider = AzureQuantumProvider(workspace)

Définir un circuit simple

Dans une nouvelle cellule, créez un objet circuit. Cet exemple est un générateur de bits aléatoires quantique simple. Ajoutez le code suivant pour définir et afficher le circuit :

# Create a Quantum Circuit acting on the q register
circuit = QuantumCircuit(3, 3)
circuit.name = "Qiskit Sample - 3-qubit GHZ circuit"
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure([0, 1, 2], [0, 1, 2])

# Print out the circuit
circuit.draw()
     ┌───┐          ┌─┐      
q_0: ┤ H ├──■───────┤M├──────
     └───┘┌─┴─┐     └╥┘┌─┐   
q_1: ─────┤ X ├──■───╫─┤M├───
          └───┘┌─┴─┐ ║ └╥┘┌─┐
q_2: ──────────┤ X ├─╫──╫─┤M├
               └───┘ ║  ║ └╥┘
c: 3/════════════════╩══╩══╩═
                     0  1  2 

Lister tout targets

Vous pouvez maintenant afficher tous les back-ends d’informatique targetsquantique disponibles dans votre espace de travail. Ajoutez une nouvelle cellule et exécutez la ligne suivante :

print("This workspace's targets:")
for backend in provider.backends():
    print("- " + backend.name())
This workspace's targets:
- ionq.qpu
- ionq.simulator
- ionq.qpu.aria-1
- microsoft.estimator
- quantinuum.qpu.h1-1
- quantinuum.sim.h1-1sc
- quantinuum.sim.h1-1e
- rigetti.sim.qvm
- rigetti.qpu.ankaa-2

Sélectionnez un target pour exécuter votre programme

Pour vérifier votre code avant de l’exécuter sur du matériel quantique réel, vous pouvez utiliser le simulateur quantique IonQ, ionq.simulator.

Ajoutez une cellule et créez un objet pour représenter le simulateur targetquantique IonQ :

# Get IonQ quantum simulator target:
simulator_backend = provider.get_backend("ionq.simulator")

Exécuter sur le simulateur IonQ

Pour exécuter votre circuit sur le simulateur, ajoutez le code suivant. Cet exemple utilise la run méthode du target pour envoyer votre travail, puis surveille le travail status.

# Submit the circuit to run on Azure Quantum
job = simulator_backend.run(circuit, shots=100)
job_id = job.id()
print("Job id", job_id)

Lorsque le travail s’exécute correctement, obtenez les résultats du travail et affichez-les :

# Get the job results:
result = job.result()
print(result)
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='7d909574-98d4-11ec-b382-00155d957f5d', success=True, results=[ExperimentResult(shots=100, success=True, meas_level=2, data=ExperimentResultData(counts=defaultdict(<class 'int'>, {'000': 50, '111': 50}), probabilities=defaultdict(<class 'int'>, {'000': 0.5, '111': 0.5})), header=QobjExperimentHeader(meas_map='[0, 1, 2]', name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits='3', qiskit='True'))])

Étant donné que ce type result est un objet natif du package Qiskit, vous pouvez utiliser result.get_counts et plot_histogram de Qiskit pour visualiser les résultats. Pour vous assurer que toutes les étiquettes bitstring possibles sont représentées, ajoutez-les à counts.

counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
{'000': 50, '001': 0, '010': 0, '011': 0, '100': 0, '101': 0, '110': 0, '111': 50}

Résultat du circuit Qiskit sur le Simulateur IonQ

Estimer le coût du travail

Avant d’exécuter un travail sur du matériel quantique réel ou une unité de traitement quantique (QPU), vous pouvez estimer le coût de l’exécution.

Tout d’abord, obtenez à nouveau la liste des fournisseurs disponibles :

print("This workspace's targets:")
for backend in provider.backends():
    print("- " + backend.name())
This workspace's targets:
- ionq.qpu
- ionq.simulator
- ionq.qpu.aria-1
- microsoft.estimator
- quantinuum.qpu.h1-1
- quantinuum.sim.h1-1sc
- quantinuum.sim.h1-1e
- rigetti.sim.qvm
- rigetti.qpu.ankaa-2

Ensuite, créez un objet pour représenter l’ordinateur quantique IonQ :

qpu_backend = provider.get_backend("ionq.qpu")

Pour estimer le coût d’exécution d’un travail sur le QPU, ajoutez et exécutez une nouvelle cellule à l’aide de la estimate_cost méthode de :target

cost = qpu_backend.estimate_cost(circuit, shots=100)

print(f"Estimated cost: {cost.estimated_total}")

Le coût estimé est affiché en USD.

Pour obtenir les dernières informations tarifaires, consultez les tarifs d’IonQ ou consultez les options tarifaires du panneau Fournisseurs de votre espace de travail.

Exécuter sur la QPU IonQ

Une fois que vous avez correctement exécuté votre travail sur le simulateur IonQ et estimé le coût de la QPU, il est temps d’exécuter votre circuit sur le matériel.

Notes

Le temps nécessaire à l’exécution d’un circuit sur le processeur quantique varie en fonction des durées de file d’attente actuelles. Vous pouvez afficher la durée moyenne de file d’attente d’un target en sélectionnant le panneau Fournisseurs de votre espace de travail.

Utilisez la même méthode run et les mêmes opérations que celles que vous avez utilisées précédemment avec le validateur d’API pour envoyer et monitorer votre travail :

# Submit the circuit to run on Azure Quantum
job = qpu_backend.run(circuit, shots=1024)
job_id = job.id()
print("Job id", job_id)

Une fois le travail terminé, obtenez les résultats du travail comme avant et affichez-les dans un graphique :

result = job.result()
print(result)
counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
Job id 910b5ac8-98cd-11ec-b3ba-00155d5528cf
Job Status: job has successfully run
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='Job id 54e8c740-98d9-11ec-b382-00155d957f5d', success=True, results=[ExperimentResult(shots=1024, success=True, meas_level=2, data=ExperimentResultData(counts={'0': 505, '1': 6, '2': 1, '3': 1, '4': 1, '5': 10, '6': 11, '7': 488}, probabilities={'0': 0.4932, '1': 0.0059, '2': 0.001, '3': 0.001, '4': 0.001, '5': 0.0098, '6': 0.0117, '7': 0.4766}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits='3', qiskit='True'))])
{'000': 505, '001': 6, '010': 1, '011': 1, '100': 1, '101': 10, '110': 11, '111': 488}

Résultat du circuit Qiskit sur la QPU IonQ

Important

L’envoi de plusieurs circuits sur un seul travail n’est pas actuellement pris en charge. Une solution de contournement consiste à appeler la méthode backend.run pour envoyer chaque circuit de manière asynchrone, puis à extraire les résultats de chaque travail. Par exemple :

jobs = []
for circuit in circuits:
    jobs.append(backend.run(circuit, shots=N))

results = []
for job in jobs:
    results.append(job.result())

Étapes suivantes