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

การใช้งาน Qiskit

ในส่วนนี้ เราจะดูการใช้งาน Qiskit บางส่วนของแนวคิดที่แนะนำในบทเรียนนี้ ถ้าต้องการรันการใช้งานเหล่านี้เอง ซึ่งแนะนำอย่างยิ่ง ให้ดูหน้า Install Qiskit ใน IBM Quantum Documentation สำหรับรายละเอียดวิธีตั้งค่า Qiskit

ควรเข้าใจว่า Qiskit อยู่ภายใต้การพัฒนาอย่างต่อเนื่อง และมุ่งเน้นหลักในการเพิ่มประสิทธิภาพของคอมพิวเตอร์ควอนตัมที่ใช้งาน ซึ่งตัวคอมพิวเตอร์เองก็ยังคงพัฒนาต่อไป ด้วยเหตุนี้ Qiskit จึงอาจมีการเปลี่ยนแปลงที่อาจทำให้โค้ดล้าสมัยได้เป็นครั้งคราว โดยคำนึงถึงสิ่งนี้ เราจะรันคำสั่งต่อไปนี้เสมอก่อนนำเสนอตัวอย่างโค้ด Qiskit ในคอร์สนี้ เพื่อให้ชัดเจนว่าใช้ Qiskit เวอร์ชันใด เริ่มต้นจาก Qiskit v1.0 นี่เป็นวิธีง่ายๆ ในการดูว่าติดตั้ง Qiskit เวอร์ชันใดอยู่ในปัจจุบัน

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit
from qiskit import __version__

print(__version__)
2.1.1

ถ้ารันสิ่งนี้ในสภาพแวดล้อม Python บนคลาวด์ อาจต้องติดตั้งแพ็คเกจต่อไปนี้บางส่วน:

#!pip install qiskit
#!pip install jupyter
#!pip install sympy
#!pip install matplotlib
#!pip install pylatexenc

เวกเตอร์และเมทริกซ์ใน Python

Qiskit ใช้ภาษาโปรแกรม Python ดังนั้นก่อนที่จะพูดถึง Qiskit โดยเฉพาะ อาจเป็นประโยชน์ที่จะพูดถึงการคำนวณเมทริกซ์และเวกเตอร์ใน Python สั้นๆ

ใน Python การคำนวณเมทริกซ์และเวกเตอร์สามารถทำได้โดยใช้คลาส array จากไลบรารี NumPy ซึ่งมีฟังก์ชันสำหรับการคำนวณเชิงตัวเลขและวิทยาศาสตร์หลายอย่าง โค้ดต่อไปนี้โหลดไลบรารีนี้ กำหนดเวกเตอร์คอลัมน์สองอัน ket0 และ ket1 ที่สอดคล้องกับเวกเตอร์สถานะ Qubit 0\vert 0\rangle และ 1,\vert 1\rangle, แล้วพิมพ์ค่าเฉลี่ยของพวกมัน

import numpy as np

ket0 = np.array([[1], [0]])
ket1 = np.array([[0], [1]])

print(ket0 / 2 + ket1 / 2)
[[0.5]
[0.5]]

เราสามารถใช้ array เพื่อสร้างเมทริกซ์ที่แทนการดำเนินการได้ด้วย

M1 = np.array([[1, 1], [0, 0]])
M2 = np.array([[1, 0], [0, 1]])
M = M1 / 2 + M2 / 2
print(M)
[[1.  0.5]
[0. 0.5]]

โปรดทราบว่าโค้ดทั้งหมดที่ปรากฏในบทเรียนที่กำหนดในคอร์สนี้คาดว่าจะรันตามลำดับ ดังนั้น เราไม่จำเป็นต้องนำเข้า NumPy อีกที่นี่ เพราะนำเข้าแล้ว

การคูณเมทริกซ์ รวมถึงการคูณเมทริกซ์-เวกเตอร์เป็นกรณีพิเศษ สามารถทำได้โดยใช้ฟังก์ชัน matmul จาก NumPy

print(np.matmul(M1, ket1))
print(np.matmul(M1, M2))
print(np.matmul(M, M))
[[1]
[0]]
[[1 1]
[0 0]]
[[1. 0.75]
[0. 0.25]]

รูปแบบ output นี้ยังมีข้อบกพร่องในแง่ภาพ ทางออกหนึ่ง สำหรับสถานการณ์ที่ต้องการความสวยงามมากกว่า คือใช้ฟังก์ชัน array_to_latex ใน Qiskit จากโมดูล qiskit.visualization สังเกตว่าในโค้ดที่ตามมา เราใช้ฟังก์ชัน display ทั่วไปของ Python ในทางตรงกันข้าม พฤติกรรมเฉพาะของ print อาจขึ้นอยู่กับสิ่งที่พิมพ์ เช่น เป็นกรณีของ array ที่กำหนดโดย NumPy

from qiskit.visualization import array_to_latex

display(array_to_latex(np.matmul(M1, ket1)))
display(array_to_latex(np.matmul(M1, M2)))
display(array_to_latex(np.matmul(M, M)))
[10] \begin{bmatrix} 1 \\ 0 \\ \end{bmatrix} [1100] \begin{bmatrix} 1 & 1 \\ 0 & 0 \\ \end{bmatrix} [134014] \begin{bmatrix} 1 & \frac{3}{4} \\ 0 & \frac{1}{4} \\ \end{bmatrix}

สถานะ การวัด และการดำเนินการ

Qiskit รวมคลาสหลายอย่างที่ช่วยให้สร้างและจัดการสถานะ การวัด และการดำเนินการได้ — ดังนั้นไม่จำเป็นต้องเขียนโปรแกรมทุกอย่างที่จำเป็นสำหรับการจำลองสถานะ การวัด และการดำเนินการเชิงควอนตัมใน Python เอง ตัวอย่างเพื่อช่วยให้เริ่มต้นได้มีด้านล่าง

กำหนดและแสดงเวกเตอร์สถานะ

คลาส Statevector ใน Qiskit ให้ฟังก์ชันสำหรับการกำหนดและจัดการเวกเตอร์สถานะควอนตัม ในโค้ดที่ตามมา คลาส Statevector ถูกนำเข้าและกำหนดเวกเตอร์ไม่กี่อัน (เราก็นำเข้าฟังก์ชัน sqrt จากไลบรารี NumPy เพื่อคำนวณรากที่สองด้วย ฟังก์ชันนี้สามารถเรียกใช้เป็น np.sqrt ได้เช่นกัน หาก NumPy ถูกนำเข้าแล้วดังเช่นด้านบน นี่เป็นเพียงวิธีที่แตกต่างในการนำเข้าและใช้ฟังก์ชันเฉพาะนี้)

from qiskit.quantum_info import Statevector
from numpy import sqrt

u = Statevector([1 / sqrt(2), 1 / sqrt(2)])
v = Statevector([(1 + 2.0j) / 3, -2 / 3])
w = Statevector([1 / 3, 2 / 3])

คลาส Statevector มีเมธอด draw สำหรับแสดงเวกเตอร์สถานะในหลายวิธี รวมถึง text สำหรับข้อความธรรมดา latex สำหรับ LaTeX ที่ render แล้ว และ latex_source สำหรับโค้ด LaTeX ซึ่งสะดวกสำหรับการตัดและวางลงในเอกสาร (ใช้ print แทน display เพื่อแสดงโค้ด LaTeX ให้ได้ผลลัพธ์ที่ดีที่สุด)

display(u.draw("text"))
display(u.draw("latex"))
print(u.draw("latex_source"))
[0.70710678+0.j,0.70710678+0.j]

220+221\frac{\sqrt{2}}{2} |0\rangle+\frac{\sqrt{2}}{2} |1\rangle

\frac{\sqrt{2}}{2} |0\rangle+\frac{\sqrt{2}}{2} |1\rangle

คลาส Statevector ยังมีเมธอด is_valid ซึ่งตรวจสอบว่าเวกเตอร์ที่กำหนดเป็นเวกเตอร์สถานะควอนตัมที่ถูกต้องหรือไม่ (กล่าวคือมี Euclidean norm เท่ากับ 1):

display(u.is_valid())
display(w.is_valid())
True
False

การจำลองการวัดโดยใช้ Statevector

ต่อไปเราจะเห็นวิธีหนึ่งที่การวัดสถานะควอนตัมสามารถจำลองได้ใน Qiskit โดยใช้เมธอด measure จากคลาส Statevector มาใช้เวกเตอร์สถานะ Qubit v เดิมที่กำหนดไว้ก่อนหน้า

display(v.draw("latex"))

(13+2i3)0231(\frac{1}{3} + \frac{2 i}{3}) |0\rangle- \frac{2}{3} |1\rangle

การรันเมธอด measure จำลองการวัดฐานมาตรฐาน มันคืนผลลัพธ์ของการวัดนั้น รวมถึงเวกเตอร์สถานะควอนตัมใหม่ของระบบหลังการวัด (ที่นี่เราใช้ฟังก์ชัน print ของ Python ที่มีคำนำหน้า f สำหรับการพิมพ์แบบจัดรูปแบบพร้อมนิพจน์ที่ฝังอยู่)

outcome, state = v.measure()
print(f"Measured: {outcome}\nPost-measurement state:")
display(state.draw("latex"))
Measured: 1
Post-measurement state:

1- |1\rangle

ผลลัพธ์การวัดเป็นแบบความน่าจะเป็น ดังนั้นเมธอดนี้สามารถคืนผลลัพธ์ที่แตกต่างกันเมื่อรันหลายครั้ง สำหรับตัวอย่างเฉพาะของเวกเตอร์ v ที่กำหนดไว้ด้านบน เมธอด measure กำหนดเวกเตอร์สถานะควอนตัมหลังการวัดเป็น

(1+2i5)0\biggl(\frac{1 + 2i}{\sqrt{5}}\biggr) \vert 0\rangle

(แทนที่จะเป็น 0\vert 0\rangle) หรือ

1- \vert 1\rangle

(แทนที่จะเป็น 1\vert 1\rangle) ขึ้นอยู่กับผลการวัด ในทั้งสองกรณี ทางเลือกแทน 0\vert 0\rangle และ 1\vert 1\rangle นั้น ที่จริงแล้วเทียบเท่ากับเวกเตอร์สถานะเหล่านี้ พวกมันถูกกล่าวว่า เทียบเท่าจนถึง global phase เพราะอันหนึ่งเท่ากับอีกอันคูณด้วยจำนวนเชิงซ้อนบนวงกลมหน่วย ประเด็นนี้ถูกกล่าวถึงในรายละเอียดเพิ่มเติมในบทเรียน Quantum circuits และสามารถละเลยได้ก่อนในตอนนี้

Statevector จะโยน error หากใช้เมธอด measure กับเวกเตอร์สถานะควอนตัมที่ไม่ถูกต้อง

Statevector ยังมีเมธอด sample_counts ที่ช่วยให้จำลองการวัดจำนวนใดก็ได้บนระบบ โดยแต่ละครั้งเริ่มต้นด้วยสำเนาใหม่ของสถานะ ตัวอย่างเช่น โค้ดต่อไปนี้แสดงผลลัพธ์ของการวัดเวกเตอร์ v 10001000 ครั้ง ซึ่ง (ด้วยความน่าจะเป็นสูง) ส่งผลให้ผลลัพธ์ 00 ประมาณ 55 ใน 99 ครั้ง (หรือประมาณ 556556 จาก 10001000 ครั้ง) และผลลัพธ์ 11 ประมาณ 44 ใน 99 ครั้ง (หรือประมาณ 444444 จาก 10001000 ครั้ง) โค้ดที่ตามมายังแสดงฟังก์ชัน plot_histogram จากโมดูล qiskit.visualization สำหรับการแสดงผลลัพธ์

from qiskit.visualization import plot_histogram

statistics = v.sample_counts(1000)
plot_histogram(statistics)

Output of the previous code cell

การรันโค้ดนี้หลายครั้งด้วยตัวเอง โดยใช้จำนวนตัวอย่างต่างๆ แทน 10001000 อาจช่วยสร้างสัญชาตญาณว่าจำนวนครั้งส่งผลต่อจำนวนครั้งที่ผลลัพธ์แต่ละอย่างปรากฏอย่างไร ยิ่งมีตัวอย่างมากขึ้นเรื่อยๆ สัดส่วนของตัวอย่างสำหรับแต่ละความเป็นไปได้น่าจะใกล้เคียงกับความน่าจะเป็นที่สอดคล้องกันมากขึ้นเรื่อยๆ ปรากฏการณ์นี้ โดยทั่วไปแล้ว เรียกว่า กฎของจำนวนมาก ในทฤษฎีความน่าจะเป็น

ทำการดำเนินการด้วย Operator และ Statevector

การดำเนินการ unitary สามารถกำหนดใน Qiskit โดยใช้คลาส Operator ดังในตัวอย่างที่ตามมา คลาสนี้มีเมธอด draw ที่มี argument คล้ายกับ Statevector สังเกตว่าตัวเลือก latex ให้ผลลัพธ์ที่เทียบเท่ากับ array_from_latex

from qiskit.quantum_info import Operator

Y = Operator([[0, -1.0j], [1.0j, 0]])
H = Operator([[1 / sqrt(2), 1 / sqrt(2)], [1 / sqrt(2), -1 / sqrt(2)]])
S = Operator([[1, 0], [0, 1.0j]])
T = Operator([[1, 0], [0, (1 + 1.0j) / sqrt(2)]])

display(T.draw("latex"))
[10022+2i2] \begin{bmatrix} 1 & 0 \\ 0 & \frac{\sqrt{2}}{2} + \frac{\sqrt{2} i}{2} \\ \end{bmatrix}

เราสามารถใช้การดำเนินการ unitary กับเวกเตอร์สถานะโดยใช้เมธอด evolve

v = Statevector([1, 0])

v = v.evolve(H)
v = v.evolve(T)
v = v.evolve(H)
v = v.evolve(S)
v = v.evolve(Y)

display(v.draw("latex"))

(0.14644660940.3535533906i)0+(0.3535533906+0.8535533906i)1(0.1464466094 - 0.3535533906 i) |0\rangle+(-0.3535533906 + 0.8535533906 i) |1\rangle

ตัวอย่างเบื้องต้นของ Circuit ควอนตัม

Circuit ควอนตัมจะไม่ถูกแนะนำอย่างเป็นทางการจนถึงบทเรียน Quantum circuits ซึ่งเป็นบทเรียนที่สามในคอร์สนี้ แต่เราสามารถทดลองการเรียงลำดับการดำเนินการ unitary ของ Qubit โดยใช้คลาส QuantumCircuit ใน Qiskit ได้ โดยเฉพาะอย่างยิ่ง เราอาจกำหนด Circuit ควอนตัม (ซึ่งในกรณีนี้จะเป็นเพียงลำดับของการดำเนินการ unitary บน Qubit เดี่ยว) ดังนี้

from qiskit import QuantumCircuit

circuit = QuantumCircuit(1)

circuit.h(0)
circuit.t(0)
circuit.h(0)
circuit.s(0)
circuit.y(0)

display(circuit.draw(output="mpl"))

Output of the previous code cell

ที่นี่เราใช้เมธอด draw จากคลาส QuantumCircuit กับ renderer mpl (ย่อมาจาก Matplotlib ไลบรารีการแสดงผลของ Python) นี่เป็น renderer เดียวที่เราจะใช้สำหรับ Circuit ควอนตัมในคอร์สนี้ แต่มีตัวเลือกอื่นรวมถึง renderer แบบข้อความและ LaTeX

การดำเนินการถูกใช้ตามลำดับ เริ่มจากซ้ายและสิ้นสุดที่ขวาในแผนภาพ วิธีที่สะดวกในการได้เมทริกซ์ unitary ที่สอดคล้องกับ Circuit นี้คือใช้เมธอด from_circuit จากคลาส Operator

display(Operator.from_circuit(circuit).draw("latex"))
[0.14644660940.3535533906i0.8535533906+0.3535533906i0.3535533906+0.8535533906i0.3535533906+0.1464466094i] \begin{bmatrix} 0.1464466094 - 0.3535533906 i & 0.8535533906 + 0.3535533906 i \\ -0.3535533906 + 0.8535533906 i & 0.3535533906 + 0.1464466094 i \\ \end{bmatrix}

เราสามารถเริ่มต้นเวกเตอร์สถานะควอนตัมเริ่มต้นแล้ว evolve สถานะนั้นตามลำดับการดำเนินการที่อธิบายโดย Circuit ได้ด้วย

ket0 = Statevector([1, 0])
v = ket0.evolve(circuit)
display(v.draw("latex"))

(0.14644660940.3535533906i)0+(0.3535533906+0.8535533906i)1(0.1464466094 - 0.3535533906 i) |0\rangle+(-0.3535533906 + 0.8535533906 i) |1\rangle

โค้ดต่อไปนี้จำลองการทดลองที่สถานะที่ได้จาก Circuit ด้านบนถูกวัดด้วยการวัดฐานมาตรฐาน 4000 ครั้ง (โดยใช้สำเนาใหม่ของสถานะแต่ละครั้ง)

statistics = v.sample_counts(4000)
display(plot_histogram(statistics))

Output of the previous code cell

Source: IBM Quantum docs — updated 5 พ.ค. 2569
English version on doQumentation — updated 7 พ.ค. 2569
This translation based on the English version of approx. 26 มี.ค. 2569