Q# Структура программы

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

Рассмотрим следующую программу Q#:

namespace Superposition {

    @EntryPoint()
    operation MeasureOneQubit() : Result {
        // Allocate a qubit, by default it is in zero state      
        use q = Qubit();  
        // We apply a Hadamard operation H to the state
        // It now has a 50% chance of being measured 0 or 1  
        H(q);      
        // Now we measure the qubit in Z-basis.
        let result = M(q);
        // We reset the qubit before releasing it.
        Reset(q);
        // Finally, we return the result of the measurement.
        return result;
    }
}

Просто читая комментарии (//), можно сказать, что эта программа выделяет кубит, применяет операцию для его размещения в суперпозиции, измеряет состояние кубита, а затем сбрасывает его и возвращает результат.

Чтобы запустить эту программу в Visual Studio Code, см. статью Начало работы с программами Q# и VS Code.

Пространства имен пользователей

Q# Программы обычно начинаются с именованного пользователем пространства имен, например

namespace Superposition {
    // Your code goes here.
}

Пространства имен помогают упорядочить связанные функции. Пространства имен имеют имя пользователя, и для каждого файла qsharp (*.qs) может быть только одно namespace .

Стандартная Q# библиотека содержит предопределенные пространства имен, содержащие функции и операции, которые можно использовать в квантовых программах. Дополнительные сведения см. в разделе Встроенные пространства имен.

Записные книжки Jupyter Notebook не используют пространства имен пользователей.

EntryPoint()

Атрибут @EntryPoint() сообщает компилятору, Q# с чего начать выполнение программы. В программах с несколькими определениями функций и операций @EntryPoint() можно поместить перед любой из функций или операций, а поток программы начинается оттуда и продолжается последовательно.

    ...
    @EntryPoint()
    operation MeasureOneQubit() : Result {
        ...

Записные книжки Jupyter Notebook не используют точки входа.

Команда %%qsharp

По умолчанию Q# программы в Jupyter Notebook используют ядро Python ipykernel . Чтобы добавить Q# код в ячейку записной книжки %%qsharp , необходимо использовать команду , которая включена с пакетом qsharp Python. Например, предыдущий пример кода в Jupyter Notebook выглядит следующим образом:

import qsharp
%%qsharp

    operation MeasureOneQubit() : Result {
        // Allocate a qubit, by default it is in zero state      
        use q = Qubit();  
        // We apply a Hadamard operation H to the state
        // It now has a 50% chance of being measured 0 or 1  
        H(q);      
        // Now we measure the qubit in Z-basis.
        let result = M(q);
        // We reset the qubit before releasing it.
        Reset(q);
        // Display the result
        Message($"Result is {result}");
        // Finally, we return the result of the measurement.
        return result;
    
    }
    MeasureOneQubit();

Обратите внимание на отсутствие пространства имен пользователя или @EntryPoint(), которые не требуются для записных книжек Jupyter Notebook. Вместо точки входа операция вызывается непосредственно в последней строке. Также обратите внимание, что Message в код Jupyter Notebook добавлен оператор для отображения результата. При запуске предыдущей Q# программы в VS Code встроенный симулятор отображает результат по умолчанию.

При использовании команды:%%qsharp

  • Сначала необходимо выполнить import qsharp, чтобы включить команду %%qsharp.
  • Область %%qsharp действия команды ограничена всей ячейкой, в которой она отображается. Обратите внимание, что он изменяет тип ячейки записной книжки с Python на Q#.
  • Код Q#, следующий за командой, должен соответствовать стандартному синтаксису кода Q#. Например, примечания обозначаются с помощью // вместо # в %%qsharp ячейках, а строки кода должны заканчиваться точкой с запятой ;.
  • Перед командой %%qsharp или после нее в ее ячейке не может находиться оператор Python.

Пример работы с программой Jupyter Notebook см. в разделах Начало работы с Q# программами и VS Code.

Типы

Q# предоставляет множество встроенных типов , которые являются общими для большинства языков, включая Int, Double, Boolи String, а также типы, характерные для квантовых вычислений. Например, Result тип представляет результат любого измерения кубита и может иметь одно из двух возможных определенных значений: One и Zero. В примере программы операция MeasureOneQubit() ожидает тип возвращаемого Result значения , а M операция измеряет кубит и возвращает Result.

...
// operation definition expecting a return type of Result
operation MeasureOneQubit() : Result {
    ...
    // Now we measure the qubit in Z-basis, returning a Result type
    let result = M(q);
    ...
}

Q# также предоставляет типы, определяющие диапазоны, массивы и кортежи. Можно даже определить собственные пользовательские типы.

Выделение кубитов

В коде Q# кубиты выделяются с использованием ключевого слова use.

В нашем примере определяется один кубит:

// Allocate a qubit.
use q = Qubit();
...

но вы также можете выделить несколько кубитов и получить доступ к каждому из них по индексу:

...
use qubits = Qubit[2];
X(qubits[1]);
H(qubits[0]);
...

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

// Reset a qubit.
Reset(q);
...

Квантовые операции

После выделения кубит можно передать в операции и функции, которые также называются вызываемыми объектами. Операции являются основными стандартными блоками программы Q#. Операцией в Q# называется квантовая подпрограмма. То есть это вызываемая подпрограмма, содержащая квантовые операции, которые изменяют состояние регистра кубита.

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

operation MeasureOneQubit() : Result {
    ...
}

Ниже приведен базовый пример, который не принимает параметров и не ожидает возвращаемого значения. Значение Unit эквивалентно NULL в других языках.

operation SayHelloQ() : Unit {
    Message("Hello quantum world!");
}

Стандартная Q# библиотека также предоставляет операции, которые можно использовать в программах, например Hadamard или H операцию, используемую в примере программы. Для кубита по основе Z операция H переводит его в четную суперпозицию. Находясь в суперпозиции, кубит при измерении имеет 50%-ю вероятность стать нулем или единицей.

Измерение кубитов

Существует множество типов квантовых измерений, но Q# основное внимание уделяется проективным измерениям на отдельных кубитах, также известных как измерения Паули. При измерении в указанном базисе (например, в вычислительном базисе $\ket{0},\ket{1}$) состояние кубита проецируется на измеренное базисное состояние, уничтожая любую существующую между кубитами суперпозицию.

В нашем примере программа использует M операцию , которая выполняет измерение одного кубита в базе Pauli Z и возвращает Result тип.

Встроенные пространства имен

Стандартная Q# библиотека использует встроенные пространства имен, содержащие функции и операции, которые можно использовать в квантовых программах. Например, пространство Microsoft.Quantum.Intrinsic имен содержит часто используемые операции и функции, такие как M, для измерения результатов и Message, для отображения пользовательских сообщений в любом месте программы.

Можно вызвать функцию или операцию, указав полное пространство имен, или использовать инструкцию open , чтобы сделать все функции и операции для этого пространства имен доступными, а также упростить чтение кода. В этих двух примерах вызывается та же операция:

 Microsoft.Quantum.Intrinsic.Message("Hello quantum world!");
open Microsoft.Quantum.Intrinsic;
Message("Hello quantum world!");

Обратите внимание, что в примере программы нет open операторов или вызовов с полными пространствами имен. Это связано с тем, что среда разработки Q# по умолчанию автоматически загружает два пространства имен ( Microsoft.Quantum.Core и Microsoft.Quantum.Intrinsic ), которые содержат часто используемые функции и операции.

Вы можете воспользоваться преимуществами Microsoft.Quantum.Measurement пространства имен и использовать MResetZ операцию для оптимизации кода в примере программы. MResetZ объединяет операции измерения и сброса в один шаг, как показано в следующем примере:

namespace Superposition {

    // open the namespace for the MResetZ operation
    open Microsoft.Quantum.Measurement;

    @EntryPoint()
    operation MeasureOneQubit() : Result {
        // Allocate a qubit, by default it is in zero state      
        use q = Qubit();  
        // We apply a Hadamard operation H to the state
        // It now has a 50% chance of being measured 0 or 1  
        H(q);   
        // Measure and reset the qubit, and return the result value   
        return MResetZ(q);
    }
    
}