RFC 016: Квантовая встроенная поддержка и интеграция с множественными бэкендами
Причина отклонения: Недостаточность предварительных зависимостей. Механизм Primitive::Extension ещё не реализован, компилятор языка не завершён, реальных пользовательских потребностей нет. Поддержку квантовых вычислений следует пересмотреть как потребителя механизма Extension после того, как язык достигнет зрелости.
Зависимости:
Резюме
Настоящий документ определяет решение для квантовой встроенной поддержки и интеграции с множественными бэкендами в языке YaoXiang. Ключевая идея: существующий дизайн YaoXiang (семантика Move по умолчанию, возврат ownership, непрозрачные типы, DAG-планировщик, константные параметры generics) естественным образом образует полную основу для языка квантового программирования без необходимости вводить какой-либо новый квантово-специфический синтаксис. Добавляя небольшое количество встроенных типов (Qubit, Complex, Topology) и встроенных функций (квантовые гейты, измерение, топологические ограничения) и используя существующие языковые механизмы, мы реализуем квантовую встроенную семантику, автоматическое распараллеливание для максимизации загрузки квантовых ресурсов, гибридное классическое программирование и поддержку множественных бэкендов.
Мотивация
Зачем нужна квантовая встроенная поддержка?
Современная экосистема квантового программирования страдает от серьёзной фрагментации:
- Низкоуровневые языки (QCIS, OpenQASM): непосредственно управляют физическими квантовыми гейтами, но лишены системы типов и механизмов абстракции, что затрудняет написание сложных алгоритмов.
- Высокоуровневые фреймворки (Qiskit, Cirq, Q#): расширяют классические языки (Python, C#), а квантовая семантика реализуется через библиотеки, что приводит к:
- необходимости вручную соблюдать правило невозможности клонирования квантового состояния (или полагаться на линейную систему типов, добавленную задним числом);
- разрыву синтаксиса между квантовыми гейтами и классическим кодом, что увеличивает порог входа.
- Гибридные вычисления: квантовая и классическая части требуют явного разделения и не имеют единой модели потоков данных.
Текущие проблемы
Имеющийся дизайн YaoXiang как раз обеспечивает полную основу для решения этих проблем:
| Потребность квантовых вычислений | Имеющийся дизайн YaoXiang | Пояснение |
|---|---|---|
| Неклонируемость квантового состояния | Семантика Move по умолчанию | Присваивание — это перемещение ownership, нет неявного копирования, что естественно согласуется с теоремой о запрете клонирования |
| Квантовый гейт как унитарное преобразование | Возврат ownership | q = H(q) потребляет исходный кубит и возвращает новый, что точно соответствует семантике гейта |
| Запутанные состояния | Непрозрачные типы | BellPair может использоваться только целиком; компилятор отслеживает жизненный цикл, предотвращая неправильную декомпозицию |
| Ограничения физической топологии | Константные параметры generics | Qubit(Topology, N) проверяет соседство на этапе компиляции |
| Коллапс при измерении | Переиспользование пустого состояния | После измерения кубит становится пустым и может быть повторно инициализирован, моделируя коллапс квантового состояния |
| Автоматическое распараллеливание квантовых схем | DAG-планировщик | Инструкции внутри функции распараллеливаются по data dependency; независимые гейты естественно выполняются параллельно |
| Гибридное классически-квантовое управление | Унифицированный синтаксис | Квантовые и классические операции используют единую форму name: type = value |
YaoXiang не "добавляет квантовую поддержку" — он обнаруживает, что его дизайн уже квантово-встроенный.
Пояснение семантики: В этом документе семантика ownership языка YaoXiang используется для выражения квантовых операций. Запрет клонирования гарантируется на уровне компилятора (безопасность ownership). «Потребление — создание» на уровне языка — это синтаксическое выражение перемещения ownership: потребление = получение ownership, возврат = передача ownership. Базовая реализация может быть истинно обратимым квантовым гейтом (in-place модификация квантового состояния), а не реальным «созданием нового квантового состояния».
Цели дизайна
- Нулевой новый синтаксис: не вводятся ключевые слова вроде
quantum,circuit; все квантовые возможности выражаются через существующие языковые механизмы. - Безопасность типов: компилятор гарантирует, что квантовое состояние не копируется и не используется недопустимым образом.
- Проверка топологических ограничений на этапе компиляции: через константный параметр generics
Qubit(T, N)верифицируется допустимость двухкубитных гейтов с учётом физической топологии. - Прозрачность множественных бэкендов: один и тот же квантовый код может компилироваться в QIR (общая экосистема) или QCIS (отечественный квантовый набор инструкций); выбор осуществляется параметром командной строки.
- Бесшовная классически-квантовая интеграция: квантовые вычисления могут свободно вызывать классические функции, а классический код — оперировать квантовыми данными (через
refсовместное использование, но с ограничениями ownership).
Предложение
Основной дизайн
1. Отображение системы квантовых типов
Базовые типы:
Qubit: Type0 = primitive_qubit
Complex: Type0 = { re: Float, im: Float }Qubit— тип первого класса, подчиняющийся правилам ownership (Move, RAII).Complexиспользуется для представления амплитуд; компилятор может выполнять инлайн-оптимизации.
Квантовые гейты как функции:
# Сигнатуры встроенных функций
H: (Qubit) -> Qubit = builtin_hadamard
X: (Qubit) -> Qubit = builtin_pauli_x
Y: (Qubit) -> Qubit = builtin_pauli_y
Z: (Qubit) -> Qubit = builtin_pauli_z
CNOT: (control: Qubit, target: Qubit) -> { Qubit, Qubit } = builtin_cnot- Все гейты потребляют входные кубиты и возвращают новые кубиты (или запутанную пару). Синтаксис возврата ownership
q = H(q)напрямую соответствует математической семантике. - Многокубитные гейты возвращают структуру, из которой результаты извлекаются через pattern matching или доступ к полям.
Измерение:
measure: (Qubit) -> Int = builtin_measure # потребляет кубит, возвращает классический бит
measure_all: (List(Qubit)) -> List(Int) = builtin_measure_all- После измерения кубит потребляется (становится пустым); пользователь может повторно инициализировать его через переиспользование пустого состояния.
Инициализация:
qubit: (Int) -> Qubit = builtin_qubit # инициализация базисного состояния 0 или 12. Запутанность и инкапсуляция через непрозрачные типы
Запутанные пары инкапсулируются как непрозрачный тип, для которого доступны только операции композиции, но не декомпозиции:
# Встроенный непрозрачный тип
BellPair: Type0 = primitive_bell_pair
# Встроенные функции — только целостные операции
CNOT: (Qubit, Qubit) -> BellPair
measure_bell: (BellPair) -> { Int, Int }
split_bell: (BellPair) -> { Qubit, Qubit } # разделение запутанной пары (использовать с осторожностью)
apply_cnot_to_bell: (BellPair, Qubit) -> BellPairКлючевые решения дизайна:
- Не предоставляются аксессоры полей; допускаются только целостные операции через встроенные функции.
measure_bell(bp)однократно потребляет всю запутанную пару и возвращает классические биты.- Компилятор способен отслеживать полный жизненный цикл запутанной пары.
Сравнение с Python/Qiskit:
Python (Qiskit): схема строится во время выполнения, ошибки могут быть обнаружены только после отправки
YaoXiang: компилятор ловит большинство логических ошибок на этапе компиляцииОставшиеся 10% (физическая декогеренция, ошибки гейтов) — это аппаратные проблемы, которые не решаются на уровне языка.
3. Ограничения физической топологии
Квантовый чип — это граф с ограничениями, не любые два кубита могут участвовать в двухкубитном гейте, они должны быть соседями. YaoXiang использует константные параметры generics для обеспечения топологических ограничений на этапе компиляции.
Определение типов топологии:
# Топология как тип, содержащий матрицу смежности
Topology: Type0 = primitive_topology
# Встроенные константы топологии
Linear8: Topology = topology(8) # линейная 8-бит: 0-1-2-3-4-5-6-7
Grid3x3: Topology = topology(3, 3) # сетка 3x3
Ring16: Topology = topology(16, ring) # кольцо из 16Привязка кубита к топологии и позиции:
# Qubit(T, N) — T — тип топологии, N — константный параметр позиции
q0: Qubit(Grid3x3, 0) # топология Grid3x3, позиция (0,0)
q1: Qubit(Grid3x3, 1) # топология Grid3x3, позиция (0,1)
q2: Qubit(Grid3x3, 2) # топология Grid3x3, позиция (0,2)
q3: Qubit(Grid3x3, 3) # топология Grid3x3, позиция (1,0)Автоматическое ограничение гейтов:
# Сигнатура CNOT содержит топологическое ограничение
CNOT: (T: Topology, I: Int, J: Int) -> (
(Qubit(T, I), Qubit(T, J)) -> { Qubit(T, I), Qubit(T, J) }
) when adjacent(T, I, J)
# Проверка на этапе компиляции
CNOT(q0, q1) # ✅ в Grid3x3 (0,0) и (0,1) соседствуют
CNOT(q0, q2) # ❌ ошибка компиляции: (0,0) и (0,2) не соседствуютКомпиляторное ограничение adjacent:
adjacent— это функция времени компиляции, использующая матрицу смежности топологии для статической проверки.- При константных индексах — 100% проверка на этапе компиляции.
- При динамических индексах — генерируется код проверки во время выполнения.
Виртуально-физическое отображение:
# Физическая позиция неизвестна на этапе компиляции? Используйте вывод типов
q = qubit(Grid3x3) # автоматическое выделение позиции 0, далее выводится4. Ownership и линейное перемещение квантового состояния
Все квантовые операции подчиняются семантике Move, гарантирующей, что кубит не копируется:
q = qubit(0)
q2 = q # ❌ ошибка компиляции: q уже перемещён, не может использоваться
q = H(q) # ✅ потребляет q, возвращает новый q
measure(q) # ✅ потребляет q, далее q становится пустым
q = qubit(0) # ✅ переиспользование пустого состояния5. Автоматическое распараллеливание и DAG-планировщик
В Standard или Full Runtime DAG-планировщик автоматически анализирует квантовую программу:
apply_two_qubit_gates: () -> {Qubit, Qubit} = () => {
q1 = H(qubit(0))
q2 = H(qubit(0))
# Две строки выше не имеют data dependency, DAG выполняет их параллельно автоматически
CNOT(q1, q2) # зависит от q1 и q2, ожидание автоматическое
}- Планировщик использует конфигурацию
num_workers(количество физических квантовых процессоров) для реального параллелизма. - Пользователю не нужно вручную упорядочивать гейты — достаточно описать поток данных.
6. Гибридные классические вычисления
Классический и квантовый код полностью сливаются:
grover_search: (target: Int) -> Int = () => {
n = 4
qubits = List(Qubit)()
for i in 0..n {
qubits.append(H(qubit(0)))
}
# Смешивание классического цикла и квантовых операций
oracle(qubits, target) # oracle — последовательность квантовых гейтов
qubits = diffusion(qubits)
results = measure_all(qubits)
return decode_result(results) # классическая пост-обработка
}- Внутри одной функции можно произвольно смешивать квантовые гейты и классический поток управления.
- Система ownership гарантирует, что квантовые переменные не будут ошибочно скопированы в классических ветвях.
7. Архитектура поддержки множественных бэкендов
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ YaoXiang 源 │ │ 类型检查 │ │ DAG 中间表示 │
│ (统一语法) │────▶│ + 所有权分析 │────▶│ (数据流图) │
└─────────────────┘ └─────────────────┘ └────────┬────────┘
│
▼
┌─────────────────────────────────────────────┐
│ 代码生成后端 (可插拔) │
├─────────────────┬───────────────────────────┤
│ QIR 后端 │ QCIS 后端 │
│ (通用生态) │ (国产量子指令集) │
├─────────────────┼───────────────────────────┤
│ - 输出 .ll 文件 │ - 输出 .qcis 文本 │
│ - 适配多种 QPU │ - 适配中科院/国盾硬件 │
└─────────────────┴───────────────────────────┘- Конвейер компиляции: единый фронтенд → построение DAG → выбор бэкенда → генерация целевого кода.
- QIR-бэкенд: отображает узлы DAG на квантовые intrinsic-инструкции QIR, генерирует LLVM bitcode с возможностью дальнейшей LLVM-оптимизации.
- QCIS-бэкенд: сериализует DAG в инструкции QCIS (например,
H q0), поддерживает прямую отправку в консоль управления квантовым чипом.
Примеры
Подготовка и измерение состояния Белла
bell_measure: () -> {Int, Int} = () => {
q1 = H(qubit(0))
q2 = H(qubit(0))
bell = CNOT(q1, q2) # возвращает непрозрачный тип BellPair
result = measure_bell(bell) # одновременное измерение двух битов
return result
}Квантовая телепортация (упрощённая)
teleport: (msg: Qubit, bell: BellPair) -> Qubit = (msg, bell) => {
# Разделение запутанной пары для получения двух независимых кубитов
(alice_qubit, bob_qubit) = split_bell(bell)
# Операции Алисы
(msg, alice_qubit) = CNOT(msg, alice_qubit)
msg = H(msg)
a1 = measure(msg)
a2 = measure(alice_qubit)
# Передача классической информации (зависимости обрабатываются планировщиком автоматически)
# Операции Боба
if a2 == 1 { bob_qubit = X(bob_qubit) }
if a1 == 1 { bob_qubit = Z(bob_qubit) }
return bob_qubit
}Детальный дизайн
Определения встроенных типов и функций
В модуле compiler/builtins добавляется:
builtins.insert("Qubit", Ty::Primitive(Primitive::Qubit));
builtins.insert("Complex", Ty::Record(vec![
("re", Ty::Primitive(Primitive::Float)),
("im", Ty::Primitive(Primitive::Float)),
]));
// Квантовые гейты
for (name, sig) in GATES {
builtins.insert(name, Ty::Function(vec![Ty::Qubit], Ty::Qubit));
}
builtins.insert("CNOT", Ty::Function(
vec![Ty::Qubit, Ty::Qubit],
Ty::Record(vec![
("q0", Ty::Qubit),
("q1", Ty::Qubit)
])
));
builtins.insert("measure", Ty::Function(vec![Ty::Qubit], Ty::Primitive(Primitive::Int)));
builtins.insert("qubit", Ty::Function(vec![Ty::Primitive(Primitive::Int)], Ty::Qubit));Специальная обработка Qubit в проверщике ownership
Qubitпомечается как!Copy(Move по умолчанию), запрещено неявное копирование.- Параметр функции
measureимеет типQubit(передача по значению), потребляет ownership. - В типах записей, возвращаемых многокубитными гейтами, поля имеют тип
Qubitи по-прежнему подчиняются правилам ownership.
Оптимизации DAG-планировщика для квантовых гейтов
- Узлы квантовых гейтов считаются чистыми функциями (без побочных эффектов), планировщик может произвольно переупорядочивать независимые гейты.
- При выводе «последовательности квантовых инструкций» планировщик сохраняет data dependency и группирует параллельные гейты (для много-кубитных процессоров).
- Поддерживаются опции
--target-num-qubitsи--target-topologyдля будущего размещения и маршрутизации (расширение на будущее).
Подробное отображение QIR-бэкенда
| Операция YaoXiang | Инструкция QIR |
|---|---|
H(q) | call void @__quantum__qis__h__body(%Qubit* %q) |
CNOT(q1, q2) | call void @__quantum__qis__cnot__body(%Qubit* %q1, %Qubit* %q2) |
measure(q) | %result = call i1 @__quantum__qis__mz__body(%Qubit* %q) |
qubit(0) | %q = call %Qubit* @__quantum__rt__qubit_allocate() |
QIR-бэкенд использует LLVM-оптимизацию -O2 и выводит bitcode, совместимый с QIR Alliance.
Подробное отображение QCIS-бэкенда
| Операция YaoXiang | Инструкция QCIS |
|---|---|
H(q) (q соответствует физ. биту 2) | H 2 |
CNOT(q1,q2) (q1→бит 0, q2→бит 1) | CNOT 0 1 |
measure(q) (бит 0) | M 0 |
qubit(0) инициализация | подразумевается в первой инструкции использования, дополнительных инструкций не требуется |
- Необходимо поддерживать таблицу отображения виртуальных кубитов (переменные YaoXiang) на физические биты.
- Поддерживается проверка топологических ограничений (реализация в будущем).
Генерация гибридного классического кода
- Классическая часть (циклы, условия, целочисленная арифметика) генерируется как обычный нативный код (x86/ARM); взаимодействие с квантовым бэкендом — через FFI или встроенные вызовы.
- В QIR-бэкенде классическая часть может быть понижена до LLVM IR и совместно скомпилирована с QIR.
Влияние на систему типов
- Добавляются примитивные типы
QubitиComplex. Qubitавтоматически обладает семантикой Move, копирование запрещено.- Сигнатуры функций квантовых гейтов должны быть зарегистрированы в системе типов.
Обратная совместимость
- ✅ Полная обратная совместимость
- Добавляются встроенные типы и функции, не затрагивающие существующий код.
- Квантовые возможности опциональны; без их использования дополнительных накладных расходов нет.
Компромиссы
Преимущества
- Отсутствие нового синтаксиса: разработчику достаточно выучить несколько встроенных функций, чтобы писать квантовые программы.
- Безопасность типов: система ownership автоматически предотвращает копирование кубитов, избегая типичных ошибок квантового программирования.
- Автоматическое распараллеливание: DAG-планировщик «бесплатно» обеспечивает параллелизм на уровне гейтов без дополнительных оптимизаций компилятора.
- Совместимость экосистемы: QIR-бэкенд позволяет YaoXiang работать на множестве квантовых облачных платформ; QCIS-бэкенд обеспечивает автономность и контроль.
- Гибридные возможности: естественное слияние классического и квантового кода, подходящее для написания сложных квантовых алгоритмов (таких как классическое управление в Shor, Grover).
Недостатки
- Статическое количество кубитов: текущий дизайн предполагает, что количество кубитов известно на этапе компиляции; динамическое выделение требует
List(Qubit), но распределение в куче дляListможет вносить дополнительные накладные расходы (можно смягчить оптимизациями). - Переиспользование после измерения: переиспользование пустого состояния позволяет повторно инициализировать кубиты, но физические квантовые биты могут иметь время релаксации; это должно обрабатываться runtime-системой (в настоящее время ответственность на пользователе).
- Динамическое топологическое отображение: если физическая топология известна только в runtime, проверка на этапе компиляции невозможна — необходима генерация кода проверки во время выполнения (текущая версия поддерживает только статическую проверку).
Альтернативы
| Решение | Почему не выбрано |
|---|---|
Введение ключевого слова quantum и типа circuit | Увеличивает синтаксис, повышает порог входа, противоречит принципу минималистичности YaoXiang |
| Реализация квантовой поддержки только как библиотеки | Не позволяет использовать компилятор для обеспечения безопасности квантового состояния и глубокой интеграции с DAG-планировщиком |
| Ожидание зрелости квантового оборудования | Упускает ключевое окно возможностей для дизайна квантового языка |
| Повторное использование существующих квантовых фреймворков (например, Qiskit) | Квантовая семантика, реализованная через библиотеку, не получает гарантий системы типов и системы ownership |
| Проектирование отдельного квантового подъязыка | Увеличивает сложность языка и стоимость сопровождения |
Стратегия реализации
Этапы
| Этап | Длительность | Содержание |
|---|---|---|
| Phase 1 | 1 месяц | Базовые квантовые типы и встроенные функции: добавление в компилятор типов Qubit, Complex, реализация проверки типов встроенных функций, расширение проверщика ownership |
| Phase 2 | 1 месяц | Распознавание квантовых гейтов DAG-планировщиком: модификация логики построения DAG, маркировка квантовых гейтов как чистых функций, вывод с группировкой параллельных гейтов |
| Phase 3 | 2 месяца | Прототип QIR-бэкенда: реализация генератора кода DAG → QIR, интеграция с LLVM, подключение симулятора QIR для верификации |
| Phase 4 | 2 месяца | Прототип QCIS-бэкенда: реализация транслятора DAG → инструкции QCIS, проектирование виртуально-физического отображения кубитов, подключение к отечественным квантовым платформам |
| Phase 5 | 2 месяца | Усиление гибридной классической части: корректная кодогенерация для пересечения классического потока управления и квантовых гейтов, поддержка List(Qubit), добавление примеров |
| Phase 6 | 2 месяца | Оптимизации и документация: реализация базового размещения и маршрутизации, написание руководства пользователя и учебника по квантовому программированию, выпуск preview-версии |
Риски
Доступность квантового оборудования: зависимость от внешних квантовых симуляторов и реальных QPU.
- Митигация: приоритетное подключение open-source симуляторов (QIR runner, Qiskit Aer); реальные QPU — долгосрочная цель.
Сложность реализации бэкендов: спецификации QIR и QCIS могут изменяться.
- Митигация: абстрагирование интерфейса кодогенерации, изоляция различий бэкендов для упрощения последующей адаптации.
Неопределённость производительности: характеристики производительности квантовых программ отличаются от классических.
- Митигация: предоставление инструментов профилирования, чтобы пользователи могли оценить эффект параллелизма на уровне гейтов.
Открытые вопросы
- [x] Топологические ограничения: реализованы через константный параметр generics
Qubit(Topology, N)с проверкой на этапе компиляции. - [ ] Динамические квантовые регистры: как
List(Qubit)отображается в QCIS-бэкенде? Можно сгенерировать соответствующее количество физических битов, но требуется механизм динамического выделения. - [ ] Смягчение ошибок: предоставлять ли встроенные конструкции смягчения ошибок (например, динамическую декаплинговку)? Можно начать как библиотеку.
- [ ] Совместимость с существующими квантовыми SDK: возможен ли импорт модулей QASM или QIR? Возможен FFI в будущем.
- [ ] Автоматическое размещение и маршрутизация: как автоматически отображать виртуальные кубиты, когда их число превышает число физических?
Ссылки
- QIR Specification
- QCIS: A Quantum Control Instruction Set (USTC/CAS)
- Rust Quantum Computing Examples
- Qunity: A Unified Language for Quantum and Classical Computing (2025)
Жизненный цикл и судьба
┌─────────────┐
│ 草案 │ ← 作者创建
└──────┬──────┘
│
▼
┌─────────────┐
│ 审核中 │ ← 社区讨论
└──────┬──────┘
│
├──────────────────┐
▼ ▼
┌─────────────┐ ┌─────────────┐
│ 已接受 │ │ 已拒绝 │
└──────┬──────┘ └──────┬──────┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ accepted/ │ │ rfc/ │
│ (正式设计) │ │ (保留原位) │
└─────────────┘ └──────┬──────┘
│
▼
┌─────────────────┐
│ deprecated/ │
│ (标记为不推荐) │
└─────────────────┘Описание статусов
| Статус | Расположение | Описание |
|---|---|---|
| 草案 | docs/design/rfc/draft/ | Черновик автора, ожидает подачи на ревью |
| 审核中 | docs/design/rfc/ | Открыто для обсуждения и обратной связи сообщества |
| 已接受 | docs/design/accepted/ | Становится официальным документом дизайна, переходит в реализацию |
| 已拒绝 | docs/design/rfc/ | Остаётся в каталоге RFC, статус обновляется |
