Skip to main content
IBM Quantum Platform

Gestion des performances : une fonction Qiskit par Q-CTRL Fire Opal

Consultez la documentation de l'API

Remarque

Les fonctions Qiskit sont une fonctionnalité expérimentale disponible uniquement pour IBM Quantum® Premium Plan, Flex Plan, et On-Prem (via IBM Quantum Platform API). Elles sont en cours de publication et peuvent être modifiées.

  • Le code figurant sur cette page a été développé selon les exigences suivantes. Nous recommandons d'utiliser ces versions ou des versions plus récentes.

    qiskit[all]~=2.3.1
    qiskit-ibm-runtime~=0.45.1
    

Aperçu

Fire Opal Performance Management permet à tout un chacun d'obtenir des résultats significatifs à partir d'ordinateurs quantiques à grande échelle sans avoir besoin d'être un expert en matériel quantique. Lors de l'exécution de circuits avec Fire Opal Performance Management, des techniques de suppression des erreurs pilotées par l'IA sont automatiquement appliquées, ce qui permet la mise à l'échelle de problèmes plus importants avec davantage de portes et de qubits. Cette approche réduit le nombre de tirs nécessaires pour obtenir la bonne réponse, sans frais généraux supplémentaires, ce qui se traduit par des économies significatives en termes de temps de calcul et de coûts.

La gestion des performances supprime les erreurs et augmente la probabilité d'obtenir la bonne réponse sur du matériel bruyant. En d'autres termes, il augmente le rapport signal/bruit. L'image suivante montre comment la précision accrue permise par la gestion des performances peut réduire le besoin de prises de vue supplémentaires dans le cas d'un algorithme de transformée de Fourier quantique à 10 qubits. Avec seulement 30 tirs, Q-CTRL atteint le seuil de confiance de 99%, alors que la méthode par défaut (QiskitRuntime Sampler, optimization_level=3 et resilience_level=1, ibm_sherbrooke) nécessite 170 000 tirs. En obtenant la bonne réponse plus rapidement, vous économisez un temps de calcul considérable.

Visualisation de la durée d'exécution améliorée

La fonction « Performance Management » peut être utilisée avec n'importe quel algorithme, et vous pouvez facilement l'utiliser à la place des primitives standard d' IBM Quantum. En coulisses, plusieurs techniques de gestion des erreurs fonctionnent de concert pour empêcher les erreurs de se produire lors de l'exécution. Toutes les méthodes de pipeline de Fire Opal sont préconfigurées et indépendantes des algorithmes, ce qui signifie que vous bénéficiez toujours des meilleures performances dès l'installation.

Pour accéder à la gestion de la performance, contactez Q-CTRL.


Description

Fire Opal Performance Management propose deux options d'exécution similaires aux primitives d' IBM Quantum, ce qui vous permet d'intégrer facilement l'échantillonneur et l'estimateur Q-CTRL. Le déroulement général de l'utilisation de la fonction « Gestion de la performance » est le suivant :

  1. Définissez votre circuit (et vos opérateurs dans le cas de l'Estimateur).
  2. Faire fonctionner le circuit.
  3. Récupérer les résultats.

Pour réduire le bruit matériel, Fire Opal utilise une série de techniques de suppression d'erreurs pilotées par l'intelligence artificielle, comme le montre l'image suivante. Avec Fire Opal, l'ensemble du pipeline est entièrement automatisé et ne nécessite aucune configuration.

Le pipeline de Fire Opal élimine le besoin de frais généraux supplémentaires, tels qu'un temps d'exécution quantique accru ou des qubits physiques supplémentaires. Notez que le temps de traitement classique reste un facteur (reportez-vous à la section Benchmarks pour des estimations, où le "temps total" reflète à la fois le traitement classique et le traitement quantique). Contrairement à l'atténuation des erreurs, qui nécessite des frais généraux sous forme d'échantillonnage, la suppression des erreurs de Fire Opal agit à la fois au niveau des portes et des impulsions pour traiter les différentes sources de bruit et prévenir la probabilité qu'une erreur se produise. En évitant les erreurs, le besoin d'un post-traitement coûteux est éliminé.

L'image suivante illustre les méthodes de suppression des erreurs automatisées par Fire Opal Performance Management.

Visualisation du pipeline de suppression des erreurs

Cette fonction propose deux primitives, « Sampler » et « Estimator », dont les entrées et les sorties étendent la spécification mise en œuvre pour les primitives « IBM Quantum » V2.


Tests de performances

Les résultats publiés de l'évaluation comparative des algorithmes démontrent une amélioration significative des performances de divers algorithmes, notamment Bernstein-Vazirani, la transformée de Fourier quantique, la recherche de Grover, l'algorithme d'optimisation approximative quantique et le résolveur d'équations quantiques variationnelles. Le reste de cette section fournit plus de détails sur les types d'algorithmes que vous pouvez exécuter, ainsi que sur les performances et les durées d'exécution attendues.

Les études indépendantes suivantes montrent comment la gestion des performances de Q-CTRL permet de mener des recherches algorithmiques à une échelle record :

Le tableau suivant donne une indication approximative de la précision et de la durée d'exécution des analyses comparatives effectuées précédemment sur ibm_fez. Les performances sur d'autres appareils peuvent varier. Le temps d'utilisation est basé sur une hypothèse de 10 000 tirs par circuit. Le "nombre de qubits" indiqué n'est pas une limite absolue, mais représente des seuils approximatifs pour lesquels on peut s'attendre à une précision extrêmement constante des solutions. Des problèmes de plus grande taille ont été résolus avec succès, et les essais au-delà de ces limites sont encouragés.

Exemple
Nombre de qubits
Exactitude
Mesure de la précision
Durée totale (s)
Utilisation du temps d'exécution (s)
Primitif (Mode)
Bernstein-Vazirani50Q100 %Taux de réussite (pourcentage d'exécutions pour lesquelles la réponse correcte est la chaîne de bits la plus élevée)108Echantillonneur
Transformée de Fourier quantique30Q100 %Taux de réussite (pourcentage d'exécutions pour lesquelles la réponse correcte est la chaîne de bits la plus élevée)108Echantillonneur
Estimation quantique de la phase30Q99.9998%Précision de l'angle trouvé : 1- abs(real_angle - angle_found)/pi108Echantillonneur
Simulation quantique : Modèle Ising (15 étapes)20Q99.775%AA (défini ci-dessous)60 (par étape)15 (par étape)Estimateur
Simulation quantique 2 : dynamique moléculaire (20 points de temps)34Q96.78%AmeanA_{mean} (défini ci-dessous)10 (par point dans le temps)6 (par point dans le temps)Estimateur

Définition de la précision de la mesure d'une valeur attendue - la métrique AA est définie comme suit :

A=1ϵidealϵmeasϵmaxidealϵminideal,A = 1 - \frac{|\epsilon^{ideal} - \epsilon^{meas}|}{\epsilon^{ideal}_{max} - \epsilon^{ideal}_{min}},

ϵideal\epsilon^{ideal} = valeur idéale attendue, ϵmeas\epsilon^{meas} = valeur mesurée attendue, ϵmaxideal\epsilon^{ideal}_{max} = valeur maximale idéale et ϵminideal\epsilon^{ideal}_{min} = valeur minimale idéale. AmeanA_{mean} est simplement la moyenne de la valeur de AA sur plusieurs mesures.

Cette mesure est utilisée parce qu'elle est invariante par rapport aux changements globaux et aux échelles dans la gamme des valeurs réalisables. En d'autres termes, que l'on augmente ou diminue la fourchette des valeurs possibles de l'espérance ou que l'on augmente l'écart, la valeur de AA devrait rester cohérente.


Premiers pas

Fire Opal Performance Management utilise Qiskit v2.0.0, qui est la version recommandée. Les versions prises en charge sont Qiskit >= v2.0.0. Authentifiez-vous à l'aide de votre clé API IBM Quantum Platform et sélectionnez la fonction Qiskit comme suit. (Cet extrait de code part du principe que vous avez déjà enregistré votre compte dans votre environnement local.)

from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

# verify that you have access to the function
catalog.list()

Output:

[QiskitFunction(qunova/hivqe-chemistry),
 QiskitFunction(global-data-quantum/quantum-portfolio-optimizer),
 QiskitFunction(algorithmiq/tem),
 QiskitFunction(qedma/qesem),
 QiskitFunction(multiverse/singularity),
 QiskitFunction(ibm/circuit-function),
 QiskitFunction(q-ctrl/optimization-solver),
 QiskitFunction(colibritd/quick-pde),
 QiskitFunction(q-ctrl/performance-management),
 QiskitFunction(kipu-quantum/iskay-quantum-optimizer)]
# Access Function
perf_mgmt = catalog.load("q-ctrl/performance-management")
Cette fonction prend-elle en charge tous les backends d' IBM?

Si vous souhaitez utiliser un backend qui n'est pas encore pris en charge par cette fonction, contactez Q-CTRL pour qu'il soit ajouté.


Primitive d'estimation

Exemple d'estimateur

Utilisez la primitive Estimator de Fire Opal Performance Management pour déterminer la valeur attendue d'une seule paire circuit-observable.

En plus des paquets qiskit-ibm-catalog et qiskit , vous utiliserez également le paquet numpy pour exécuter cet exemple. Vous pouvez installer ce paquet en décommentant la cellule suivante si vous exécutez cet exemple dans un ordinateur portable utilisant le noyau IPython.

# %pip install numpy

1. Créer le circuit

Par exemple, générez un opérateur hermitien aléatoire et un observable à introduire dans la fonction de gestion des performances.

import numpy as np
from qiskit.circuit.library import iqp
from qiskit.quantum_info import random_hermitian, SparsePauliOp

n_qubits = 50

# Generate a random circuit
mat = np.real(random_hermitian(n_qubits, seed=1234))
circuit = iqp(mat)
circuit.measure_all()

# Define observables as a string
observable = SparsePauliOp("Z" * n_qubits)
# Create PUB tuple
estimator_pubs = [(circuit, observable)]

2. Faire fonctionner le circuit

Exécutez le circuit et définissez éventuellement le backend et le nombre de tirs.

# Run the circuit using Estimator
qctrl_estimator_job = perf_mgmt.run(
    primitive="estimator",
    pubs=estimator_pubs,
    backend_name=backend_name,
)

Vous pouvez utiliser les API familières d' Qiskit Serverless s pour vérifier l'état de votre charge de travail Qiskit Function :

qctrl_estimator_job.status()

Output:

'QUEUED'

3. Récupérer le résultat

# Retrieve the counts from the result list
result = qctrl_estimator_job.result()

Les résultats se présentent sous le même format que ceux d'Estimator :

import numpy

result_str = str(result)

with numpy.printoptions(threshold=200):
    print(
        f"The result of the submitted job had {len(result)} PUB "
        f"and has a value:\n {result[0]}\n"
    )

print("The associated PubResult of this job has the following DataBins:")
print(f"{result[0].data}\n")

print(f"And this DataBin has attributes: {result[0].data.keys()}")

print("The expectation values measured from this PUB are:")
print(f"{result[0].data.evs}")

Output:

The result of the submitted job had 1 PUB
The result of the submitted job had 1 PUB and has a value:
 PubResult(data=DataBin(evs=0.0195, stds=0.9998098569228051), metadata={'precision': None})

The associated PubResult of this job has the following DataBins:
DataBin(evs=0.0195, stds=0.9998098569228051)

And this DataBin has attributes: dict_keys(['evs', 'stds'])
The expectation values measured from this PUB are:
0.0195

Primitive d'échantillonnage

Exemple d'échantillonneur

Utilisez la primitive Sampler de Fire Opal Performance Management pour exécuter un circuit Bernstein-Vazirani. Cet algorithme, utilisé pour trouver une chaîne cachée à partir des sorties d'une fonction de boîte noire, est un algorithme d'évaluation commun car il n'y a qu'une seule réponse correcte.

1. Créer le circuit

Définissez la réponse correcte à l'algorithme, à la chaîne de bits cachée et au circuit de Bernstein-Vazirani. Vous pouvez ajuster la largeur du circuit en changeant simplement l'adresse circuit_width.

import qiskit

circuit_width = 35
hidden_bitstring = "1" * circuit_width

# Create circuit, reserving one qubit for BV oracle
bv_circuit = qiskit.QuantumCircuit(circuit_width + 1, circuit_width)
bv_circuit.x(circuit_width)
bv_circuit.h(range(circuit_width + 1))
for input_qubit, bit in enumerate(reversed(hidden_bitstring)):
    if bit == "1":
        bv_circuit.cx(input_qubit, circuit_width)
bv_circuit.barrier()
bv_circuit.h(range(circuit_width + 1))
bv_circuit.barrier()
for input_qubit in range(circuit_width):
    bv_circuit.measure(input_qubit, input_qubit)

# Create PUB tuple
sampler_pubs = [(bv_circuit,)]

2. Faire fonctionner le circuit

Exécutez le circuit et définissez éventuellement le backend et le nombre de tirs.

# Run the circuit using Sampler
qctrl_sampler_job = perf_mgmt.run(
    primitive="sampler",
    pubs=sampler_pubs,
    backend_name=backend_name,
)

Pour vérifier l'état de votre charge de travail Qiskit Function ou obtenir les résultats, procédez comme suit :

# Print the ID so you can use it later, if necessary
print(qctrl_sampler_job.job_id)

qctrl_sampler_job.status()

Output:

60fe2fa1-a860-43e4-8615-c6ac4180f93b
'QUEUED'

3. Récupérer le résultat

# Retrieve the job results
sampler_result = qctrl_sampler_job.result()
# Get results for the first (and only) PUB
pub_result = sampler_result[0]
counts = pub_result.data.c.get_counts()

print("Counts for the meas output register (limited to 30 results):")
for i, (bitstring, count) in enumerate(counts.items()):
    if i >= 50:
        print(f"  ... ({len(counts) - 30} more items)")
        break
    print(f"  {bitstring}: {count}")

Output:

Counts for the meas output register (limited to 30 results):
  11111111111111111111111111111111111: 1661
  11111111111111111111111111110111111: 60
  11111111111111111111111111111101111: 54
  11111111111111111111111111111110111: 54
  11111111111111011111111111111111111: 46
  11111111111111111110111111111111111: 44
  11111111111111111111111101111111111: 42
  11111111111111111111111110111111111: 42
  11111111111111110111111111111111111: 41
  11111111111111111111111111111111101: 39
  11111111111111111111101111111111111: 38
  11111111111111111111110111111111111: 38
  11111111111111111111111111101111111: 37
  11111111111111111111111111111111110: 36
  11111111111110111111111111111111111: 35
  11111111111111111111111111111011111: 32
  11111111111111101111111111111111111: 32
  01111111111111111111111111111111111: 27
  11111111111111111011111111111111111: 23
  11111111101111111111111111111111111: 22
  11111111111111111111111111111111011: 21
  11111111011111111111111111111111111: 20
  00000000000000011111111111111111111: 18
  11111111111111111111110101111111111: 18
  00000001111111111111111111111111111: 17
  11111111001111111111111111111111111: 16
  11101111111111111111111111111111111: 16
  11111111111101111111111111111111111: 16
  00000101111111111111111111111111111: 13
  11111111111111111111111011111111111: 13
  11111111111111111111111110101111111: 13
  11111111111111111101111111111111111: 12
  10111111111111111111111111111111111: 12
  11111111111111111111111110001111111: 12
  00000000000000000011111111111111111: 11
  11111111111111111111111111111110110: 10
  00000000000000000000000001111111111: 10
  11111111111011111111111111111111111: 9
  11111111111111101011111111111111111: 9
  00000000011111111111111111111111111: 8
  10101111111111111111111111111111111: 8
  00000000000000000000000001011111111: 8
  11111111111111111111111111111111001: 8
  00000111111111111111111111111111111: 7
  11111111111111111111111111111101110: 7
  11111111110111111111111111111111111: 7
  00000000000001011111111111111111111: 6
  00000000000000001111111111111111111: 6
  00000000000000000001011111111111111: 6
  11111111111111111111111111011111111: 6
  ... (1050 more items)

3. Tracer les chaînes de bits supérieures

Tracer la chaîne de bits avec les comptes les plus élevés pour voir si la chaîne de bits cachée était le mode.

import matplotlib.pyplot as plt


def plot_top_bitstrings(counts_dict, hidden_bitstring=None):
    # Sort and take the top 100 bitstrings
    top_100 = sorted(counts_dict.items(), key=lambda x: x[1], reverse=True)[
        :100
    ]
    if not top_100:
        print("No bitstrings found in the input dictionary.")
        return

    # Unzip the bitstrings and their counts
    bitstrings, counts = zip(*top_100)

    # Assign colors: purple if the bitstring matches hidden_bitstring,
    # otherwise gray
    colors = [
        "#680CE9" if bit == hidden_bitstring else "gray" for bit in bitstrings
    ]

    # Create the bar plot
    plt.figure(figsize=(15, 8))
    plt.bar(
        range(len(bitstrings)), counts, tick_label=bitstrings, color=colors
    )

    # Rotate the bitstrings for better readability
    plt.xticks(rotation=90, fontsize=8)
    plt.xlabel("Bitstrings")
    plt.ylabel("Counts")
    plt.title("Top 100 Bitstrings by Counts")

    # Show the plot
    plt.tight_layout()
    plt.show()

La chaîne de bits cachée est surlignée en violet et devrait être la chaîne de bits ayant le plus grand nombre de comptes.

plot_top_bitstrings(counts, hidden_bitstring)

Output:

Output of the previous code cell

Journal des modifications

  • 2026-02-20 : Avis de dépréciation - le champ provider_job_ids de métadonnées sera déprécié dans 30 jours dans la version 0.13.0. Les utilisateurs peuvent accéder à l'ID de tâche via job_id() la méthode du service d'exécution.
  • 11 février 2026 : Nous prenons désormais en charge ibm_miami et avons ajouté des métadonnées d'exécution au PubResult.

Obtenir de l'aide

Pour toute question ou problème, contactez Q-CTRL.


Etapes suivantes

Recommandations
Cette page a-t-elle été utile ?
Signaler un bogue, une coquille ou proposer du contenu sur GitHub.