Search
Progetto finale: Pauli Twirling

Progetto finale: Pauli twirling

Il Pauli twirling, noto anche come compilazione randomizzata, è una fase comune applicata prima di molte tecniche di mitigazione del rumore utilizzate nel campo dell’informatica quantistica. Con il Pauli twirling è possibile trasformare i canali di rumore generici in canali di Pauli stocastici, che presentano un modello relativamente semplice, mantenendo al contempo inalterato il circuito logico.

In questo progetto finale esploreremo l’effetto del Pauli twirling sui diversi canali di rumore trattati nel corso, implementeremo una classe di esperimento personalizzata da utilizzare in combinazione con altre classi di qiskit-experiments e simuleremo l’effetto del Pauli twirling sui canali di rumore.

Il Pauli twirling è stato introdotto per la prima volta come compilazione randomizzata in J. Wallman e J. Emerson, Phys. Rev. A 94, 052325 (2015). Funziona generando miscele classiche del canale di rumore con gate applicati su entrambi i lati del canale stesso. I gate sono spesso scelti tra quelli di Pauli $\{I, X, Y, Z\}$. L’azione di twirling $\mathcal{T}_i$ su un canale quantistico $\Lambda(\rho)$ è descritta come \begin{align} \mathcal{T}_i\Lambda &=\mathcal{P}_i\Lambda\mathcal{P}_i^\dagger \end{align} dove il supra-operatore $\mathcal{P}_i$ agisce su un operatore \begin{align} \mathcal{P}_i\Lambda&= \sigma_i^\dagger\Lambda\sigma_i. \end{align}

Il canale risultante è quindi prodotto mediando su tutti i canali twirled sui gate scelti, nel nostro caso i gate di Pauli \begin{align} \widetilde{\Lambda} &= \frac{1}{4}\sum_{i=0}^3{\mathcal{T}_i\Lambda} \\ &= \frac{\Lambda + \mathcal{P}_{x}\Lambda \mathcal{P}_{x}^\dagger + \mathcal{P}_{y}\Lambda \mathcal{P}_{y}^\dagger + \mathcal{P}_{z} \Lambda \mathcal{P}_{z}^\dagger}{4}. \end{align}

\begin{align} \widetilde{\Lambda}(\rho) &= \frac{1}{4}\sum_{i=0}^3{\mathcal{T}_i\Lambda(\rho)} \\ &= \frac{1}{4}\sum_{i=0}^3{\mathcal{P}_i(\Lambda(\mathcal{P}_i^\dagger(\rho)))} \\ &= \frac{\Lambda \rho + \mathcal{P}_{x}\Lambda \mathcal{P}_{x}^\dagger \rho + \mathcal{P}_{y}\Lambda \mathcal{P}_{y}^\dagger \rho + \mathcal{P}_{z} \Lambda \mathcal{P}_{z}^\dagger \rho}{4}. \end{align}

Iniziamo con una matrice dnesità $\rho$ e applichiamo un canale $\lambda$ su di essa: $$\Lambda \rho = \Lambda(\rho)$$ Poi, ruotiamo (twirl) solo il canale: $$\widetilde{\Lambda} = \mathcal{T}_i\Lambda = \mathcal{P}_i\Lambda\mathcal{P}_i^\dagger$$ Quando applichiamo questo nuovo canale nuovamente su $\rho$ otteniamo $$\widetilde{\Lambda}(\rho) = \mathcal{P}_i\Lambda\mathcal{P}_i^\dagger\rho = \mathcal{P}_i(\Lambda(\mathcal{P}_i^\dagger(\rho))).$$ Il supra-operatore di Pauli a destra agisce sull'input che canale di twirling e non sul canale stesso.

from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
import numpy as np

Attività 1 (7 punti)

Calcola algebricamente il canel risultante dopo aver applicato il twirling su:

1) Canale bit-flip $$ \Lambda_d (\rho) = (1-p) I \rho I + p (X \rho X)$$ 2) Rotazione coerente $$ \Lambda_r (\rho) = \cos^2{\left(\frac{\theta}{2}\right)} I \rho I + \sin^2{\left(\frac{\theta}{2}\right)} X \rho X + \frac{i}{2} (\sin{(\theta)} I \rho X - \sin{(\theta)} X \rho I)$$ 3) Canale di smorzamento dell'ampiezza $$ \Lambda_a (\rho) = A_0 \rho A_0^\dagger + A_1 \rho A_1^\dagger$$ dove $A_0 = \frac{(1+\sqrt{1-p})}{2} I + \frac{(1-\sqrt{1-p})}{2} Z$ e $A_1 = \frac{\sqrt{p}}{2} (X + iY)$.

Scrivi i canali risultanti come canali di Pauli.

Attività 2 (8 punti)

Scrivi classi personalizzate per esperimenti e analisi utilizzando, ad esempio, il framework qiskit-experiments per estrarre matrici di densità dopo aver ruotato i canali di rumore tramite tomografia di stato. La classe di esperimento dovrebbe accettare come input almeno un circuito con un canale di rumore, mentre la classe di analisi dovrebbe restituire come output una matrice di densità.

Esistono molti modi possibili per implementare questa funzionalità, ma per darti un’idea da dove iniziare, ti forniamo un modello qui di seguito. La tua classe di esperimento potrebbe ereditare da BaseExperiment o TomographyExperiment e implementare i metodi __init__ e circuit per generare i circuiti necessari per il twirling di Pauli. La tua classe di analisi invece potrebbe ereditare da BaseAnalysis e implementare il metodo _run_analysis per calcolare la media dei risultati ottenuti dai diversi twirl dell’esperimento. Puoi consultare le istruzioni nella Documentazione di Qiskit-experiments per ulteriore assistenza. Qiskit-experiments è completamente open source, quindi anche dare un’occhiata al codice sorgente può essere d’aiuto.

from qiskit import QuantumCircuit
from typing import Tuple, List, Optional, Sequence
import matplotlib
from qiskit.providers.backend import Backend
from qiskit_experiments.library.tomography import TomographyExperiment
from qiskit_experiments.framework import (
    BaseAnalysis,
    Options,
    ExperimentData,
    AnalysisResultData
)

class TwirledStateTomographyAnalysis(BaseAnalysis):
    """Classe di analisi per tomografia di stato con twirling."""

    @classmethod
    def _default_options(cls) -> Options:
        """Imposta opzioni di analisi di default."""

        options = super()._default_options()
        options.plot = False
        options.ax = None
        return options

    def _run_analysis(
        self,
        experiment_data: ExperimentData
    ) -> Tuple[List[AnalysisResultData], List["matplotlib.figure.Figure"]]:
        """Esegui l'analisi."""

        data_objects = experiment_data.data()

        # Combine twirled results and perform state tomography
        result = AnalysisResultData()

        return result, []

class TwirledStateTomography(TomographyExperiment):
    """Tomografia di stato con twirling."""

    def __init__(self,
                 circuit: QuantumCircuit,
                #  add your own arguments here...
                 physical_qubits: Sequence[int] = None,
                 measurement_indices: Sequence[int] = None,
                 backend: Optional[Backend] = None):
        """Inizializza l'esperimento."""
        if physical_qubits is None:
            physical_qubits = tuple(range(circuit.num_qubits))
        super().__init__(circuit=circuit,
                        backend=backend,
                        physical_qubits=physical_qubits,
                        measurement_indices=measurement_indices,
                        analysis=TwirledStateTomographyAnalysis(),
                        )

    def circuits(self) -> List[QuantumCircuit]:
        """Genera la lista di circuiti da eseguire."""
        circuits = []
        # Genera i circuits e inserisci i metadata qui

        return circuits

    @classmethod
    def _default_experiment_options(cls) -> Options:
        """Imposta opzioni di esperimnto di default."""
        options = super()._default_experiment_options()
        return options
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[1], line 1
----> 1 from qiskit import QuantumCircuit
      2 from typing import Tuple, List, Optional, Sequence
      3 import matplotlib

ModuleNotFoundError: No module named 'qiskit'

Attività 3 (8 punti)

Inizializza un qubit in uno stato con popolazioni e coerenze diverse da zero. Applica a tale qubit ciascuno dei canali di rumore riportati di seguito ed esegui la tomografia dello stato con e senza l’applicazione del twirling al canale. Per ciascun canale di rumore, traccia sulla stessa figura $\rho_{00}$, $\rho_{11}$, $Re(\rho_{01})$, $Im(\rho_{01})$ per i casi con e senza rotazione, per diversi valori di $p$ o $\theta$.

Canali di rumore:

  • Bit-flip
    • Canale di Pauli con $(1-p, p, 0, 0)$.
  • Rotazione coerente
    • Applicare il gate RX con un angolo piccolo.
  • Canale di smorzamento di ampiezza

È possibile utilizzare i modelli di rumore implementati in qiskit_aer.noise. È inoltre consentito utilizzare le implementazioni dei canali di rumore provenienti da progetti precedenti, ma occorre tenere presente che si potrebbero verificare instabilità numeriche.

p_values = np.linspace(0, 1, 10)
theta_values = np.linspace(-np.pi, np.pi, 10)

Attività 4 (7 punti)

Infine, invertiamo o attenuiamo i canali di rumore sottoposti a twirling per estrarre la matrice di densità priva di rumore. Dopo il twirling, il canale di rumore dovrebbe assumere la forma di un canale di Pauli, che è relativamente facile da invertire se i coefficienti di rumore sono noti. Non è garantito che il canale invertito sia un canale fisico, poiché i coefficienti potrebbero essere negativi. La procedura per invertire i canali di rumore comuni è descritta in S. Mangini, et al. EPJ Quantum Technol. 9, 29 (2022).

L'inversa di un generico canale di Pauli con coefficienti $(p_{0}, p_{x}, p_{y}, p_{z})$ risulta essere $$\begin{aligned} & \Lambda^{-1}_{\boldsymbol{p}}(\Lambda) = \beta _{0} \Lambda + \beta _{1} \sigma _{x} {\Lambda} \sigma _{x} + \beta _{2} \sigma _{y} {\Lambda} \sigma _{y} + \beta _{3} \sigma _{z} {\Lambda} \sigma _{z}\quad \text{with} \\ & \beta _{0} =\frac{1}{4} \biggl(1+\frac{1}{1-2(p_{x}+p_{y})}+ \frac{1}{1-2(p_{x}+p_{z})}+\frac{1}{1-2(p_{y}+p_{z})} \biggr), \\ & \beta _{1} = \frac{1}{4} \biggl(1-\frac{1}{1-2(p_{x}+p_{y})}- \frac{1}{1-2(p_{x}+p_{z})}+\frac{1}{1-2(p_{y}+p_{z})} \biggr), \\ & \beta _{2} = \frac{1}{4} \biggl(1-\frac{1}{1-2(p_{x}+p_{y})}+ \frac{1}{1-2(p_{x}+p_{z})}-\frac{1}{1-2(p_{y}+p_{z})} \biggr), \\ & \beta _{3} = \frac{1}{4} \biggl(1+\frac{1}{1-2(p_{x}+p_{y})}- \frac{1}{1-2(p_{x}+p_{z})}-\frac{1}{1-2(p_{y}+p_{z})} \biggr) . \end{aligned}$$

Usando i coefficienti dei canali di rumore twirled dall'Attività 1, inverti ciascuna delle matrici densità che trovi nell'Attività 3 (per ogni $p$ e $\theta$) e confronta $\rho_{00}$, $\rho_{11}$, $Re(\rho_{01})$, $Im(\rho_{01})$ con quelli non invertiti (ad esempio in un plot).

Suggerimento: L'espressione si semplifica molto se sostituisci i coefficienti dell'Attività 1.