Поделиться через


Управление квантовой памятью

Программа всегда запускается без кубитов, то есть нельзя передавать значения типа Qubit в качестве аргументов точки входа. Это ограничение намеренно, так как цель Q# заключается в том, чтобы выразить и причину о программе в целом. Вместо этого программа выделяет и освобождает кубиты или квантовую память, как это происходит. В этом отношении Q# моделирует квантовый компьютер как кучу кубитов.

Вместо поддержки отдельных выделения и инструкций для квантовой памяти Q# поддерживает выделение квантовой памяти в виде операторов блоков, где память доступна только в пределах этой инструкции блока. Блок инструкций может быть неявно определен при выделении кубитов в течение текущей области, как описано более подробно в разделах об use и borrow операторах. Попытка получить доступ к выделенным кубитам после завершения инструкции приводит к исключению среды выполнения.

Q# имеет две инструкции, use и borrow, которые создает экземпляры значений кубитов, массивов кубитов или любое их сочетание. Эти инструкции можно использовать только в операциях. Они собирают экземплярные значения кубитов, привязывают их к переменным, указанным в инструкции, а затем выполняют блок инструкций. В конце блока связанные переменные выходят из области и больше не определены.

Q# различает выделение чистых и грязных кубитов. Чистые кубиты не запутаны и не используются другой частью вычисления. Грязные кубиты являются кубитами, состояние которых неизвестно и даже может быть запутано с другими частями памяти квантового процессора.

Оператор Use

Чистые кубиты выделяются оператором use.

  • Инструкция состоит из ключевого слова use за привязкой и необязательным блоком инструкций.
  • Если блок инструкций присутствует, кубиты доступны только в этом блоке. В противном случае кубиты доступны до конца текущей области.
  • Привязка следует тому же шаблону, что и операторы let: один символ или кортеж символов, за которым следует знак равенства =, а также один кортеж или соответствующий кортеж инициализаторов.

Инициализаторы доступны либо для одного кубита, указанного как Qubit(), либо массив кубитов, Qubit[n], где n является выражением Int. Например

use qubit = Qubit();
// ...

use (aux, register) = (Qubit(), Qubit[5]);
// ...

use qubit = Qubit() {
    // ...
}

use (aux, register) = (Qubit(), Qubit[5]) {
    // ...
}

Кубиты гарантированно находятся в состоянии |0⟩ при выделении. Они выпускаются в конце области и должны находиться в состоянии |0⟩ при выпуске. Это требование не применяется компилятором, так как для этого требуется символьная оценка, которая быстро получает запретительно дорого. При выполнении на симуляторах требование может применяться во время выполнения. На квантовых процессорах требование не может быть применено во время выполнения; неустранимый кубит может быть сброшен на |0⟩ через унитарное преобразование. Сбой этого приводит к неправильному поведению.

Оператор use выделяет кубиты из свободного кубита квантового процессора и возвращает их в кучу не позднее конца области, в которой кубиты привязаны.

Оператор "Заимствование"

Оператор borrow предоставляет доступ к кубитам, которые уже выделены, но сейчас не используются. Эти кубиты могут находиться в произвольном состоянии и должны находиться в том же состоянии снова при завершении инструкции заимствования. Некоторые квантовые алгоритмы могут использовать кубиты, не опираясь на их точное состояние, и не требуя, чтобы они не запутались с остальной частью системы. То есть они требуют дополнительных кубитов временно, но они могут гарантировать, что эти кубиты возвращаются именно в исходное состояние, независимо от того, какое состояние было.

Если есть кубиты, которые используются, но не касаются во время частей подпрограммы, эти кубиты можно заимствовать для использования таким алгоритмом вместо выделения дополнительной квантовой памяти. Заимствование вместо выделения может значительно снизить общие требования к квантовой памяти алгоритма и является квантовым примером типичного компромисса по времени.

Оператор borrow следует тому же шаблону, который описан ранее для инструкции useс теми же инициализаторами, которые доступны. Например

borrow qubit = Qubit();
// ...

borrow (aux, register) = (Qubit(), Qubit[5]);
// ...

borrow qubit = Qubit() {
    // ...
}

borrow (aux, register) = (Qubit(), Qubit[5]) {
    // ...
}

Заимствованные кубиты находятся в неизвестном состоянии и выходят из области в конце блока инструкций. Заемщик фиксирует выход из кубитов в том же состоянии, что и когда они были заимствованы; То есть их состояние в начале и конце блока инструкций, как ожидается, будет одинаковым.

Оператор borrow извлекает кубиты, которые гарантированно не будут использоваться программой с момента привязки кубита до последнего использования этого кубита. Если для заимствований недостаточно кубитов, то кубиты выделяются и возвращаются в кучу, как оператор use.

Примечание.

Среди известных вариантов использования грязных кубитов являются реализации многоконтролируемых шлюзов CNOT, требующих очень мало кубитов и реализаций добавочных элементов. В этом документе по факторингу с кубитами представлен пример алгоритма, используюющего заимствованные кубиты.