คลาส Operator
Package versions
The code on this page was developed using the following requirements. We recommend using these versions or newer.
qiskit[all]~=2.4.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")
โปรดทราบว่าในตัวอย่างข้างต้น 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 สอง ตัว และ สามารถรวมกันเป็น tensor product operator ได้โดยใช้ฟังก์ชัน Operator.tensor โปรดทราบว่าถ้าทั้ง และ เป็น single-qubit operator แล้ว A.tensor(B) = จะมี subsystem ที่ index ว่าเมทริกซ์ อยู่ที่ subsystem 0 และเมทริกซ์ อยู่ที่ 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 สองตัว และ คุณจะได้ A.expand(B) = โดย subsystem จะ index ว่าเมทริกซ์ อยู่ที่ subsystem 0 และเมทริกซ์ อยู่ที่ 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 สองตัว และ เพื่อทำการคูณเมทริกซ์โดยใช้เมธอด Operator.compose โดย A.compose(B) คืนค่า operator ที่มีเมทริกซ์ :
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 ในลำดับย้อนกลับได้โดยใช้ ด้านหน้า ผ่าน kwarg front ของ compose: A.compose(B, front=True) = :
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 แรก เท่ากับ input dimension รวมของ operator ที่ compose (และในทำนองเดียวกัน output dimension ของ ต้องเท่ากับ input dimension ของ เมื่อ 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
ขั้นตอนถัดไป
- สำรวจ reference Operator API