ข้ามไปยังเนื้อหาหลัก

คลาส Operator

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

หน้านี้แสดงวิธีใช้คลาส Operator สำหรับภาพรวมระดับสูงของการแทนค่า operator ใน Qiskit รวมถึงคลาส Operator และคลาสอื่นๆ ดูที่ ภาพรวมของคลาส operator

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit
import numpy as np
from qiskit.circuit import QuantumCircuit
from qiskit.circuit.library import CXGate, RXGate, XGate
from qiskit.quantum_info import Operator, Pauli, process_fidelity

แปลงคลาสต่างๆ เป็น Operator

คลาสอื่นๆ หลายคลาสใน Qiskit สามารถแปลงเป็น object Operator ได้โดยตรงโดยใช้วิธี operator initialization ตัวอย่างเช่น:

  • object Pauli
  • object Gate และ Instruction
  • object QuantumCircuit

โปรดทราบว่าข้อสุดท้ายหมายความว่าคุณสามารถใช้คลาส Operator เป็น unitary simulator เพื่อคำนวณ unitary matrix สุดท้ายสำหรับ quantum circuit โดยไม่ต้องเรียก simulator Backend ถ้า Circuit มีการดำเนินการที่ไม่รองรับ จะเกิด exception การดำเนินการที่ไม่รองรับได้แก่: measure, reset, conditional operations หรือ Gate ที่ไม่มีนิยาม matrix หรือการแตกตัวในรูปของ Gate ที่มีนิยาม matrix

# Create an Operator from a Pauli object

pauliXX = Pauli("XX")
Operator(pauliXX)
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))
# Create an Operator for a Gate object
Operator(CXGate())
Operator([[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[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]],
input_dims=(2, 2), output_dims=(2, 2))
# Create an operator from a parameterized Gate object
Operator(RXGate(np.pi / 2))
Operator([[0.70710678+0.j        , 0.        -0.70710678j],
[0. -0.70710678j, 0.70710678+0.j ]],
input_dims=(2,), output_dims=(2,))
# Create an operator from a QuantumCircuit object
circ = QuantumCircuit(10)
circ.h(0)
for j in range(1, 10):
circ.cx(j - 1, j)

# Convert circuit to an operator by implicit unitary simulation
Operator(circ)
Operator([[ 0.70710678+0.j,  0.70710678+0.j,  0.        +0.j, ...,
0. +0.j, 0. +0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0.70710678+0.j, ...,
0. +0.j, 0. +0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0. +0.j, ...,
0. +0.j, 0. +0.j, 0. +0.j],
...,
[ 0. +0.j, 0. +0.j, 0. +0.j, ...,
0. +0.j, 0. +0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0.70710678+0.j, ...,
0. +0.j, 0. +0.j, 0. +0.j],
[ 0.70710678+0.j, -0.70710678+0.j, 0. +0.j, ...,
0. +0.j, 0. +0.j, 0. +0.j]],
input_dims=(2, 2, 2, 2, 2, 2, 2, 2, 2, 2), output_dims=(2, 2, 2, 2, 2, 2, 2, 2, 2, 2))

ใช้ Operator ใน Circuit

Operator แบบ unitary สามารถแทรกเข้าไปใน QuantumCircuit ได้โดยตรงโดยใช้เมธอด QuantumCircuit.append ซึ่งจะแปลง Operator เป็น object UnitaryGate แล้วเพิ่มเข้าไปใน Circuit

ถ้า operator ไม่ใช่ unitary จะเกิด exception สามารถตรวจสอบได้โดยใช้ฟังก์ชัน Operator.is_unitary() ซึ่งคืนค่า True ถ้า operator เป็น unitary และ False หากไม่ใช่

# Create an operator
XX = Operator(Pauli("XX"))

# Add to a circuit
circ = QuantumCircuit(2, 2)
circ.append(XX, [0, 1])
circ.measure([0, 1], [0, 1])
circ.draw("mpl")

Output of the previous code cell

โปรดทราบว่าในตัวอย่างข้างต้น operator ถูก initialize จาก object Pauli แต่ object Pauli ก็สามารถแทรกเข้าไปใน Circuit โดยตรงได้เช่นกันและจะถูกแปลงเป็นลำดับของ single-qubit Pauli Gate:

# Add to a circuit
circ2 = QuantumCircuit(2, 2)
circ2.append(Pauli("XX"), [0, 1])
circ2.measure([0, 1], [0, 1])
circ2.draw()
┌────────────┐┌─┐
q_0: ┤0 ├┤M├───
│ Pauli(XX) │└╥┘┌─┐
q_1: ┤1 ├─╫─┤M├
└────────────┘ ║ └╥┘
c: 2/═══════════════╩══╩═
0 1

รวม Operator

Operator สามารถรวมกันได้หลายวิธี

Tensor product

Operator สอง ตัว AA และ BB สามารถรวมกันเป็น tensor product operator ABA\otimes B ได้โดยใช้ฟังก์ชัน Operator.tensor โปรดทราบว่าถ้าทั้ง AA และ BB เป็น single-qubit operator แล้ว A.tensor(B) = ABA\otimes B จะมี subsystem ที่ index ว่าเมทริกซ์ BB อยู่ที่ subsystem 0 และเมทริกซ์ AA อยู่ที่ subsystem 1

A = Operator(Pauli("X"))
B = Operator(Pauli("Z"))
A.tensor(B)
Operator([[ 0.+0.j,  0.+0.j,  1.+0.j,  0.+0.j],
[ 0.+0.j, -0.+0.j, 0.+0.j, -1.+0.j],
[ 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[ 0.+0.j, -1.+0.j, 0.+0.j, -0.+0.j]],
input_dims=(2, 2), output_dims=(2, 2))

Tensor expansion

การดำเนินการที่เกี่ยวข้องใกล้ชิดคือ Operator.expand ซึ่งทำงานเหมือน tensor product แต่ในลำดับย้อนกลับ ดังนั้น สำหรับ operator สองตัว AA และ BB คุณจะได้ A.expand(B) = BAB\otimes A โดย subsystem จะ index ว่าเมทริกซ์ AA อยู่ที่ subsystem 0 และเมทริกซ์ BB อยู่ที่ subsystem 1

A = Operator(Pauli("X"))
B = Operator(Pauli("Z"))
A.expand(B)
Operator([[ 0.+0.j,  1.+0.j,  0.+0.j,  0.+0.j],
[ 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[ 0.+0.j, 0.+0.j, -0.+0.j, -1.+0.j],
[ 0.+0.j, 0.+0.j, -1.+0.j, -0.+0.j]],
input_dims=(2, 2), output_dims=(2, 2))

Composition

คุณยังสามารถ compose operator สองตัว AA และ BB เพื่อทำการคูณเมทริกซ์โดยใช้เมธอด Operator.compose โดย A.compose(B) คืนค่า operator ที่มีเมทริกซ์ B.AB.A:

A = Operator(Pauli("X"))
B = Operator(Pauli("Z"))
A.compose(B)
Operator([[ 0.+0.j,  1.+0.j],
[-1.+0.j, 0.+0.j]],
input_dims=(2,), output_dims=(2,))

คุณยังสามารถ compose ในลำดับย้อนกลับได้โดยใช้ BB ด้านหน้า AA ผ่าน kwarg front ของ compose: A.compose(B, front=True) = A.BA.B:

A = Operator(Pauli("X"))
B = Operator(Pauli("Z"))
A.compose(B, front=True)
Operator([[ 0.+0.j, -1.+0.j],
[ 1.+0.j, 0.+0.j]],
input_dims=(2,), output_dims=(2,))

Subsystem composition

โปรดทราบว่า compose ก่อนหน้าต้องการให้ output dimension รวมของ operator แรก AA เท่ากับ input dimension รวมของ operator ที่ compose BB (และในทำนองเดียวกัน output dimension ของ BB ต้องเท่ากับ input dimension ของ AA เมื่อ compose ด้วย front=True)

คุณยังสามารถ compose operator ขนาดเล็กกว่ากับ subsystem ที่เลือกของ operator ขนาดใหญ่กว่าได้โดยใช้ kwarg qargs ของ compose ไม่ว่าจะใช้หรือไม่ใช้ front=True ในกรณีนี้ input และ output dimension ที่เกี่ยวข้องของ subsystem ที่ถูก compose ต้องตรงกัน โปรดทราบว่า operator ขนาดเล็กต้องเป็น argument ของเมธอด compose เสมอ

ตัวอย่างเช่น การ compose two-qubit Gate กับ three-qubit operator:

# Compose XZ with a 3-qubit identity operator
op = Operator(np.eye(2**3))
XZ = Operator(Pauli("XZ"))
op.compose(XZ, qargs=[0, 2])
Operator([[ 0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  1.+0.j,  0.+0.j,  0.+0.j,
0.+0.j],
[ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j, 0.+0.j,
0.+0.j],
[ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j,
0.+0.j],
[ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
-1.+0.j],
[ 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
0.+0.j],
[ 0.+0.j, -1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
0.+0.j],
[ 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
0.+0.j],
[ 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
0.+0.j]],
input_dims=(2, 2, 2), output_dims=(2, 2, 2))
# Compose YX in front of the previous operator
op = Operator(np.eye(2**3))
YX = Operator(Pauli("YX"))
op.compose(YX, qargs=[0, 2], front=True)
Operator([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j, 0.+0.j, 0.+0.j],
[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j, 0.+0.j, 0.+0.j, 0.+0.j],
[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j],
[0.+0.j, 0.+0.j, 0.+0.j, 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.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[0.+0.j, 0.+0.j, 0.+0.j, 0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
[0.+0.j, 0.+0.j, 0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]],
input_dims=(2, 2, 2), output_dims=(2, 2, 2))

การรวมเชิงเส้น

Operator ยังสามารถรวมกันได้โดยใช้ตัวดำเนินการเชิงเส้นมาตรฐานสำหรับการบวก การลบ และการคูณสเกลาร์ด้วยจำนวนเชิงซ้อน

XX = Operator(Pauli("XX"))
YY = Operator(Pauli("YY"))
ZZ = Operator(Pauli("ZZ"))

op = 0.5 * (XX + YY - 3 * ZZ)
op
Operator([[-1.5+0.j,  0. +0.j,  0. +0.j,  0. +0.j],
[ 0. +0.j, 1.5+0.j, 1. +0.j, 0. +0.j],
[ 0. +0.j, 1. +0.j, 1.5+0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0. +0.j, -1.5+0.j]],
input_dims=(2, 2), output_dims=(2, 2))

สิ่งสำคัญคือ ในขณะที่ tensor, expand และ compose รักษาความเป็น unitary ของ unitary operator ไว้ แต่การรวมเชิงเส้นไม่รักษา ดังนั้น การบวก unitary operator สองตัวโดยทั่วไปจะได้ผลลัพธ์เป็น non-unitary operator:

op.is_unitary()
False

การแปลงโดยนัยเป็น Operator

โปรดทราบว่าสำหรับเมธอดต่อไปนี้ทั้งหมด ถ้า object ที่สองยังไม่ใช่ object Operator จะถูกแปลงเป็น Operator โดยนัยผ่านเมธอดนั้น ซึ่งหมายความว่าสามารถส่งเมทริกซ์เข้าไปได้โดยตรงโดยไม่ต้องแปลงเป็น Operator ก่อนอย่างชัดเจน ถ้าไม่สามารถแปลงได้ จะเกิด exception

# Compose with a matrix passed as a list
Operator(np.eye(2)).compose([[0, 1], [1, 0]])
Operator([[0.+0.j, 1.+0.j],
[1.+0.j, 0.+0.j]],
input_dims=(2,), output_dims=(2,))

เปรียบเทียบ Operator

Operator มีเมธอดความเท่าเทียมที่ใช้ตรวจสอบว่า operator สองตัวเท่ากันโดยประมาณหรือไม่

Operator(Pauli("X")) == Operator(XGate())
True

โปรดทราบว่านี่จะตรวจสอบว่าแต่ละ element ของเมทริกซ์ของ operator เท่ากันโดยประมาณ unitary สองตัวที่ต่างกันเพียง global phase จะไม่ถือว่าเท่ากัน:

Operator(XGate()) == np.exp(1j * 0.5) * Operator(XGate())
False

Process fidelity

คุณยังสามารถเปรียบเทียบ operator โดยใช้ฟังก์ชัน process_fidelity จากโมดูล Quantum Information นี่คือปริมาณเชิงทฤษฎีสารสนเทศที่บอกว่า quantum channel สองช่องมีความใกล้เคียงกันแค่ไหน และในกรณีของ unitary operator จะไม่ขึ้นอยู่กับ global phase

# Two operators which differ only by phase
op_a = Operator(XGate())
op_b = np.exp(1j * 0.5) * Operator(XGate())

# Compute process fidelity
F = process_fidelity(op_a, op_b)
print("Process fidelity =", F)
Process fidelity = 1.0

โปรดทราบว่า process fidelity โดยทั่วไปเป็นตัวชี้วัดความใกล้เคียงที่ถูกต้องก็ต่อเมื่อ operator input เป็น unitary (หรือ CP ในกรณีของ quantum channel) และจะเกิด exception ถ้า input ไม่ใช่ CP

ขั้นตอนถัดไป

คำแนะนำ
Source: IBM Quantum docs — updated 27 เม.ย. 2569
English version on doQumentation — updated 7 พ.ค. 2569
This translation based on the English version of 11 มี.ค. 2569