Vue d'ensemble des classes d'opérateurs
Versions des packages
Le code de cette page a été développé avec les versions suivantes. Nous recommandons d'utiliser ces versions ou des versions plus récentes.
qiskit[all]~=2.3.0
Dans Qiskit, les opérateurs quantiques sont représentés à l'aide des classes du module quantum_info. La classe d'opérateur la plus importante est SparsePauliOp, qui représente un opérateur quantique général sous la forme d'une combinaison linéaire de chaînes de Pauli. SparsePauliOp est la classe la plus couramment utilisée pour représenter des observables quantiques. Le reste de cette page explique comment utiliser SparsePauliOp et d'autres classes d'opérateurs.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit
import numpy as np
from qiskit.quantum_info.operators import Operator, Pauli, SparsePauliOp
SparsePauliOp
La classe SparsePauliOp représente une combinaison linéaire de chaînes de Pauli. Il existe plusieurs façons d'initialiser un SparsePauliOp, mais la plus flexible est d'utiliser la méthode from_sparse_list, comme illustré dans la cellule de code suivante. La méthode from_sparse_list accepte une liste de triplets (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 prend en charge les opérations arithmétiques, comme illustré dans la cellule de code suivante.
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 représente une seule chaîne de Pauli avec un coefficient de phase optionnel appartenant à l'ensemble . Un objet Pauli peut être initialisé en passant une chaîne de caractères de l'ensemble {"I", "X", "Y", "Z"}, éventuellement préfixée par l'un des éléments {"", "i", "-", "-i"} pour représenter le coefficient de phase.
op1 = Pauli("iXX")
op1
Pauli('iXX')
La cellule de code suivante illustre l'utilisation de certains attributs et méthodes.
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]]
Les objets Pauli disposent de nombreuses autres méthodes pour manipuler les opérateurs, notamment pour déterminer l'adjoint, vérifier s'il (anti)commute avec un autre Pauli, ou calculer le produit scalaire avec un autre Pauli. Consulte la documentation de l'API pour plus d'informations.
Operator
La classe Operator représente un opérateur linéaire général. Contrairement à SparsePauliOp, Operator stocke l'opérateur linéaire sous forme de matrice dense. Étant donné que la mémoire nécessaire pour stocker une matrice dense croît de façon exponentielle avec le nombre de qubits, la classe Operator n'est adaptée qu'à un petit nombre de qubits.
Tu peux initialiser un Operator en passant directement un tableau Numpy contenant la matrice de l'opérateur. Par exemple, la cellule de code suivante crée un opérateur Pauli XX à deux qubits :
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'objet opérateur stocke la matrice sous-jacente ainsi que les dimensions d'entrée et de sortie des sous-systèmes.
data: Pour accéder au tableau Numpy sous-jacent, tu peux utiliser la propriétéOperator.data.dims: Pour obtenir les dimensions totales d'entrée et de sortie de l'opérateur, tu peux utiliser la propriétéOperator.dim. Remarque : le résultat est retourné sous forme de tuple(input_dim, output_dim), ce qui est l'inverse de la forme de la matrice sous-jacente.
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 Operator garde également trace des dimensions des sous-systèmes, ce qui peut être utile pour composer des opérateurs entre eux. Ces informations sont accessibles via les fonctions input_dims et output_dims.
Pour les opérateurs de taille par , les dimensions d'entrée et de sortie sont automatiquement supposées correspondre à M qubits en entrée et N qubits en sortie :
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,)
Si la matrice d'entrée n'est pas divisible en sous-systèmes de qubits, elle sera alors stockée en tant qu'opérateur à un seul sous-système. Par exemple, pour une matrice :
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,)
Les dimensions d'entrée et de sortie peuvent également être spécifiées manuellement lors de l'initialisation d'un nouvel opérateur :
# 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)
Tu peux également extraire uniquement les dimensions d'entrée ou de sortie d'un sous-ensemble de sous-systèmes à l'aide des fonctions input_dims et 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,)
Étapes suivantes
- Apprends à spécifier des observables dans la base de Pauli.
- Consulte un exemple d'utilisation des opérateurs dans le tutoriel Combiner les options de mitigation d'erreurs avec la primitive Estimator.
- Lis une présentation approfondie de la classe Operator.
- Explore la référence de l'API Operator.