Vai al contenuto principale
Questo progetto è in fase beta. Hai trovato un bug? Apri una issue su GitHub. Hai una domanda o un'idea? Chiedi su GitHub Discussions — apprezziamo il tuo feedback!
Com'è la qualità della traduzione su questa pagina?

Panoramica delle classi di operatori

Versioni dei pacchetti

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

qiskit[all]~=2.5.2

In Qiskit, gli operatori quantistici sono rappresentati usando classi del modulo quantum_info. La classe di operatori più importante è SparsePauliOp, che rappresenta un operatore quantistico generale come combinazione lineare di stringhe di Pauli. SparsePauliOp è la classe più comunemente usata per rappresentare gli osservabili quantistici. Il resto di questa pagina spiega come usare SparsePauliOp e altre classi di operatori.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
import numpy as np
from qiskit.quantum_info.operators import Operator, Pauli, SparsePauliOp

SparsePauliOp​

La classe SparsePauliOp rappresenta una combinazione lineare di stringhe di Pauli. Esistono diversi modi per inizializzare un SparsePauliOp, ma il più flessibile è usare il metodo from_sparse_list, come mostrato nella cella di codice seguente. from_sparse_list accetta una lista di triplette (pauli_string, qubit_indices, coefficient).

op1 = SparsePauliOp.from_sparse_list(
[("ZX", [1, 4], 1.0), ("YY", [0, 3], -1 + 1j)], num_qubits=5
)
op1
SparsePauliOp(['XIIZI', 'IYIIY'],
coeffs=[ 1.+0.j, -1.+1.j])

SparsePauliOp supporta operazioni aritmetiche, come mostrato nella cella di codice seguente.

op2 = SparsePauliOp.from_sparse_list(
[("XXZ", [0, 1, 4], 1 + 2j), ("ZZ", [1, 2], -1 + 1j)], num_qubits=5
)

# Addition
print("op1 + op2:")
print(op1 + op2)
print()
# Multiplication by a scalar
print("2 * op1:")
print(2 * op1)
print()
# Operator multiplication (composition)
print("op1 @ op2:")
print(op1 @ op2)
print()
# Tensor product
print("op1.tensor(op2):")
print(op1.tensor(op2))
op1 + op2:
SparsePauliOp(['XIIZI', 'IYIIY', 'ZIIXX', 'IIZZI'],
coeffs=[ 1.+0.j, -1.+1.j, 1.+2.j, -1.+1.j])

2 * op1:
SparsePauliOp(['XIIZI', 'IYIIY'],
coeffs=[ 2.+0.j, -2.+2.j])

op1 @ op2:
SparsePauliOp(['YIIYX', 'XIZII', 'ZYIXZ', 'IYZZY'],
coeffs=[ 1.+2.j, -1.+1.j, -1.+3.j, 0.-2.j])

op1.tensor(op2):
SparsePauliOp(['XIIZIZIIXX', 'XIIZIIIZZI', 'IYIIYZIIXX', 'IYIIYIIZZI'],
coeffs=[ 1.+2.j, -1.+1.j, -3.-1.j, 0.-2.j])

Pauli​

La classe Pauli rappresenta una singola stringa di Pauli con un coefficiente di fase opzionale appartenente all'insieme { +1,i,−1,−i }\set{+1, i, -1, -i}. Un oggetto Pauli può essere inizializzato passando una stringa di caratteri dall'insieme {"I", "X", "Y", "Z"}, preceduta facoltativamente da uno dei prefissi {"", "i", "-", "-i"} per indicare il coefficiente di fase.

op1 = Pauli("iXX")
op1
Pauli('iXX')

La cella di codice seguente mostra l'uso di alcuni attributi e metodi.

print(f"Dimension of {op1}: {op1.dim}")
print(f"Phase of {op1}: {op1.phase}")
print(f"Matrix representation of {op1}: \n {op1.to_matrix()}")
Dimension of iXX: (4, 4)
Phase of iXX: 3
Matrix representation of iXX:
[[0.+0.j 0.+0.j 0.+0.j 0.+1.j]
[0.+0.j 0.+0.j 0.+1.j 0.+0.j]
[0.+0.j 0.+1.j 0.+0.j 0.+0.j]
[0.+1.j 0.+0.j 0.+0.j 0.+0.j]]

Gli oggetti Pauli dispongono di numerosi altri metodi per manipolare gli operatori, come determinarne l'aggiunto, verificare se (anti)commuta con un altro Pauli, e calcolare il prodotto scalare con un altro Pauli. Consulta la documentazione delle API per ulteriori informazioni.

Operator​

La classe Operator rappresenta un operatore lineare generale. A differenza di SparsePauliOp, Operator memorizza l'operatore lineare come matrice densa. Poiché la memoria necessaria per memorizzare una matrice densa cresce esponenzialmente con il numero di qubit, la classe Operator è adatta solo per un numero ridotto di qubit.

Puoi inizializzare un Operator passando direttamente un array Numpy che contiene la matrice dell'operatore. Ad esempio, la cella di codice seguente crea un operatore Pauli XX a due qubit:

XX = Operator(
np.array(
[
[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0],
[1, 0, 0, 0],
]
)
)
XX
Operator([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
[0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]],
input_dims=(2, 2), output_dims=(2, 2))

L'oggetto operatore memorizza la matrice sottostante e le dimensioni di input e output dei sottosistemi.

  • data: Per accedere all'array Numpy sottostante, puoi usare la proprietà Operator.data.

  • dim: Per restituire la dimensione totale di input e output dell'operatore, puoi usare la proprietà Operator.dim. Nota: l'output viene restituito come tupla (input_dim, output_dim), che è in ordine inverso rispetto alla forma (shape) della matrice sottostante.

XX.data
array([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
[0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]])
input_dim, output_dim = XX.dim
input_dim, output_dim
(4, 4)

La classe degli operatori tiene traccia anche delle dimensioni dei sottosistemi, che possono essere usate per comporre operatori insieme. È possibile accedervi tramite le funzioni input_dims e output_dims.

Per gli operatori 2N×2M2^N \times 2^M, le dimensioni di input e output vengono automaticamente considerate rispettivamente di M e N qubit:

op = Operator(np.random.rand(2**1, 2**2))
print("Input dimensions:", op.input_dims())
print("Output dimensions:", op.output_dims())
Input dimensions: (2, 2)
Output dimensions: (2,)

Se la matrice di input non è divisibile in sottosistemi di qubit, verrà memorizzata come operatore a singolo qubit. Ad esempio, per una matrice 6×66\times6:

op = Operator(np.random.rand(6, 6))
print("Input dimensions:", op.input_dims())
print("Output dimensions:", op.output_dims())
Input dimensions: (6,)
Output dimensions: (6,)

Le dimensioni di input e output possono anche essere specificate manualmente durante l'inizializzazione di un nuovo operatore:

# Force input dimension to be (4,) rather than (2, 2)
op = Operator(np.random.rand(2**1, 2**2), input_dims=[4])
print("Input dimensions:", op.input_dims())
print("Output dimensions:", op.output_dims())
Input dimensions: (4,)
Output dimensions: (2,)
# Specify system is a qubit and qutrit
op = Operator(np.random.rand(6, 6), input_dims=[2, 3], output_dims=[2, 3])
print("Input dimensions:", op.input_dims())
print("Output dimensions:", op.output_dims())
Input dimensions: (2, 3)
Output dimensions: (2, 3)

Puoi anche estrarre solo le dimensioni di input o output di un sottoinsieme di sottosistemi usando le funzioni input_dims e output_dims:

print("Dimension of input system 0:", op.input_dims([0]))
print("Dimension of input system 1:", op.input_dims([1]))
Dimension of input system 0: (2,)
Dimension of input system 1: (3,)

Passi successivi​

Raccomandazioni