דלג לתוכן הראשי

סקירת מחלקות אופרטורים

Package versions

The code on this page was developed using the following requirements. We recommend using these versions or newer.

qiskit[all]~=2.3.0

ב-Qiskit, אופרטורים קוונטיים מיוצגים באמצעות מחלקות ממודול quantum_info. מחלקת האופרטור החשובה ביותר היא SparsePauliOp, המייצגת אופרטור קוונטי כללי כצירוף לינארי של מחרוזות Pauli. SparsePauliOp היא המחלקה הנפוצה ביותר לייצוג משתנים קוונטיים הניתנים לצפייה. שאר הדף מסביר כיצד להשתמש ב-SparsePauliOp ובמחלקות אופרטורים אחרות.

# 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

המחלקה SparsePauliOp מייצגת צירוף לינארי של מחרוזות Pauli. ישנן מספר דרכים לאתחל SparsePauliOp, אך הדרך הגמישה ביותר היא להשתמש במתודה from_sparse_list, כפי שמודגם בתא הקוד הבא. ה-from_sparse_list מקבל רשימה של טריאדות (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 תומך בפעולות חשבוניות, כפי שמודגם בתא הקוד הבא.

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

המחלקה Pauli מייצגת מחרוזת Pauli בודדת עם מקדם פאזה אופציונלי מהקבוצה {+1,i,1,i}\set{+1, i, -1, -i}. ניתן לאתחל Pauli על ידי העברת מחרוזת תווים מהקבוצה {"I", "X", "Y", "Z"}, עם קידומת אופציונלית אחת מ-{"", "i", "-", "-i"} לייצוג מקדם הפאזה.

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

תא הקוד הבא מדגים את השימוש בכמה מאפיינים ומתודות.

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

לאובייקטי Pauli יש מספר מתודות נוספות למניפולציה של האופרטורים כגון קביעת הצמוד שלו, האם הוא (אנטי)מתחלף עם Pauli אחר, וחישוב המכפלה הפנימית עם Pauli אחר. עיין בתיעוד ה-API למידע נוסף.

Operator

המחלקה Operator מייצגת אופרטור לינארי כללי. בניגוד ל-SparsePauliOp, ה-Operator שומר את האופרטור הלינארי כמטריצה צפופה. מכיוון שהזיכרון הנדרש לאחסון מטריצה צפופה גדל באופן אקספוננציאלי עם מספר ה-Qubits, מחלקת Operator מתאימה רק לשימוש עם מספר קטן של Qubits.

אתה יכול לאתחל Operator על ידי העברת מערך Numpy המאחסן את המטריצה של האופרטור. לדוגמה, תא הקוד הבא יוצר אופרטור Pauli XX דו-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))

אובייקט האופרטור שומר את המטריצה הבסיסית, וממדי הקלט והפלט של תת-מערכות.

  • data: לגישה למערך Numpy הבסיסי, ניתן להשתמש במאפיין Operator.data.
  • dims: להחזרת ממד הקלט והפלט הכולל של האופרטור, ניתן להשתמש במאפיין Operator.dim. שים לב: הפלט מוחזר כ-tuple (input_dim, output_dim), שהוא ההיפך מצורת המטריצה הבסיסית.
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)

מחלקת האופרטור עוקבת גם אחר ממדי תת-מערכות, שניתן להשתמש בהם לרכוב אופרטורים יחד. ניתן לגשת אליהם באמצעות הפונקציות input_dims ו-output_dims.

עבור אופרטורים בגודל 2N2^N על 2M2^M, ממדי הקלט והפלט מונחים אוטומטית להיות M-Qubit ו-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,)

אם מטריצת הקלט אינה ניתנת לחלוקה לתת-מערכות של Qubit, היא תישמר כאופרטור של Qubit בודד. לדוגמה, עבור מטריצה 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,)

ניתן גם לציין ידנית את ממד הקלט והפלט בעת אתחול אופרטור חדש:

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

אתה יכול גם לחלץ רק את ממדי הקלט או הפלט של תת-קבוצת תת-מערכות באמצעות הפונקציות input_dims ו-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,)

השלבים הבאים