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

OpenQASM 2 และ Qiskit SDK

เวอร์ชันของ package

โค้ดในหน้านี้ถูกพัฒนาโดยใช้ requirements ต่อไปนี้ แนะนำให้ใช้เวอร์ชันเหล่านี้หรือใหม่กว่า

qiskit[all]~=2.3.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

นำเข้าโปรแกรมพื้นฐาน

สำหรับโปรแกรม 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")

โดยค่าเริ่มต้น 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 ซึ่งแทนการดำเนินการทางคณิตศาสตร์ arctan(y/x)\arctan(y/x) แบบรับรู้ 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")

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

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