주 콘텐츠로 건너뛰기

OpenQASM 2와 Qiskit SDK

패키지 버전

이 페이지의 코드는 다음 요구 사항을 사용하여 개발되었습니다. 이 버전 이상을 사용하길 권장해요.

qiskit[all]~=2.3.0
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit

Qiskit SDK는 양자 프로그램의 OpenQASM 표현과 QuantumCircuit 클래스 간에 변환하기 위한 몇 가지 도구를 제공합니다.

OpenQASM 2 프로그램을 Qiskit으로 가져오기

OpenQASM 2 프로그램을 Qiskit으로 가져오는 함수가 두 가지 있습니다. 파일 이름을 인수로 받는 qasm2.load()와, OpenQASM 2 프로그램을 문자열로 받는 qasm2.loads()입니다.

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.loadqasm2.loads를 단일 인수로 간단히 사용할 수 있습니다.

예시: OpenQASM 2 프로그램을 문자열로 가져오기

qasm2.loads()를 사용하여 OpenQASM 2 프로그램을 문자열로 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")

기본적으로, Qiskit의 OpenQASM 2 임포터는 인클루드 파일 "qelib1.inc"를 사실상의 표준 라이브러리로 처리합니다. 임포터는 이 파일이 OpenQASM 2를 정의한 원본 논문에서 설명된 Gate를 정확하게 포함하고 있는 것으로 처리합니다. Qiskit은 "qelib1.inc"의 Gate를 표현하기 위해 Circuit 라이브러리의 내장 Gate를 사용합니다. 프로그램에서 수동 OpenQASM 2 gate 문으로 정의된 Gate는 기본적으로 사용자 정의 Qiskit Gate 서브클래스로 구성됩니다.

임포터가 만나는 특정 gate 문에 대해 특정 Gate 클래스를 사용하도록 지정할 수 있습니다. 이 메커니즘을 사용하여 추가 Gate 이름을 "내장"으로, 즉 명시적 정의가 필요하지 않도록 처리할 수도 있습니다. "qelib1.inc" 외부의 gate 문에 사용할 Gate 클래스를 지정하면, 결과 Circuit은 일반적으로 더 효율적으로 작동합니다.

경고

Qiskit SDK v1.0부터, Qiskit의 OpenQASM 2 익스포터 (Qiskit Circuit을 OpenQASM 2로 내보내기 참조)는 여전히 "qelib1.inc"에 실제보다 더 많은 Gate가 있는 것처럼 동작합니다. 이는 임포터의 기본 설정으로는 당사의 익스포터가 내보낸 프로그램을 가져오지 못할 수 있음을 의미합니다. 이 문제를 해결하려면 레거시 익스포터와 함께 작업하는 구체적인 예시를 참조하세요.

이 불일치는 Qiskit의 레거시 동작이며, Qiskit의 이후 릴리스에서 해결될 예정입니다.

OpenQASM 2 임포터에 사용자 정의 명령어에 대한 정보를 전달하려면 qasm2.CustomInstruction 클래스를 사용하세요. 다음과 같은 네 가지 필수 정보가 순서대로 필요합니다:

  • OpenQASM 2 프로그램에서 사용되는 Gate의 이름
  • Gate가 받는 각도 파라미터의 수
  • Gate가 작용하는 Qubit의 수
  • Gate 파라미터(Qubit 제외)를 개별 인수로 받는 Gate의 Python 생성자 클래스 또는 함수

임포터가 주어진 사용자 정의 명령어와 일치하는 gate 정의를 만나면, 해당 사용자 정의 정보를 사용하여 Gate 객체를 재구성합니다. 사용자 정의 명령어의 name과 일치하는 gate 문을 만났지만 파라미터 수와 Qubit 수가 모두 일치하지 않는 경우, 임포터는 제공된 정보와 프로그램 간의 불일치를 나타내기 위해 QASM2ParseError를 발생시킵니다.

또한, 다섯 번째 인수인 builtin을 선택적으로 True로 설정하여 Gate가 명시적으로 정의되지 않더라도 OpenQASM 2 프로그램 내에서 자동으로 사용 가능하게 할 수 있습니다. 임포터가 내장 사용자 정의 명령어에 대한 명시적 gate 정의를 만나면 조용히 수락합니다. 마찬가지로, 같은 이름의 명시적 정의가 제공된 사용자 정의 명령어와 호환되지 않으면 QASM2ParseError가 발생합니다. 이는 오래된 OpenQASM 2 익스포터 및 하드웨어의 "기저 Gate"를 내장 명령어로 처리하는 특정 다른 양자 플랫폼과의 호환성을 위해 유용합니다.

Qiskit은 Qiskit의 OpenQASM 2 내보내기 기능의 레거시 버전으로 생성된 OpenQASM 2 프로그램을 다루기 위한 데이터 속성을 제공합니다. 이는 qasm2.LEGACY_CUSTOM_INSTRUCTIONS로, qasm2.load()qasm2.loads()custom_instructions 인수로 전달할 수 있습니다.

예시: Qiskit의 레거시 익스포터로 생성된 프로그램 가져오기

이 OpenQASM 2 프로그램은 "qelib1.inc"의 원본 버전에 없는 Gate를 선언 없이 사용하지만, 이는 Qiskit 라이브러리의 표준 Gate입니다. qasm2.LEGACY_CUSTOM_INSTRUCTIONS를 사용하면 Qiskit의 OpenQASM 2 익스포터가 이전에 사용하던 것과 동일한 Gate 세트를 임포터에 쉽게 알릴 수 있습니다.

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,
)

예시: OpenQASM 2 프로그램을 가져올 때 특정 Gate 클래스 사용하기

Qiskit은 일반적으로 OpenQASM 2 gate 문의 정의가 Qiskit 표준 라이브러리 Gate와 정확히 일치하는지 확인할 수 없습니다. 대신, Qiskit은 제공된 정확한 정의를 사용하여 사용자 정의 Gate를 선택합니다. 이는 내장 표준 Gate 또는 사용자 정의 Gate를 사용하는 것보다 효율이 떨어질 수 있습니다. 특정 클래스로 gate 문을 수동으로 정의할 수 있습니다.

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,
)

예시: OpenQASM 2 프로그램에서 새로운 내장 Gate 정의하기

builtin=True 인수가 설정되면 사용자 정의 Gate는 연관된 정의를 가질 필요가 없습니다.

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,
)

사용자 정의 고전 함수 정의하기

OpenQASM 2에는 Gate 인수에서 사용할 수 있는 내장 고전 함수가 포함되어 있습니다. qasm2.load()qasm2.loads()custom_classical 인수와 qasm2.CustomClassical 클래스를 사용하여 더 많은 함수로 언어를 확장할 수 있습니다.

사용자 정의 고전 함수를 정의하려면 다음을 제공해야 합니다:

  • OpenQASM 2 프로그램에 나타나는 함수의 이름
  • 함수가 받는 부동소수점 인수의 수
  • 함수를 평가하는 호출 가능한 Python 객체

정의된 모든 사용자 정의 고전 함수는 임포터에 의해 OpenQASM 2 언어에 내장된 것으로 처리됩니다. OpenQASM 2 언어 내에서 새로운 함수를 정의하는 공식적인 방법은 없으며, 이는 Qiskit의 확장 기능입니다.

예시: 사용자 정의 고전 명령어 사용하기

여기서 두 가지 사용자 정의 고전 함수를 제공합니다. 첫 번째는 간단하며, 입력에 1을 더하기만 합니다. 두 번째는 사분면을 인식하는 방식으로 수학 연산 arctan(y/x)\arctan(y/x)를 나타내는 함수 math.atan2입니다.

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)

엄격 모드

기본적으로 이 파서는 공식 사양보다 더 유연합니다. 파라미터 목록의 후행 쉼표, 불필요한 (빈 문) 세미콜론, OPENQASM 2.0; 버전 문 생략, 그리고 오류 없이 여러 가지 편의 개선 사항을 허용합니다. 하지만 strict=True로 "사양의 문자 그대로" 모드를 사용할 수 있습니다.

Qiskit Circuit을 OpenQASM 2로 내보내기

Qiskit은 QuantumCircuit을 OpenQASM 2로 내보낼 수도 있습니다. 파일에 쓰려면 qasm2.dump() 함수를, 문자열에 쓰려면 qasm2.dumps() 함수를 사용합니다. 이 함수들은 현재 매우 간단한 인터페이스를 가지고 있습니다: Circuit을 받고, qasm2.dump()의 경우에만 출력을 쓸 위치도 받습니다.

경고

Qiskit의 OpenQASM 2 익스포터는 여전히 "qelib1.inc" 인클루드 파일의 레거시, 비표준 버전을 가정합니다. 이는 Qiskit의 이후 릴리스에서 해결될 예정입니다. 그러나 그동안 Qiskit으로 생성된 OpenQASM 2 프로그램을 다시 가져와야 한다면, 임포터에 레거시 Gate를 알리는 방법에 대한 위의 예시를 사용하세요.

예시: 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")

다음 단계

추천 사항