Comment envoyer un circuit avec Cirq à Azure Quantum

Découvrez comment envoyer un circuit quantique Cirq à l’aide du azure-quantumPython package. Vous pouvez envoyer des circuits Cirq à 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 .

  • Le package Azure Quantum azure-quantum avec la balise [cirq] et les qsharp packages et ipykernel .

    python -m pip install --upgrade azure-quantum[cirq] 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 azure.quantum.cirq import AzureQuantumService

Se connecter au service Azure Quantum

Pour se connecter au service Azure Quantum, votre programme aura 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 AzureQuantumService 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")
    )

service = AzureQuantumService(workspace)

Lister tout targets

Utilisez la targets()méthode pour répertorier tous les targets éléments de votre espace de travail qui peuvent exécuter votre circuit, y compris l’heure et la disponibilité de la file d’attente actuelle.

Notes

Tous les targets dans votre espace de travail peuvent ne pas être répertoriés. Seul le targets qui peut accepter un circuit Cirq ou OpenQASM sera répertorié ici.

print(service.targets())
[<Target name="quantinuum.qpu.h1-1", avg. queue time=0 s, Degraded>,
<Target name="quantinuum.sim.h1-1sc", avg. queue time=1 s, Available>,
<Target name="quantinuum.sim.h1-1e", avg. queue time=40 s, Available>,
<Target name="ionq.qpu", avg. queue time=229 s, Available>,
<Target name="ionq.simulator", avg. queue time=3 s, Available>,
<Target name="ionq.qpu.aria-1", avg. queue time=1136774 s, Available>]

Créer un circuit simple

Ensuite, créez un circuit Cirq simple à exécuter. Ce circuit utilise la porte racine carrée de X, native du système matériel IonQ.

import cirq

q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
    cirq.X(q0)**0.5,             # Square root of X
    cirq.CX(q0, q1),              # CNOT
    cirq.measure(q0, q1, key='b') # Measure both qubits
)
print(circuit)
0: ───X^0.5───@───M────────
              │   │
1: ───────────X───M────────

Sélectionnez un target pour exécuter votre programme

Exécuter sur le simulateur IonQ

Vous pouvez maintenant exécuter le programme par le biais du service Azure Quantum et obtenir le résultat. La cellule suivante soumet un travail (au simulateur IonQ par défaut) qui exécute le circuit avec 100 captures, attend que le travail soit terminé, puis renvoie les résultats.

result = service.run(program=circuit, repetitions=100, target="ionq.simulator")

Cela retourne un objet cirq.Result.

print(result)
    b=1001100101100001000011011101000011010100010111100011001000100100010000001110010010101110110000011010, 1001100101100001000011011101000011010100010111100011001000100100010000001110010010101110110000011010

Estimer le coût du travail

Avant d’exécuter un travail sur le processeur quantique, 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 :

cost = service.estimate_cost(
    program=circuit,
    repetitions=100,
    target="ionq.qpu"
)

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

Le travail précédent a été exécuté sur le simulateur par défaut, "ionq.simulator". Toutefois, vous pouvez également l’exécuter sur le processeur matériel de IonQ (Query Processing Unit (QPU)). Pour exécuter la QPU IonQ, fournissez "ionq.qpu" comme argument target :

result = service.run(
    program=circuit,
    repetitions=100,
    target="ionq.qpu",
    timeout_seconds=500 # Set timeout to accommodate queue time on QPU
)

À nouveau, cela retourne un objet cirq.Result.

print(result)
b=0101011011011111100001011101101011011110100010000000011110111000100100110110101100110001001111101111, 0101011011011111100001011101101011011110100010000000011110111000100100110110101100110001001111101111

Modèle asynchrone utilisant des travaux

Pour des circuits longs, il peut être utile de les exécuter de manière asynchrone. La méthode service.create_job renvoie un objet Job que vous pouvez utiliser pour obtenir les résultats une fois l’exécution du travail aboutie.

job = service.create_job(
    program=circuit,
    repetitions=100,
    target="ionq.simulator"
)

Pour vérifier l’état du travail, utilisez la méthode job.status() :

print(job.status())
'completed'

Pour attendre que le travail soit accompli, puis obtenir les résultats, utilisez l’appel bloquant job.results() :

result = job.results()
print(result)
00: 0.5
11: 0.5

Notez que cela ne renvoie aucun objet cirq.Result. À la place, cela renvoie un objet résultat spécifique au simulateur IonQ, et utilisant des probabilités d’état plutôt que des données de capture.

type(result)
cirq_ionq.results.SimulatorResult

Pour convertir ceci en objet cirq.Result, utilisez result.to_cirq_result() :

print(result.to_cirq_result())
b=1110101111111110111000011101011111001100010000001011011101001111001111001101100111010000001100011100, 1110101111111110111000011101011111001100010000001011011101001111001111001101100111010000001100011100

Prérequis

Créer un notebook dans votre espace de travail

  1. Connectez-vous au portail Azure et sélectionnez l’espace de travail de 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, Cirq.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 un module supplémentaire.

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

from azure.quantum.cirq import AzureQuantumService

Se connecter au service Azure Quantum

Ensuite, créez un AzureQuantumService 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 = AzureQuantumService(workspace)

Définir un circuit simple

Ensuite, créez un circuit Cirq simple à exécuter. Ce circuit utilise la porte racine carrée de X, native du système matériel IonQ.

import cirq

q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
    cirq.X(q0)**0.5,             # Square root of X
    cirq.CX(q0, q1),              # CNOT
    cirq.measure(q0, q1, key='b') # Measure both qubits
)
print(circuit)
0: ───X^0.5───@───M────────
              │   │
1: ───────────X───M────────

Lister tout targets

Utilisez la targets()méthode pour répertorier tous les targets éléments de votre espace de travail qui peuvent exécuter votre circuit, y compris l’heure et la disponibilité de la file d’attente actuelle.

Notes

Tous les targets dans votre espace de travail peuvent ne pas être répertoriés. Seul le targets qui peut accepter un circuit Cirq ou OpenQASM sera répertorié ici.

print("This workspace's targets:")
for target in service.targets():
     print(target)
This workspace's targets:
<Target name="quantinuum.qpu.h1-1", avg. queue time=0 s, Degraded>
<Target name="quantinuum.sim.h1-1sc", avg. queue time=1 s, Available>
<Target name="quantinuum.sim.h1-1e", avg. queue time=40 s, Available>
<Target name="ionq.qpu", avg. queue time=229 s, Available>
<Target name="ionq.simulator", avg. queue time=3 s, Available>
<Target name="ionq.qpu.aria-1", avg. queue time=1136774 s, Available>

Notes

La liste complète de target peut être différente pour votre espace de travail.

Sélectionnez un target pour exécuter votre programme

Exécuter sur le simulateur IonQ

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

La cellule suivante soumet un travail qui exécute le circuit avec 100 captures, attend que le travail soit terminé, puis renvoie les résultats.

result = service.run(
    program=circuit,
    repetitions=100,
    target="ionq.simulator"
)

Cela retourne un objet cirq.Result.

print(result)
    b=1001100101100001000011011101000011010100010111100011001000100100010000001110010010101110110000011010, 1001100101100001000011011101000011010100010111100011001000100100010000001110010010101110110000011010

Vous pouvez tracer les résultats dans un histogramme :

import pylab as pl

pl.hist(result.data)
pl.ylabel("Counts")
pl.xlabel("Result")

Estimer le coût du travail

Avant d’exécuter un travail sur du matériel quantique réel ou sur un processeur quantique, vous pouvez estimer le coût de l’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 :

cost = service.estimate_cost(
    program=circuit,
    repetitions=100,
    target="ionq.qpu"
)

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

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

Pour obtenir les dernières informations tarifaires, consultez Tarifs IonQ ou consultez les options tarifaires du panneau Fournisseurs de votre espace de travail. Pour voir l’état actuel de votre crédit et de votre utilisation, sélectionnez Crédits et quotas.

Exécuter sur la QPU IonQ

Le travail précédent a été exécuté sur le simulateur par défaut, ionq.simulator. Toutefois, vous pouvez également l’exécuter sur le processeur matériel de IonQ ou un processeur quantique. Pour exécuter la QPU IonQ, fournissez ionq.qpu comme argument target :

result = service.run(
    program=circuit,
    repetitions=100,
    target="ionq.qpu",
    timeout_seconds=500 # Set timeout to accommodate queue time on QPU
)

Notes

Le temps nécessaire à l’exécution d’un circuit sur le processeur quantique peut varier 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.

À nouveau, cela retourne un objet cirq.Result.

print(result)
    b=1001100101100001000011011101000011010100010111100011001000100100010000001110010010101110110000011010, 1001100101100001000011011101000011010100010111100011001000100100010000001110010010101110110000011010

Modèle asynchrone utilisant des travaux

Pour des circuits longs, il peut être utile de les exécuter de manière asynchrone. La méthode service.create_job renvoie un objet Job que vous pouvez utiliser pour obtenir les résultats une fois l’exécution du travail aboutie.

job = service.create_job(
    program=circuit,
    repetitions=100,
    target="ionq.simulator"
)

Pour vérifier l’état du travail, utilisez la méthode job.status() :

print(job.status())
'completed'

Pour attendre que le travail soit accompli, puis obtenir les résultats, utilisez l’appel bloquant job.results() :

result = job.results()
print(result)
00: 0.5
11: 0.5

Notes

La fonction job.results() ne retourne pas d’objet cirq.Result. À la place, cela renvoie un objet résultat spécifique au simulateur IonQ, et utilisant des probabilités d’état plutôt que des données de capture.

type(result)
cirq_ionq.results.SimulatorResult

Pour convertir ceci en objet cirq.Result, utilisez result.to_cirq_result() :

print(result.to_cirq_result())
b=1110101111111110111000011101011111001100010000001011011101001111001111001101100111010000001100011100, 1110101111111110111000011101011111001100010000001011011101001111001111001101100111010000001100011100

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