Перейти до основного вмісту

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(), яка приймає ім'я файлу, і qasm2.loads(), яка приймає програму OpenQASM 2 як рядок.

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 з одним аргументом.

Приклад: імпорт програми 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")

Прив'язка вентилів OpenQASM 2 до вентилів Qiskit

За замовчуванням імпортер OpenQASM 2 у Qiskit розглядає файл включення "qelib1.inc" як де-факто стандартну бібліотеку. Імпортер трактує цей файл як такий, що містить рівно ті вентилі, які описано в оригінальній статті про OpenQASM 2. Qiskit використовуватиме вбудовані вентилі з бібліотеки схем для представлення вентилів із "qelib1.inc". Вентилі, визначені в програмі вручну за допомогою операторів gate у OpenQASM 2, за замовчуванням будуть побудовані як власні підкласи Qiskit Gate.

Ти можеш вказати імпортеру використовувати конкретні класи Gate для заданих операторів gate, які він зустрічає. Також можна використовувати цей механізм, щоб вважати додаткові імена вентилів «вбудованими», тобто такими, що не потребують явного визначення. Якщо ти вкажеш, які класи вентилів використовувати для операторів gate поза "qelib1.inc", отримана схема зазвичай буде ефективнішою у роботі.

попередження

Починаючи з Qiskit SDK v1.0, експортер OpenQASM 2 у Qiskit (див. Експорт схеми Qiskit у OpenQASM 2) досі поводиться так, ніби "qelib1.inc" містить більше вентилів, ніж є насправді. Це означає, що стандартні налаштування імпортера можуть не розпізнати програму, експортовану нашим експортером. Щоб розв'язати цю проблему, дивись конкретний приклад роботи з legacy-експортером.

Ця розбіжність є спадковою поведінкою Qiskit, і вона буде усунена в одному з наступних релізів Qiskit.

Щоб передати інформацію про власну інструкцію імпортеру OpenQASM 2, використовуй клас qasm2.CustomInstruction. Він потребує чотирьох обов'язкових частин інформації, у такому порядку:

  • Ім'я вентиля, що використовується в програмі OpenQASM 2
  • Кількість кутових параметрів, які приймає вентиль
  • Кількість кубітів, на які діє вентиль
  • Python-конструктор — клас або функція для вентиля, яка приймає параметри вентиля (але не кубіти) як окремі аргументи

Якщо імпортер зустрічає визначення gate, що відповідає заданій власній інструкції, він використовує цю інформацію для відтворення об'єкта вентиля. Якщо зустрічається оператор gate, що збігається за name із власною інструкцією, але не збігається за кількістю параметрів або кубітів, імпортер викине QASM2ParseError, сигналізуючи про невідповідність між наданою інформацією та програмою.

Крім того, п'ятий аргумент builtin може бути необов'язково встановлено в True, щоб вентиль автоматично був доступний у програмі OpenQASM 2 навіть без явного визначення. Якщо імпортер усе ж зустріне явне визначення gate для вбудованої власної інструкції — він мовчки його прийме. Як і раніше, якщо явне визначення з тим самим іменем несумісне з наданою власною інструкцією, буде викинуто QASM2ParseError. Це корисно для сумісності зі старішими експортерами OpenQASM 2 та з деякими іншими квантовими платформами, які вважають «базові вентилі» свого апаратного забезпечення вбудованими інструкціями.

Qiskit надає атрибут даних для роботи з програмами OpenQASM 2, створеними старими версіями можливостей Qiskit з експорту OpenQASM 2. Це qasm2.LEGACY_CUSTOM_INSTRUCTIONS, який можна передати як аргумент custom_instructions до qasm2.load() та qasm2.loads().

Приклад: імпорт програми, створеної legacy-експортером Qiskit

Ця програма OpenQASM 2 використовує вентилі, яких немає в оригінальній версії "qelib1.inc", не оголошуючи їх явно, але вони є стандартними вентилями бібліотеки Qiskit. Ти можеш скористатися qasm2.LEGACY_CUSTOM_INSTRUCTIONS, щоб легко вказати імпортеру використовувати той самий набір вентилів, що раніше застосовувався в експортері OpenQASM 2 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,
)

Приклад: використання конкретного класу вентиля при імпорті програми OpenQASM 2

Qiskit загалом не може перевірити, чи визначення в операторі gate OpenQASM 2 точно відповідає стандартному вентилю бібліотеки Qiskit. Натомість Qiskit обирає власний вентиль, використовуючи саме те визначення, що надано. Це може бути менш ефективним, ніж використання одного з вбудованих стандартних вентилів або визначеного користувачем власного вентиля. Ти можеш вручну прив'язати оператори 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

Якщо встановлено аргумент builtin=True, власний вентиль не потребує пов'язаного визначення.

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 містить деякі вбудовані класичні функції для використання в аргументах вентилів. Ти можеш розширити мову власними функціями, передавши аргумент custom_classical до qasm2.load() та qasm2.loads() разом із класом qasm2.CustomClassical.

Щоб визначити власну класичну функцію, потрібно вказати:

  • Ім'я функції, як воно з'являється в програмі OpenQASM 2
  • Кількість аргументів із рухомою комою, які вона приймає
  • Callable-об'єкт Python, що обчислює цю функцію

Усі визначені власні класичні функції імпортер розглядає як вбудовані в мову OpenQASM 2. Офіційного способу визначити нові функції засобами самої мови OpenQASM 2 не існує — це розширення Qiskit.

Приклад: використання власних класичних інструкцій

Тут ми надаємо дві власні класичні функції. Перша проста — вона просто додає одиницю до свого аргументу. Друга — це функція math.atan2, що представляє математичну операцію arctan(y/x)\arctan(y/x) з урахуванням квадранта.

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 у OpenQASM 2

Qiskit також може експортувати QuantumCircuit у OpenQASM 2. Для запису у файл використовується функція qasm2.dump(), а для запису в рядок — qasm2.dumps(). Наразі ці функції мають дуже простий інтерфейс: вони приймають схему і, лише у випадку qasm2.dump(), місце для запису виводу.

попередження

Експортер OpenQASM 2 у Qiskit досі припускає застарілу, нестандартну версію файлу включення "qelib1.inc". Це буде виправлено в одному з наступних релізів Qiskit, але поки що, якщо тобі потрібно повторно імпортувати програму OpenQASM 2, створену Qiskit, скористайся наведеним вище прикладом, щоб повідомити імпортеру про legacy-вентилі.

Приклад: експорт схеми у 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")

Наступні кроки

Рекомендації