Skip to main content
IBM Quantum Platform

Gestione delle prestazioni: una funzione Qiskit di Q-CTRL Fire Opal

Consulta la documentazione dell'API

Nota

Le funzioni Qiskit sono una funzione sperimentale disponibile solo per gli utenti di IBM Quantum® Premium Plan, Flex Plan e On-Prem (tramite IBM Quantum Platform API) Plan. Sono in stato di anteprima e sono soggetti a modifiche.

  • Il codice presente in questa pagina è stato sviluppato utilizzando i seguenti requisiti. Si consiglia di utilizzare queste versioni o versioni più recenti.

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

Panoramica

Fire Opal Performance Management rende semplice per chiunque ottenere risultati significativi dai computer quantistici su scala, senza dover essere esperti di hardware quantistico. Quando si eseguono circuiti con Fire Opal Performance Management, le tecniche di soppressione degli errori guidate dall'intelligenza artificiale vengono applicate automaticamente, consentendo di scalare problemi più grandi con un numero maggiore di porte e qubit. Questo approccio riduce il numero di scatti necessari per ottenere la risposta corretta, senza alcun costo aggiuntivo, con un notevole risparmio in termini di tempo di calcolo e di costi.

La gestione delle prestazioni elimina gli errori e aumenta la probabilità di ottenere la risposta corretta su hardware rumoroso. In altre parole, aumenta il rapporto segnale/rumore. L'immagine seguente mostra come la maggiore precisione consentita dal Performance Management possa ridurre la necessità di ulteriori scatti nel caso di un algoritmo di Trasformata di Fourier Quantistica a 10 qubit. Con soli 30 scatti, Q-CTRL raggiunge la soglia di confidenza del 99%, mentre il default (QiskitRuntime Sampler, optimization_level=3 e resilience_level=1, ibm_sherbrooke) richiede 170.000 scatti. Ottenendo più rapidamente la risposta giusta, si risparmia un tempo di esecuzione significativo.

Visualizzazione del tempo di esecuzione migliorato

La funzione Performance Management può essere utilizzata con qualsiasi algoritmo ed è possibile impiegarla facilmente al posto delle primitive standard di IBM Quantum. Dietro le quinte, diverse tecniche di soppressione degli errori operano in sinergia per impedire che si verifichino errori durante l'esecuzione. Tutti i metodi di pipeline di Fire Opal sono preconfigurati e indipendenti dall'algoritmo, il che significa che si ottengono sempre le migliori prestazioni fin da subito.

Per accedere alla Gestione delle prestazioni, contattate Q-CTRL.


Descrizione

Fire Opal Performance Management offre due opzioni di esecuzione simili alle primitive di “ IBM Quantum ”, consentendo di sostituire facilmente il campionatore e lo stimatore di Q-CTRL. Il flusso di lavoro generale per l'utilizzo della funzione "Gestione delle prestazioni" è il seguente:

  1. Definire il circuito (e gli operatori nel caso dell'Estimatore).
  2. Eseguire il circuito.
  3. Recuperare i risultati.

Per ridurre il rumore dell'hardware, Fire Opal impiega una serie di tecniche di soppressione degli errori guidate dall'intelligenza artificiale, illustrate nell'immagine seguente. Con Fire Opal, l'intera pipeline è completamente automatizzata e non richiede alcuna configurazione.

La pipeline di Fire Opal elimina la necessità di ulteriori spese generali, come l'aumento del tempo di esecuzione quantistica o l'aggiunta di qubit fisici. Si noti che il tempo di elaborazione classica rimane un fattore (per le stime si rimanda alla sezione Benchmark, dove "Tempo totale" riflette sia l'elaborazione classica che quella quantistica). A differenza della mitigazione degli errori, che richiede un overhead sotto forma di campionamento, la soppressione degli errori di Fire Opal agisce sia a livello di gate che di impulsi per affrontare le varie fonti di rumore e prevenire la probabilità che si verifichi un errore. Prevenendo gli errori, si elimina la necessità di una costosa post-elaborazione.

L'immagine seguente illustra i metodi di soppressione degli errori automatizzati da Fire Opal Performance Management.

Visualizzazione della pipeline di soppressione degli errori

La funzione offre due primitive, Sampler ed Estimator, e gli input e gli output di entrambe estendono le specifiche implementate per le primitive IBM Quantum V2.


Benchmark

I risultati dei benchmark algoritmici pubblicati dimostrano un significativo miglioramento delle prestazioni di vari algoritmi, tra cui Bernstein-Vazirani, la trasformata di Fourier quantistica, la ricerca di Grover, l'algoritmo di ottimizzazione approssimativo quantistico e l'eigensolver variazionale quantistico. Il resto di questa sezione fornisce maggiori dettagli sui tipi di algoritmi che è possibile eseguire, nonché sulle prestazioni e sui tempi di esecuzione previsti.

I seguenti studi indipendenti dimostrano come la gestione delle prestazioni di Q-CTRL consenta la ricerca algoritmica su scala record:

La tabella seguente fornisce una guida approssimativa sull'accuratezza e sui tempi di esecuzione di precedenti analisi comparative su ibm_fez. Le prestazioni su altri dispositivi possono variare. Il tempo di utilizzo si basa su un'ipotesi di 10.000 colpi per circuito. Il "Numero di qubit" indicato non è un limite rigido, ma rappresenta una soglia approssimativa in cui ci si può aspettare una precisione di soluzione estremamente costante. Sono stati risolti con successo problemi di dimensioni maggiori e si incoraggia la sperimentazione oltre questi limiti.

Esempio
Numero di qubit
Accuratezza
Misura della precisione
Tempo totale
Utilizzo del tempo di esecuzione (s)
Primitivo (modalità)
Bernstein-Vazirani50Q100%Tasso di successo (percentuale di esecuzioni in cui la risposta corretta è la stringa di bit con conteggio più alto)108Campionatore
Trasformata quantistica di Fourier30Q100%Tasso di successo (percentuale di esecuzioni in cui la risposta corretta è la stringa di bit con conteggio più alto)108Campionatore
Stima quantistica della fase30Q99.9998%Precisione dell'angolo trovato: 1- abs(real_angle - angle_found)/pi108Campionatore
Simulazione quantistica: Modello di Ising (15 passi)20Q99.775%AA (definito di seguito)60 (per passo)15 (per passo)Stimatore
Simulazione quantistica 2: dinamica molecolare (20 punti temporali)34Q96.78%AmeanA_{mean} (definito di seguito)10 (per punto temporale)6 (per punto temporale)Stimatore

Definizione dell'accuratezza della misurazione di un valore di aspettativa - la metrica AA è definita come segue:

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

dove ϵideal\epsilon^{ideal} = valore di aspettativa ideale, ϵmeas\epsilon^{meas} = valore di aspettativa misurato, ϵmaxideal\epsilon^{ideal}_{max} = valore massimo ideale e ϵminideal\epsilon^{ideal}_{min} = valore minimo ideale. AmeanA_{mean} è semplicemente la media del valore di AA su più misurazioni.

Questa metrica viene utilizzata perché è invariante rispetto agli spostamenti globali e alla scalatura nell'intervallo dei valori raggiungibili. In altre parole, indipendentemente dal fatto che si sposti la gamma dei possibili valori di aspettativa più in alto o più in basso o che si aumenti lo spread, il valore di AA dovrebbe rimanere costante.


Introduzione

Fire Opal Performance Management utilizza Qiskit v2.0.0, che è la versione consigliata. Le versioni supportate sono Qiskit >=v2.0.0. Autenticati utilizzando la tua chiave API IBM Quantum Platform e seleziona la funzione Qiskit come segue. (Questo frammento di codice presuppone che tu abbia già salvato il tuo account nell'ambiente locale.)

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")
Questa funzione supporta tutti i backend di IBM?

Se desideri utilizzare un backend che questa funzione non supporta al momento, contatta Q-CTRL per richiedere l'aggiunta del supporto.


Primitiva di stima

Esempio di stimatore

Utilizzare la primitiva Estimator di Fire Opal Performance Management per determinare il valore atteso di una singola coppia circuito-osservabile.

Oltre ai pacchetti qiskit-ibm-catalog e qiskit , per eseguire questo esempio si utilizzerà anche il pacchetto numpy . È possibile installare questo pacchetto decommentando la seguente cella se si esegue questo esempio in un notebook che utilizza il kernel IPython.

# %pip install numpy

1. Creare il circuito

A titolo di esempio, generare un operatore Hermitiano casuale e un osservabile da inserire nella funzione Performance Management.

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. Eseguire il circuito

Eseguire il circuito e definire facoltativamente il backend e il numero di colpi.

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

È possibile utilizzare le note API di Qiskit Serverless per verificare lo stato del carico di lavoro della funzione Qiskit:

qctrl_estimator_job.status()

Output:

'QUEUED'

3. Recuperare il risultato

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

I risultati hanno lo stesso formato dei risultati di 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

Primitiva campionatore

Esempio di campionatore

Utilizzate la primitiva Sampler di Fire Opal Performance Management per eseguire un circuito Bernstein-Vazirani. Questo algoritmo, utilizzato per trovare una stringa nascosta dalle uscite di una funzione black box, è un comune algoritmo di benchmarking perché esiste una sola risposta corretta.

1. Creare il circuito

Definire la risposta corretta all'algoritmo, alla stringa di bit nascosta e al circuito Bernstein-Vazirani. È possibile regolare l'ampiezza del circuito cambiando semplicemente 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. Eseguire il circuito

Eseguire il circuito e definire facoltativamente il backend e il numero di colpi.

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

Per verificare lo stato del carico di lavoro della funzione Qiskit o per ottenere i risultati, procedere come segue:

# 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. Recuperare il risultato

# 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. Tracciare le migliori stringhe di bit

Tracciare la stringa di bit con i conteggi più alti per vedere se la stringa di bit nascosta era la modalità.

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 bitstring nascosta è evidenziata in viola e dovrebbe essere la bitstring con il maggior numero di conteggi.

plot_top_bitstrings(counts, hidden_bitstring)

Output:

Output of the previous code cell

Log di modifica

  • 2026-02-20: Avviso di obsolescenza - il campo provider_job_ids metadata sarà deprecato tra 30 giorni nella versione 0.13.0 Gli utenti possono accedere all'ID del processo tramite job_id() il metodo del servizio runtime.
  • 11/02/2026: Ora supportiamo ibm_miamie abbiamo aggiunto i metadati di esecuzione al PubResult.

Ottenere supporto

Per qualsiasi domanda o problema, contattare Q-CTRL.


Passi successivi

Suggerimenti
Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.