Skip to main content
IBM Quantum Platform

Ingressi e uscite dell'esecutore

  • Il codice presente in questa pagina è stato sviluppato sulla base dei seguenti requisiti. Si consiglia di utilizzare queste versioni o quelle più recenti.

    qiskit[all]~=2.4.0
    qiskit-ibm-runtime~=0.46.1
    samplomatic~=0.18.0
    

La primitiva Executor fa parte del modello di esecuzione diretta, che offre maggiore flessibilità nella personalizzazione di un flusso di lavoro per la mitigazione degli errori.

Gli ingressi e le uscite della primitiva Executor sono molto diversi da quelli delle primitive Sampler ed Estimator. Ad esempio, invece di accettare come input un elenco di PUB, Executor accetta un QuantumProgram, che contiene un elenco di QuantumProgramItem oggetti. Queste classi di contenitori offrono una maggiore flessibilità rispetto a un « PUB », che è una semplice struttura dati di tipo tupla.

L'output di Executor è un QuantumProgramResult, che è un oggetto iterabile e contiene un elemento per ogni input QuantumProgramItem.


Input: programmi Quantum

Come già detto, l'input di una primitiva Executor è un QuantumProgram, ovvero un iterabile di QuantumProgramItem oggetti. Questi oggetti possono essere di due tipi:

  • CircuitItem, che in genere contiene un circuito e i valori dei suoi parametri (se presenti).
  • SamplexItem, che in genere contiene le seguenti informazioni:
    • Un circuito modello
    • Un oggetto Samplex, utilizzato per generare insiemi casuali di parametri in fase di esecuzione (ad esempio per eseguire operazioni di twirling o per introdurre rumore)
    • Argomenti per il samplex, che potrebbero includere i valori dei parametri del circuito originale

Ciascuna di queste voci rappresenta un compito diverso che Executor deve svolgere.

Prima di iniziare

Alcuni degli esempi di codice presenti in questa pagina utilizzano samplex, che fa parte del pacchetto Samplomatic. Pertanto, prima di eseguire quei blocchi di codice, è necessario installare Samplomatic, come illustrato nel blocco di codice seguente. Per ulteriori informazioni, consultare la documentazione di Samplomatic.

pip install samplomatic

# For visualization support, include the visualization dependencies.
# pip install samplomatic[vis]

Esempio: creare un QuantumProgram con due attività diverse

Inizia inizializzando il tuo programma quantistico, quindi aggiungi elementi al programma utilizzando o append_samplex_item``append_circuit_item (se è presente un samplex), come mostrato negli esempi seguenti.

La cella seguente inizializza una variabile QuantumProgram e specifica che devono essere eseguiti 1024 test per ogni configurazione di ciascun elemento del programma.

Note

A differenza di Sampler, un QuantumProgram accetta solo un singolo valore di campionamento. QuantumProgramSe desideri un valore di esposizione diverso, ti servirà un'altra foto, il che comporterebbe un lavoro a parte.

from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.quantum_program import QuantumProgram
from qiskit_ibm_runtime import Executor, QiskitRuntimeService
from qiskit.circuit import Parameter, QuantumCircuit
import numpy as np
from samplomatic import build
from samplomatic.transpiler import generate_boxing_pass_manager

# Initialize an empty program
program = QuantumProgram(shots=1024)

# Initialize and transpile a 3-qubit quantum circuit with 2 parameters.
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.rz(Parameter("theta"), 0)
circuit.rz(Parameter("phi"), 1)

# `measure_all` adds a 3-bit classical register named "meas"
circuit.measure_all()

# Choose the least busy backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)

# Generate a preset pass manager
# This will be used to convert the abstract circuit to an
# equivalent Instruction Set Architecture (ISA) circuit.
preset_pass_manager = generate_preset_pass_manager(
    backend=backend, optimization_level=0
)

# Transpile the circuit
isa_circuit = preset_pass_manager.run(circuit)

Aggiungi un CircuitItem

Successivamente, aggiungere il circuito di destinazione, che è stato transpilato in base all'architettura del set di istruzioni (ISA) del backend, al file QuantumProgram. Poiché questo circuito ha due parametri, dobbiamo anche specificarne i valori (10 coppie in questo esempio). L'esecuzione di questa operazione CircuitItem è la prima attività che il programma eseguirà.

# Append the transpiled circuit and an array
# containing 10 sets of parameter values to the program
program.append_circuit_item(
    isa_circuit,
    circuit_arguments=np.random.rand(
        10, 2
    ),  # 10 sets of parameter values and 2 parameters
)

Aggiungi un SamplexItem

Le operazioni del circuito vengono eseguite senza alcun tipo di casualità. Al contrario, gli elementi samplex consentono di specificare come randomizzare il loro contenuto. La cella successiva utilizza la generate_boxing_pass_manager() funzione per raggruppare i gate e le misurazioni del circuito in riquadri e aggiungere un'annotazione rotante a ciascun riquadro. Genera quindi uno schema circuitale e una coppia di campioni utilizzando la build() funzione.

L'esecuzione di questa operazione SamplexItem è la seconda attività che il programma svolgerà.

Per ulteriori dettagli su samplex e i suoi argomenti, consultare la documentazione dell'API di Samplomatic. Per informazioni sull'uso della generate_boxing_pass_manager() funzione, consultare la guida di Samplomatic Transpiler.

# Transpile the circuit, additionally grouping gates and measurements into annotated boxes
preset_pass_manager = generate_preset_pass_manager(
    backend=backend, optimization_level=0
)

# Use the boxing pass manager to group gates
# and measurements into boxes and add
# a`Twirl` annotation.
preset_pass_manager.post_scheduling = generate_boxing_pass_manager(
    # Add gate twirling
    enable_gates=True,
    # Add measurement twirling
    enable_measures=True,
)
boxed_circuit = preset_pass_manager.run(circuit)

# Build the template circuit and the samplex.  The template circuit has parametric gates
# without fixed values and the samplex randomly generates the parameter
# values on the server side at runtime to perform twirling.
template_circuit, samplex = build(boxed_circuit)

# Determine what arguments are required by the samplex.
# Input the arguments in samplex_arguments.
print(samplex.inputs())

Output:

TensorInterface(<
  - 'parameter_values' <float64[2]>: Input parameter values to use during sampling.
>)
# Append the template circuit and samplex as a samplex item
program.append_samplex_item(
    template_circuit,
    samplex=samplex,
    samplex_arguments={
        # the arguments required by the samplex.sample method
        "parameter_values": np.random.rand(10, 2),
    },
    shape=(28, 10),  # 28 randomizations and 10 sets of parameter values
)
# Initialize an Executor with the default options
executor = Executor(mode=backend)

# Submit the job
job = executor.run(program)

# Retrieve the result
result = job.result()

Output

Il risultato di Executor è un QuantumProgramResult, che è un iterabile. Contiene una voce per ogni dato QuantumProgramItem immesso, nello stesso ordine in cui sono stati inseriti. Ciascuna di queste voci di output è un dizionario in cui le chiavi sono stringhe che corrispondono ai nomi dei registri classici presenti nei circuiti di input (tra gli altri); pertanto, non è più necessario memorizzare questi nomi come si faceva con l'output del Sampler. I valori del dizionario sono di tipo np.ndarray.

Il risultato dell'esempio precedente contiene i seguenti elementi:

CircuitItem risultato

La prima voce riporta i risultati dell'esecuzione della prima attività (a CircuitItem) del programma. Contiene una sola chiave, meas, che è il nome del registro classico nel circuito di ingresso. Il valore di questa chiave corrisponde a un array np.ndarray di forma (parameter sets, shots, register bits), che nell'esempio sopra riportato è (10, 1024, 3).

Il codice seguente mostra come accedere a queste informazioni:

# Access the results of the classical register of task #0, a CircuitItem
result_0 = result[0]["meas"]
print(f"Result shape: {result_0.shape}")

Output:

Result shape: (10, 1024, 3)

SamplexItem risultato

La seconda voce contiene i risultati dell'esecuzione della seconda attività (a SamplexItem) del programma. Questo articolo contiene più chiavi. La meas chiave, che corrisponde al nome del registro classico del circuito di ingresso, rimanda alla matrice dei risultati di quel registro. Questo array ha la forma (randomizations, parameter sets, shots, classical bits), ovvero (28, 10, 1024, 3) in questo esempio. Inoltre, l'output contiene una measurement_flips.meas chiave che rappresenta le correzioni di inversione di bit necessarie per annullare la rotazione della misurazione per il meas registro. In questo esempio, la dimensione dell'output sarà (28, 10, 1, 3) poiché è sufficiente un solo passaggio per eseguire il bit-flip.

# Access the results of the classical register of task #1
result_1 = result[1]["meas"]
print(f"Result shape: {result_1.shape}")

# Access the bit-flip corrections
flips_1 = result[1]["measurement_flips.meas"]
print(f"Bit-flip corrections shape: {flips_1.shape}")

# Undo the bit flips via classical XOR
unflipped_result_1 = result_1 ^ flips_1

Output:

Result shape: (28, 10, 1024, 3)
Bit-flip corrections shape: (28, 10, 1, 3)

Passi successivi

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