Skip to main content
IBM Quantum Platform

TeNPy backend basato su livelli

qiskit_addon_mpf.backends.tenpy_layers

Un backend a evoluzione temporale a strati che utilizza tenpy.

Attenzione

La dipendenza opzionale TeNPy era precedentemente offerta con una licenza GPLv3. A partire dal rilascio di v1.0.4 il 2 ottobre 2024, è stato offerto con la licenza Apache v2. La licenza di questo pacchetto è compatibile solo con le versioni con licenza Apache di TeNPy.

Avvertenza

Questo backend è disponibile solo se sono state installate le dipendenze opzionali:

pip install "qiskit-addon-mpf[tenpy]"
LayerwiseEvolverUn caso particolare di TEBDEvolver basato su modelli di evoluzione a strati.
LayerModelUn modello per rappresentare uno strato di interazioni tempo-evoluzione.

Metodo sottostante

Questo modulo fornisce un backend a evoluzione temporale simile a quello basato su TEBD fornito dal modulo tenpy_tebd modulo. La differenza principale è che questo modulo offre all'utente la massima flessibilità nella definizione delle formule dei prodotti, senza limitarsi alle opzioni della libreria tenpy libreria.

Nella sua essenza, l'algoritmo fornito da questo modulo è ancora un algoritmo TEBD [1]. Tuttavia, invece di imporre l'aggiornamento alternato dei legami pari e dispari dello stato di evoluzione temporale (vedi anche evolve_step()), questa implementazione affida la responsabilità di aggiornare i legami in modo alternato alla definizione di più livelli di evoluzione temporale.

Questo si spiega meglio con un esempio. Supponiamo di avere una generica hamiltoniana che agisce su una catena di siti a 1 dimensione.

Suggerimento

Qui di seguito si fa molta attenzione all'ordine dei termini di Pauli dell'Hamiltoniana, perché questo ha un impatto diretto sulla struttura del circuito di evoluzione del tempo in seguito.

>>> from qiskit.quantum_info import SparsePauliOp
>>> hamil = SparsePauliOp.from_sparse_list(
...     [("ZZ", (i, i+1), 1.0) for i in range(1, 9, 2)] +
...     [("Z", (i,), 0.5) for i in range(10)] +
...     [("ZZ", (i, i+1), 1.0) for i in range(0, 9, 2)],
...     num_qubits=10,
... )

Esaminiamo ora il circuito di evoluzione temporale di questa hamiltoniana utilizzando una formula di Suzuki-Trotter del secondo ordine.

>>> from qiskit.synthesis import SuzukiTrotter
>>> from qiskit_addon_utils.problem_generators import generate_time_evolution_circuit
>>> circuit = generate_time_evolution_circuit(hamil, time=1.0, synthesis=SuzukiTrotter(order=2))
>>> circuit.draw("mpl")  
<Figure size 956...x869... with 1 Axes>
Output del codice precedente.

Nel circuito qui sopra, possiamo identificare chiaramente la sua struttura a strati. Possiamo enfatizzare ulteriormente questo aspetto, suddividendo il circuito in più strati come mostrato di seguito (ricombiniamo il layers in un unico circuito con barriere tra di loro per facilitare la visualizzazione).

>>> from qiskit_addon_utils.slicing import combine_slices, slice_by_gate_types
>>> layers = slice_by_gate_types(circuit)
>>> combine_slices(layers, include_barriers=True).draw("mpl")  
<Figure size 1374...x869... with 1 Axes>
Output del codice precedente.
Suggerimento

L'asimmetria degli strati centrali è il risultato dell'applicazione della formula di Qiskit SuzukiTrotter formula di Qiskit. Nella sua forma del secondo ordine, combina le due evoluzioni semitemporali del termine finale dell'Hamiltoniana in un'unica evoluzione di lunghezza doppia. Potremmo transpilare questo circuito per far collassare tutte le porte subequenti nei due strati centrali (proprio come l'ultimo), ma per la semplicità di questo esempio non lo faremo qui.

Non è possibile istruire l'algoritmo TeNPy’s TEBD per simulare l'esatta struttura del circuito mostrato sopra. Il motivo è una limitazione della sua interfaccia, in quanto accetta solo l'intera hamiltoniana da fornire, che viene poi evoluta nel tempo utilizzando formule di Trotter predefinite. Tuttavia, in questo modo non tratta l'ordine dei termini di Pauli in un'hamiltoniana con alcun significato (come facciamo qui).

Se si desidera calcolare i coefficienti dinamici MPF di un'evoluzione temporale utilizzando una struttura di formule di prodotto diversa da quelle implementate in TeNPy (come l'esempio precedente), si può utilizzare l'algoritmo di evoluzione temporale fornito da questo modulo. Piuttosto che prendere una singola hamiltoniana monolitica di cui si vuole modellare l'evoluzione temporale, il programma LayerwiseEvolver accetta un elenco di oggetti LayerModel ognuno dei quali descrive un singolo livello della formula del prodotto. In questo modo l'utente ha la possibilità di definire la decomposizione di Trotter fino al livello più granulare.

Tuttavia, occorre prestare attenzione affinché sia garantita la proprietà del TEBD di aggiornare alternativamente i titoli pari e dispari. Fortunatamente, per i circuiti quantistici costituiti al massimo da porte a due qubit, questa proprietà è soddisfatta per costruzione.


Esempio di codice

In questa sezione, si sviluppa l'esempio precedente e si mostra come prendere una formula di Trotter personalizzata e utilizzarla per costruire un elemento LayerwiseEvolver che può essere utilizzato per sostituire la formula tenpy_tebd.TEBDEvolver nel flusso di lavoro descritto in tenpy_tebd.

Suggerimento

Il flusso di lavoro complessivo per l'utilizzo di questo modulo è lo stesso del modulo tenpy_tebd quindi si consiglia di leggere anche queste istruzioni.

In parole povere, dobbiamo convertire ciascuno dei circuiti layers (vedi sopra) in una LayerModel istanza. A questo scopo, possiamo utilizzare il suo metodo from_quantum_circuit() metodo.

>>> from qiskit_addon_mpf.backends.tenpy_layers import LayerModel
>>> model0 = LayerModel.from_quantum_circuit(layers[0])
>>> layer_models = [model0]

Nel codice qui sopra si può vedere come la conversione sia semplice per gli strati che contengono solo porte a due qubit che agiscono su qubit mutuamente esclusivi (cosa che gli strati di profondità 1 garantiscono).

Tuttavia, dobbiamo essere più cauti con gli strati che includono porte a singolo qubit. Il motivo è che l'algoritmo TEBD che sta alla base del sistema LayerwiseEvolver deve aggiornare i legami pari e dispari in modo alternato. E poiché i gate a singolo qubit non vengono applicati su un sito, ma sono divisi a metà e applicati ai legami su entrambi i lati, uno strato di gate a singolo qubit che agisce su tutti i qubit romperebbe questa ipotesi.

Per aggirare questo problema, possiamo prendere un qualsiasi strato costituito solo da porte a singolo qubit e applicarlo due volte (una volta sui legami pari e una volta su quelli dispari).

>>> model1a = LayerModel.from_quantum_circuit(layers[1], keep_only_odd=True)
>>> model1b = LayerModel.from_quantum_circuit(layers[1], keep_only_odd=False)
>>> layer_models.extend([model1a, model1b])

Ora che sappiamo come trattare gli strati costituiti da porte a due e a un solo bit, possiamo trasformare gli strati rimanenti.

>>> for layer in layers[2:]:
...     num_qubits = len(layer.data[0].qubits)
...     if num_qubits == 2:
...         layer_models.append(LayerModel.from_quantum_circuit(layer))
...     else:
...         layer_models.append(
...             LayerModel.from_quantum_circuit(layer, keep_only_odd=True)
...         )
...         layer_models.append(
...             LayerModel.from_quantum_circuit(layer, keep_only_odd=False)
...         )
>>> assert len(layer_models) == 8

Alla fine abbiamo 8 LayerModeluno per ciascuno dei 4 strati a due bit e due per ciascuno dei 2 strati a un bit.

Infine, possiamo definire il nostro ApproxEvolverFactory da utilizzare all'interno della funzione setup_dynamic_lse() della funzione.

>>> from functools import partial
>>> from qiskit_addon_mpf.backends.tenpy_layers import LayerwiseEvolver
>>> approx_evolver_factory = partial(
...     LayerwiseEvolver,
...     layers=layer_models,
...     options={
...         "preserve_norm": False,
...         "trunc_params": {
...             "chi_max": 10,
...             "svd_min": 1e-5,
...             "trunc_cut": None,
...         },
...     },
... )
Attenzione

Va notato che in questo flusso di lavoro non abbiamo ancora fissato il passo temporale utilizzato dalla formula di Trotter. Abbiamo inoltre impostato una sola ripetizione della formula di Trotter, poiché il resto sarà fatto dall'algoritmo interno di DynamicMPF interno, eseguito durante setup_dynamic_lse().

Naturalmente, si può anche usare questo metodo per specificare un file ExactEvolverFactory. Ma è anche possibile combinare un tenpy_layers.LayerwiseEvolver con un tenpy_tebd.TEBDEvolver.


Risorse

[1]: https://en.wikipedia.org/wiki/Time-evolving _block_decimazione

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