OpenQASM 2 และ Qiskit SDK
เวอร์ชันของ package
โค้ดในหน้านี้ถูกพัฒนาโดยใช้ requirements ต่อไปนี้ แนะนำให้ใช้เวอร์ชันเหล่านี้หรือใหม่กว่า
qiskit[all]~=2.4.0
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
Qiskit SDK มีเครื่องมือบางอย่างสำหรับการแปลงระหว่าง OpenQASM representation ของโปรแกรม quantum และ QuantumCircuit class
นำเข้าโปรแกรม OpenQASM 2 เข้าสู่ Qiskit
มีสองฟังก์ชันสำหรับนำเข้าโปรแกรม OpenQASM 2 เข้าสู่ Qiskit
ฟังก์ชันเหล่านี้คือ qasm2.load() ซึ่งรับชื่อไฟล์ และ qasm2.loads() ซึ่งรับโปรแกรม OpenQASM 2 เป็น string
import qiskit.qasm2
qiskit.qasm2.load(filename, include_path=('.',), include_input_directory='append', custom_instructions=(), custom_classical=(), strict=False)
qiskit.qasm2.loads(program, include_path=('.',), custom_instructions=(), custom_classical=(), strict=False)
ดูข้อมูลเพิ่มเติมที่ OpenQASM 2 Qiskit API
- Review the Verify your program topic.
นำเข้าโปรแกรมพื้นฐาน
สำหรับโปรแกรม OpenQASM 2 ส่วนใหญ่ สามารถใช้ qasm2.load และ qasm2.loads ด้วย argument เดียวได้
ตัวอย่าง: นำเข้าโปรแกรม OpenQASM 2 เป็น string
ใช้ qasm2.loads() เพื่อนำเข้าโปรแกรม OpenQASM 2 เป็น string เข้าสู่ QuantumCircuit:
import qiskit.qasm2
program = """
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0], q[1];
measure q -> c;
"""
circuit = qiskit.qasm2.loads(program)
circuit.draw()
┌───┐ ┌─┐
q_0: ┤ H ├──■──┤M├───
└───┘┌─┴─┐└╥┘┌─┐
q_1: ─────┤ X ├─╫─┤M├
└───┘ ║ └╥┘
c: 2/═══════════╩══╩═
0 1
ตัวอย่าง: นำเข้าโปรแกรม OpenQASM 2 จากไฟล์
ใช้ load() เพื่อนำเข้าโปรแกรม OpenQASM 2 จากไฟล์เข้าสู่ QuantumCircuit:
import qiskit.qasm2
circuit = qiskit.qasm2.load("myfile.qasm")
เชื่อมโยง Gate ของ OpenQASM 2 กับ Gate ของ Qiskit
โดยค่าเริ่มต้น importer ของ OpenQASM 2 ใน Qiskit จะถือว่าไฟล์ include "qelib1.inc" เป็น de facto standard library
importer ถือว่าไฟล์นี้ประกอบด้วย Gate ที่อธิบายไว้ใน paper ต้นฉบับที่นิยาม OpenQASM 2 อย่างแม่นยำ
Qiskit จะใช้ Gate ที่มีอยู่แล้วใน circuit library เพื่อแทน Gate ใน "qelib1.inc"
Gate ที่นิยามในโปรแกรมด้วย OpenQASM 2 gate statement โดยค่าเริ่มต้นจะถูกสร้างเป็น Qiskit Gate subclass แบบกำหนดเอง
สามารถบอก importer ให้ใช้ Gate class ที่เฉพาะเจาะจงสำหรับ gate statement ที่กำหนดได้
สามารถใช้กลไกนี้เพื่อจัดการ gate name เพิ่มเติมว่าเป็น "built-in" นั่นคือไม่ต้องมี definition ที่ชัดเจน
หากระบุ Gate class ที่จะใช้สำหรับ gate statement ที่อยู่นอก "qelib1.inc" Circuit ที่ได้จะมีประสิทธิภาพมากขึ้นในการทำงาน
ณ Qiskit SDK v1.0 exporter OpenQASM 2 ของ Qiskit (ดู Export a Qiskit circuit to OpenQASM 2) ยังคงทำงานราวกับว่า "qelib1.inc" มี Gate มากกว่าความเป็นจริง
ซึ่งหมายความว่าการตั้งค่าเริ่มต้นของ importer อาจไม่สามารถนำเข้าโปรแกรมที่ export โดย importer ของเราได้
ดู ตัวอย่างการทำงานกับ legacy exporter เพื่อแก้ปัญหานี้
ความแตกต่างนี้เป็น legacy behavior ของ Qiskit และ จะถูกแก้ไขใน release ถัดไปของ Qiskit
หากต้องการส่งข้อมูลเกี่ยวกับ custom instruction ไปยัง OpenQASM 2 importer ให้ใช้ คลาส qasm2.CustomInstruction
ต้องการข้อมูลสี่ส่วนตามลำดับ:
- ชื่อ ของ Gate ที่ใช้ในโปรแกรม OpenQASM 2
- จำนวน angle parameter ที่ Gate รับ
- จำนวน Qubit ที่ Gate ทำงานบน
- Python constructor class หรือฟังก์ชันของ Gate ซึ่งรับ Gate parameter (แต่ไม่ใช่ Qubit) เป็น argument แต่ละตัว
หาก importer พบ gate definition ที่ตรงกับ custom instruction ที่กำหนด จะใช้ข้อมูล custom นั้นเพื่อสร้าง Gate object ขึ้นใหม่
หากพบ gate statement ที่ตรงกับ name ของ custom instruction แต่ไม่ตรงกับทั้งจำนวน parameter และจำนวน Qubit importer จะ raise QASM2ParseError เพื่อระบุความไม่ตรงกันระหว่างข้อมูลที่ให้มาและโปรแกรม
นอกจากนี้ argument ที่ห้า builtin สามารถตั้งค่าเป็น True เพื่อทำให้ Gate พร้อมใช้งานโดยอัตโนมัติภายในโปรแกรม OpenQASM 2 แม้ว่าจะไม่ได้นิยามอย่างชัดเจน
หาก importer พบ gate definition ที่ชัดเจนสำหรับ built-in custom instruction จะยอมรับอย่างเงียบๆ
เช่นเดิม หากพบ definition ที่ชัดเจนของชื่อเดียวกันแต่ไม่เข้ากันกับ custom instruction ที่ให้มา จะ raise QASM2ParseError
สิ่งนี้มีประโยชน์สำหรับความเข้ากันได้กับ OpenQASM 2 exporter รุ่นเก่า และกับ quantum platform บางแห่งที่ถือว่า "basis gate" ของฮาร์ดแวร์เป็น built-in instruction
Qiskit มี data attribute สำหรับการทำงานกับโปรแกรม OpenQASM 2 ที่สร้างโดย Qiskit's OpenQASM 2 exporting capabilities รุ่นเก่า
นั่นคือ qasm2.LEGACY_CUSTOM_INSTRUCTIONS ซึ่งสามารถให้เป็น argument custom_instructions ของ qasm2.load() และ qasm2.loads()
ตัวอย่าง: นำเข้าโปรแกรมที่สร้างโดย legacy exporter ของ Qiskit
โปรแกรม OpenQASM 2 นี้ใช้ Gate ที่ไม่ได้อยู่ในเวอร์ชันต้นฉบับของ "qelib1.inc" โดยไม่มีการประกาศ แต่เป็น Gate มาตรฐานใน Qiskit library
สามารถใช้ qasm2.LEGACY_CUSTOM_INSTRUCTIONS เพื่อบอก importer ให้ใช้ Gate set เดียวกับที่ OpenQASM 2 exporter ของ Qiskit เคยใช้ได้อย่างง่ายดาย
from qiskit import qasm2
program = """
OPENQASM 2.0;
include "qelib1.inc";
qreg q[4];
creg c[4];
h q[0];
cx q[0], q[1];
// 'rxx' is not actually in `qelib1.inc`,
// but Qiskit used to behave as if it were.
rxx(0.75) q[2], q[3];
measure q -> c;
"""
circuit = qasm2.loads(
program,
custom_instructions=qasm2.LEGACY_CUSTOM_INSTRUCTIONS,
)
ตัวอย่าง: ใช้ Gate class ที่เฉพาะเจาะจงเมื่อนำเข้าโปรแกรม OpenQASM 2
Qiskit ไม่สามารถตรวจสอบได้โดยทั่วไปว่า definition ใน OpenQASM 2 gate statement ตรงกับ Qiskit standard-library gate อย่างแม่นยำหรือไม่
แทนที่ Qiskit จะเลือก custom Gate โดยใช้ definition ที่ให้มาอย่างแม่นยำ
วิธีนี้อาจมีประสิทธิภาพน้อยกว่าการใช้ standard gate ที่มีอยู่แล้ว หรือ custom Gate ที่ผู้ใช้นิยาม
สามารถนิยาม gate statement ด้วย class ที่เฉพาะเจาะจงได้ด้วยตนเอง
from qiskit import qasm2
from qiskit.circuit import Gate
from qiskit.circuit.library import RZXGate
# Define a custom gate that takes one qubit and two angles.
class MyGate(Gate):
def __init__(self, theta, phi):
super().__init__("my", 1, [theta, phi])
custom_instructions = [
# Link the OpenQASM 2 name 'my' with our custom gate.
qasm2.CustomInstruction("my", 2, 1, MyGate),
# Link the OpenQASM 2 name 'rzx' with Qiskit's
# built-in RZXGate.
qasm2.CustomInstruction("rzx", 1, 2, RZXGate),
]
program = """
OPENQASM 2.0;
gate my(theta, phi) q {
U(theta / 2, phi, -theta / 2) q;
}
gate rzx(theta) a, b {
// It doesn't matter what definition is
// supplied, if the parameters match;
// Qiskit will still use `RZXGate`.
}
qreg q[2];
my(0.25, 0.125) q[0];
rzx(pi) q[0], q[1];
"""
circuit = qasm2.loads(
program,
custom_instructions=custom_instructions,
)
ตัวอย่าง: นิยาม built-in Gate ใหม่ในโปรแกรม OpenQASM 2
หาก argument builtin=True ถูกตั้งค่า custom Gate ไม่จำเป็นต้องมี definition ที่เกี่ยวข้อง
from qiskit import qasm2
from qiskit.circuit import Gate
# Define a custom gate that takes one qubit and two angles.
class MyGate(Gate):
def __init__(self, theta, phi):
super().__init__("my", 1, [theta, phi])
custom_instructions = [
qasm2.CustomInstruction("my", 2, 1, MyGate, builtin=True),
]
program = """
OPENQASM 2.0;
qreg q[1];
my(0.25, 0.125) q[0];
"""
circuit = qasm2.loads(
program,
custom_instructions=custom_instructions,
)
นิยามฟังก์ชัน classical แบบกำหนดเอง
OpenQASM 2 มีฟังก์ชัน classical แบบ built-in สำหรับใช้ใน Gate argument
สามารถขยายภาษาด้วยฟังก์ชันเพิ่มเติมได้โดยใช้ argument custom_classical ของ qasm2.load() และ qasm2.loads() พร้อมกับ qasm2.CustomClassical class
หากต้องการนิยามฟังก์ชัน classical แบบกำหนดเอง ต้องระบุ:
- ชื่อ ของฟังก์ชันที่ปรากฏในโปรแกรม OpenQASM 2
- จำนวน floating-point argument ที่รับ
- Python object ที่ callable เพื่อประมวลผลฟังก์ชัน
ฟังก์ชัน classical แบบกำหนดเองทั้งหมดจะถูกถือว่าเป็น built-in ของภาษา OpenQASM 2 โดย importer ไม่มีวิธีการอย่างเป็นทางการในภาษา OpenQASM 2 เพื่อนิยามฟังก์ชันใหม่ นี่เป็นส่วนขยายของ Qiskit
ตัวอย่าง: ใช้ custom classical instruction
ที่นี่เราให้ฟังก์ชัน classical แบบกำหนดเองสองตัว
ตัวแรกง่ายมาก เพียงแค่บวกหนึ่งเข้ากับ input
ตัวที่สองคือฟังก์ชัน math.atan2 ซึ่งแทนการดำเนินการทางคณิตศาสตร์ แบบรับรู้ quadrant
import math
from qiskit import qasm2
program = """
include "qelib1.inc";
qreg q[2];
rx(arctan(pi, 3 + add_one(0.2))) q[0];
cx q[0], q[1];
"""
def add_one(x):
return x + 1
customs = [
# Our `add_one` takes only one parameter.
qasm2.CustomClassical("add_one", 1, add_one),
# `arctan` takes two parameters, and `math.atan2` implements it.
qasm2.CustomClassical("arctan", 2, math.atan2),
]
circuit = qasm2.loads(program, custom_classical=customs)
Strict mode
โดยค่าเริ่มต้น parser นี้จะผ่อนปรนกว่า specification อย่างเป็นทางการ
อนุญาตให้มี trailing comma ใน parameter list, semicolon ที่ไม่จำเป็น (empty-statement), การละเว้น OPENQASM 2.0; version statement, และการปรับปรุงความสะดวกอื่นๆ อีกหลายอย่างโดยไม่มี error
อย่างไรก็ตาม สามารถใช้โหมด "letter-of-the-spec" ด้วย strict=True ได้
Export Circuit ของ Qiskit ไปยัง OpenQASM 2
Qiskit ยังสามารถ export QuantumCircuit ไปยัง OpenQASM 2 ได้
ใช้ฟังก์ชัน qasm2.dump() เพื่อเขียนลงไฟล์ และ qasm2.dumps() เพื่อเขียนเป็น string
ฟังก์ชันเหล่านี้มี interface ที่เรียบง่ายมาก: รับ Circuit และ ในกรณีของ qasm2.dump() เท่านั้น ตำแหน่งที่จะเขียน output ไป
OpenQASM 2 exporter ของ Qiskit ยังคงถือว่า "qelib1.inc" include file เป็น legacy, non-standard version
ปัญหานี้จะถูกแก้ไขใน release ถัดไปของ Qiskit แต่ในระหว่างนี้ หากต้องการนำเข้าโปรแกรม OpenQASM 2 ที่สร้างด้วย Qiskit อีกครั้ง ให้ใช้ ตัวอย่างข้างต้นเพื่อบอก importer เกี่ยวกับ legacy gate
ตัวอย่าง: export Circuit ไปยัง OpenQASM 2
from qiskit import QuantumCircuit, qasm2
# Define any circuit.
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure([0, 1], [0, 1])
# Export to a string.
program = qasm2.dumps(circuit)
# Export to a file.
qasm2.dump(circuit, "my_file.qasm")
ขั้นตอนถัดไป
- เรียนรู้วิธีสร้างโค้ด OpenQASM ใน IBM Quantum Composer guide
- ดู OpenQASM 2 Qiskit API reference
- ทบทวนหัวข้อ Verify your program
- เยี่ยมชม OpenQASM Live Specification