Skip to main content
IBM Quantum Platform

Panoramica delle classi di operatori

  • 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.2
    

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

import numpy as np
from qiskit.quantum_info.operators import Operator, Pauli, SparsePauliOp

SparsePauliOp

La SparsePauliOp rappresenta una combinazione lineare di stringhe Pauli. Esistono diversi modi per inizializzare un SparsePauliOp, ma il modo più flessibile è quello di utilizzare il metodo from_sparse_list come dimostra la seguente cella di codice. from_sparse_list accetta un elenco 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

Output:

SparsePauliOp(['XIIZI', 'IYIIY'],
              coeffs=[ 1.+0.j, -1.+1.j])

SparsePauliOp supporta le operazioni aritmetiche, come dimostra la seguente cella di codice.

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))

Output:

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 Pauli con un coefficiente di fase opzionale dall'insieme { +1,i,−1,−i }\set{+1, i, -1, -i}. Una Pauli può essere inizializzata passando una stringa di caratteri dell'insieme {"I", "X", "Y", "Z"}, eventualmente preceduta da uno degli {"", "i", "-", "-i"} per rappresentare il coefficiente di fase.

op1 = Pauli("iXX")
op1

Output:

Pauli('iXX')

La seguente cella di codice dimostra 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()}")

Output:

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]]

Pauli gli oggetti possiedono una serie di altri metodi per manipolare gli operatori, come ad esempio determinare il suo adjoint, se (anti)commuta con un altro Pauli, e calcolare il prodotto di punti con un altro Pauli. Per maggiori informazioni, consultare la documentazione API.


Operatore

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

È possibile inizializzare un Operator passando direttamente un array Numpy che memorizza la matrice dell'operatore. Ad esempio, la seguente cella di codice 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

Output:

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 la dimensione di ingresso e di uscita dei sottosistemi.

  • data: Per accedere all'array Numpy sottostante, è possibile utilizzare la proprietà Operator.data .
  • dim: Per ottenere le dimensioni totali di ingresso e uscita dell'operatore, è possibile utilizzare la proprietà Operator.dim . *Nota: il risultato viene restituito come tupla *(input_dim, output_dim), la cui forma è l'inverso di quella della matrice sottostante.
XX.data

Output:

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

Output:

(4, 4)

La classe operatore tiene anche traccia delle dimensioni del sottosistema, che possono essere utilizzate per comporre gli operatori tra loro. È possibile accedervi utilizzando le funzioni input_dims e output_dims .

Per 2N2^N da parte degli operatori di 2M2^M, le dimensioni di ingresso e di uscita sono automaticamente assunte come M-qubit e N-qubit:

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

Output:

Input dimensions: (2, 2)
Output dimensions: (2,)

Se la matrice di ingresso 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())

Output:

Input dimensions: (6,)
Output dimensions: (6,)

La dimensione di ingresso e di uscita può anche essere specificata manualmente quando si inizializza 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())

Output:

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())

Output:

Input dimensions: (2, 3)
Output dimensions: (2, 3)

È inoltre possibile estrarre solo le dimensioni di ingresso o di uscita di un sottoinsieme di sottosistemi utilizzando 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]))

Output:

Dimension of input system 0: (2,)
Dimension of input system 1: (3,)

Passi successivi

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