Skip to main content
IBM Quantum Platform

Imposta il livello di ottimizzazione del transpiler

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

    qiskit[all]~=2.5.1
    qiskit-ibm-runtime~=0.47.0
    

I dispositivi quantistici reali sono soggetti a rumore ed errori di gate, quindi l'ottimizzazione dei circuiti per ridurre la profondità e il numero di gate può migliorare significativamente i risultati ottenuti dall'esecuzione di tali circuiti. La funzione generate_preset_pass_manager ha un argomento posizionale obbligatorio, optimization_level, che controlla quanto sforzo il transpiler dedica all'ottimizzazione dei circuiti. Questo argomento può essere un numero intero che assume uno dei valori 0, 1, 2 o 3. Livelli di ottimizzazione più elevati generano circuiti più ottimizzati a scapito di tempi di compilazione più lunghi. La tabella seguente spiega le ottimizzazioni eseguite con ciascuna impostazione.

Livello di ottimizzazione
Descrizione
0

Nessuna ottimizzazione: tipicamente utilizzato per la caratterizzazione dell'hardware

  • Traduzione di base
  • Layout/Routing: TrivialLayout dove seleziona gli stessi numeri di qubit fisici e virtuali e inserisce degli SWAP per farli funzionare (usando SabreSwap)
1

Ottimizzazione della luce:

  • Layout/Instradamento: Il layout viene prima tentato con TrivialLayout. Se sono necessari ulteriori SWAP, si trova un layout con un numero minimo di SWAP usando SabreSwap, quindi si usa VF2LayoutPostLayout per cercare di selezionare i migliori qubit nel grafo.
  • InverseCancellation
  • 1Q ottimizzazione del gate
2

Ottimizzazione media:

  • Layout/Instradamento: Ottimizzazione di livello 1 (senza banalità) + euristica ottimizzata con maggiore profondità di ricerca e prove della funzione di ottimizzazione profondità di ricerca e prove della funzione di ottimizzazione. Poiché non viene utilizzato TrivialLayout , non si cerca di utilizzare lo stesso numero di qubit fisici e virtuali.
  • CommutativeCancellation
3

Ottimizzazione elevata:

  • Ottimizzazione di livello 2 + euristica ottimizzata su layout/routing con maggiore impegno/trials
  • Sintesi di blocchi a due qubit utilizzando la decomposizione KAK di Cartan.
  • Passaggi di rottura dell'unità:
    • OptimizeSwapBeforeMeasure: Sposta le misure per evitare gli SWAP
    • RemoveDiagonalGatesBeforeMeasure: Rimuove le porte prima delle misurazioni che non influiscono su di esse

Livello di ottimizzazione in azione

Poiché le porte a due equbit sono tipicamente la fonte più significativa di errori, possiamo quantificare approssimativamente l'"efficienza hardware" della transpilazione contando il numero di porte a due equbit nel circuito risultante. Qui proveremo i diversi livelli di ottimizzazione su un circuito di ingresso costituito da un unitario casuale seguito da una porta SWAP.

from qiskit import QuantumCircuit
from qiskit.circuit.library import UnitaryGate
from qiskit.quantum_info import Operator, random_unitary

UU = random_unitary(4, seed=12345)
rand_U = UnitaryGate(UU)

qc = QuantumCircuit(2)
qc.append(rand_U, range(2))
qc.swap(0, 1)
qc.draw("mpl", style="iqp")

Output:

Output of the previous code cell
Note

In questi esempi viene utilizzato il backend FakeSherbrooke``qiskit_ibm_runtime fittizio di, ma è possibile provarlo su qualsiasi backend reale o fittizio compatibile con Qiskit. I tuoi risultati potrebbero essere diversi.

Per prima cosa, proviamo a traspilare utilizzando il livello di ottimizzazione 0.

from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

backend = FakeSherbrooke()

pass_manager = generate_preset_pass_manager(
    optimization_level=0, backend=backend, seed_transpiler=12345
)
qc_t1_exact = pass_manager.run(qc)
qc_t1_exact.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Il circuito transpilato ha sei porte ECR a due qubit.

Ripetere l'operazione per il livello di ottimizzazione 1:

from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

backend = FakeSherbrooke()

pass_manager = generate_preset_pass_manager(
    optimization_level=1, backend=backend, seed_transpiler=12345
)
qc_t1_exact = pass_manager.run(qc)
qc_t1_exact.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Il circuito transpilato ha ancora sei porte ECR, ma il numero di porte a singolo qubit si è ridotto.

Ripetere l'operazione per il livello di ottimizzazione 2:

pass_manager = generate_preset_pass_manager(
    optimization_level=2, backend=backend, seed_transpiler=12345
)
qc_t2_exact = pass_manager.run(qc)
qc_t2_exact.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Si ottengono così gli stessi risultati del livello di ottimizzazione 1. Si noti che l'aumento del livello di ottimizzazione non sempre fa la differenza.

Ripetere nuovamente l'operazione con il livello di ottimizzazione 3:

pass_manager = generate_preset_pass_manager(
    optimization_level=3, backend=backend, seed_transpiler=12345
)
qc_t3_exact = pass_manager.run(qc)
qc_t3_exact.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Ora ci sono solo tre porte ECR. Otteniamo questo risultato perché al livello di ottimizzazione 3, Qiskit cerca di risintetizzare blocchi di porte a due qubit e qualsiasi porta a due qubit può essere implementata utilizzando al massimo tre porte ECR. Si può ottenere un numero ancora minore di porte ECR se si imposta approximation_degree a un valore inferiore a 1, consentendo al transpiler di effettuare approssimazioni che possono introdurre qualche errore nella decomposizione delle porte (vedere Parametri comunemente usati per la transpilazione ):

pass_manager = generate_preset_pass_manager(
    optimization_level=3,
    approximation_degree=0.99,
    backend=backend,
    seed_transpiler=12345,
)
qc_t3_approx = pass_manager.run(qc)
qc_t3_approx.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Questo circuito ha solo due porte ECR, ma è un circuito approssimativo. Per capire in che modo il suo effetto differisce dal circuito esatto, possiamo calcolare la fedeltà tra l'operatore unitario che questo circuito implementa e l'operatore unitario esatto. Prima di eseguire il calcolo, riduciamo il circuito transpilato, che contiene 127 qubit, a un circuito che contiene solo i qubit attivi, che sono due.

import numpy as np


def trace_to_fidelity_2q(trace: float) -> float:
    return (4.0 + trace * trace.conjugate()) / 20.0


# Reduce circuits down to 2 qubits so they are easy to simulate
qc_t3_exact_small = QuantumCircuit.from_instructions(qc_t3_exact)
qc_t3_approx_small = QuantumCircuit.from_instructions(qc_t3_approx)

# Compute the fidelity
exact_fid = trace_to_fidelity_2q(
    np.trace(np.dot(Operator(qc_t3_exact_small).adjoint().data, UU))
)
approx_fid = trace_to_fidelity_2q(
    np.trace(np.dot(Operator(qc_t3_approx_small).adjoint().data, UU))
)
print(
    f"Synthesis fidelity\nExact: {exact_fid:.3f}\nApproximate: {approx_fid:.3f}"
)

Output:

Synthesis fidelity
Exact: 1.000+0.000j
Approximate: 0.992+0.000j

La regolazione del livello di ottimizzazione può modificare anche altri aspetti del circuito, non solo il numero di porte ECR. Per alcuni esempi di come la modifica del livello di ottimizzazione influisca sulla struttura, consultare la sezione "Rappresentazione dei computer quantistici".


Passi successivi

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