Учебник. Реализация квантового генератора случайных чисел на языке Q#
Примечание
Microsoft Quantum Development Kit (классический QDK) больше не будет поддерживаться после 30 июня 2024 г. Если вы уже являетесь разработчиком QDK, мы рекомендуем перейти на новую версию Azure Quantum Development Kit (современный QDK), чтобы продолжить разработку квантовых решений. Дополнительные сведения см. в статье Перенос Q# кода в современный QDK.
Здесь вы узнаете, как создать простую квантовую программу на языке Q#, которая использует природу квантовой механики для получения случайного числа.
Выполняя данное руководство, вы сделаете следующее:
- Q# Create программы.
- Просмотрите main компоненты Q# программы.
- Определите логику задачи.
- Сочетание классических и квантовых операций для решения задачи.
- Работа с кубитами и суперпозицией для создания квантового генератора случайных чисел.
Совет
Если вы хотите ускорить путь квантовых вычислений, проверка код с помощью Azure Quantum, уникальной функции веб-сайта Azure Quantum. Здесь можно запускать встроенные Q# примеры или собственные Q# программы, создавать новый Q# код на основе запросов, открывать и запускать код в VS Code для Интернета одним щелчком мыши и задавать Copilot любые вопросы о квантовых вычислениях.
Предварительные требования
Чтобы запустить пример кода в Copilot в Azure Quantum, выполните следующие действия.
- Учетная запись электронной почты Майкрософт (MSA).
Чтобы разработать и запустить пример кода в Visual Studio Code:
Последняя версия Visual Studio Code или откройте VS Code в Интернете.
Последняя версия расширения Azure Quantum Development Kit . Сведения об установке см. в статье Установка современного QDK в VS Code.
Если вы хотите использовать Jupyter Notebook, необходимо также установить Python, расширения Jupyter , а также последнюю версию
qsharp
пакета Python. Для этого откройте терминал и выполните следующую команду:$ pip install --upgrade qsharp
Определение проблемы
На классических компьютерах действительно случайные числа не создаются, а лишь псевдослучайные. Генератор псевдослучайных чисел создает детерминированную последовательность чисел на основе некоторого начального значения. Для более точной аппроксимации случайных значений этим начальным значением часто является текущее время таймера ЦП.
Квантовые компьютеры, с другой стороны, могут генерировать действительно случайные числа. Это связано с тем, что измерение кубита в суперпозиции является вероятностным процессом. Результат измерения является случайным, и невозможно предсказать результат. Это основной принцип квантовых генераторов случайных чисел.
Кубит — это единица квантовой информации, которая может находиться в суперпозиции. При измерении кубит может принимать только два состояния: 0 или 1. Однако до измерения состояние кубита представляет вероятность получить значение 0 или 1 при измерении.
Для начала возьмите кубит в базовом состоянии, например 0. Первым шагом генератора случайных чисел является использование операции Hadamard, чтобы поместить кубит в равную суперпозицию. Измерение этого состояния приводит к нулю или единице с вероятностью 50 % каждого результата, действительно случайным битом.
Невозможно узнать, что вы получите после измерения кубита в суперпозиции, и результатом будет другое значение при каждом вызове кода. Но как можно использовать это поведение для создания больших случайных чисел?
Предположим, что вы повторяете этот процесс четыре раза, создав следующую последовательность двоичных цифр:
$${0, 1, 1, 0}$$
Если сцепить (или объединить) эти биты в битовую строку, можно получить большее число. В этом примере битовая последовательность ${0110}$ эквивалентна шести в десятичном формате.
$${0110_{\ binary} \equiv 6_{\ decimal}}$$
Если повторить этот процесс много раз, можно объединить несколько битов для формирования любого большого числа. Затем это число можно использовать в качестве надежного пароля, и вы можете быть уверены, что ни один космический хакер не сможет определить результаты последовательности измерений.
Определение логики генератора случайных чисел
Давайте рассмотрим логику генератора случайных чисел при условии, что у нас есть генератор случайных битов:
- Определите
max
как максимальное число, которое требуется создать. - Определите количество случайных битов, которые требуется создать. Для этого вычисляется количество битов (
nBits
), необходимых для выражения целых чисел вплоть доmax
. - Создание случайной битовой строки, длина которой равна
nBits
. - Если битовая строка представляет число больше
max
, выполняется возврат к шагу 3. - В противном случае процесс завершается. Возврат созданного числа в виде целого числа.
В качестве примера зададим для max
значение 12. То есть 12 — это максимальное число, которое требуется использовать в качестве надежного пароля.
Для представления числа от 0 до 12 требуется ${\lfloor ln(12) / ln(2) + 1 \rfloor}$ или 4 бита. (Для краткости мы опустим вывод этого уравнения.)
Предположим, что вы создаете битовую строку $${1101_{\ binary}}$, которая эквивалентна ${13_{\ decimal}}$. Так как 13 больше 12, вы повторяете процесс.
Затем создается битовая строка ${0110_{\ binary}}$, которая эквивалентна ${6_{\ decimal}}$. Так как 6 меньше 12, процесс завершен.
Квантовый генератор случайных чисел вернет число 6 в качестве пароля. На практике в качестве максимального следует задать большее число, поскольку более низкие числа легко взломать простым перебором всех возможных паролей. Чтобы повысить устойчивость пароля к перебору или взлому, можно использовать код ASCII для преобразования двоичных данных в текст и создания пароля с помощью чисел, символов и букв в разных регистрах.
Создание генератора случайных битов
Первым шагом является запись Q# операции, которая создает случайный бит. Эта операция будет одним из стандартных блоков генератора случайных чисел.
operation GenerateRandomBit() : Result {
// Allocate a qubit.
use q = Qubit();
// Set the qubit into superposition of 0 and 1 using the Hadamard
H(q);
// At this point the qubit `q` has 50% chance of being measured in the
// |0〉 state and 50% chance of being measured in the |1〉 state.
// Measure the qubit value using the `M` operation, and store the
// measurement value in the `result` variable.
let result = M(q);
// Reset qubit to the |0〉 state.
// Qubits must be in the |0〉 state by the time they are released.
Reset(q);
// Return the result of the measurement.
return result;
}
Теперь давайте изучим этот новый код.
- Вы определяете операцию
GenerateRandomBit
, которая не принимает никаких входных данных и формирует значение типаResult
. ТипResult
представляет результат измерения и может иметь два возможных значения:Zero
илиOne
. - Вы выделяете один кубит с
use
помощью ключевое слово. Только что выделенный кубит всегда находится в состоянииZero
. - Операция используется
H
для размещения кубита в равной суперпозиции. - Операция используется для
M
измерения кубита, возврата измеряемого значения (Zero
илиOne
). - Операция используется
Reset
для сброса кубита в состояние |0〉.
Если мы переводим кубит в состояние суперпозиции с помощью операции H
и измеряем его с помощью операции M
, при каждом вызове кода возвращаются разные результаты.
Визуализация Q# кода с помощью сферы Блоха
В сфере Блоха северный полюс соответствует классическому значению 0, а южный — классическому значению 1. Любое состояние суперпозиции обозначается точкой на этой сфере (или стрелкой на схеме). Чем ближе конец этой стрелки к одному из полюсов, тем выше вероятность схлопывания этого кубита при измерении в то классическое состояние, которое соответствует этому полюсу. В примере ниже красная стрелка обозначает состояние кубита с более высокой вероятностью получить значение 0 при измерении кубита.
Вы можете использовать это представление для визуализации работы нашего кода.
Для начала инициализируйте кубит в состоянии 0 и примените
H
, чтобы создать состояние суперпозиции с равной вероятностью получить значения 0 и 1.Затем измерьте состояние кубита и сохраните выходное значение:
Поскольку результат измерения является случайным и вероятности получения 0 и 1 одинаковы, вы получили совершенно случайный бит. Вызывая эту операцию несколько раз, вы можете создавать большие целые числа. Например, три вызова этой операции предоставят вам три случайных бита, из которых можно собрать трехбитовое число (то есть случайное число в диапазоне от 0 до 7).
Создание полного генератора случайных чисел
Сначала необходимо добавить необходимые Q# пространства имен в программу. Для полного генератора случайных чисел необходимо включить три Q# пространства имен:
Microsoft.Quantum.Math
,Microsoft.Quantum.Intrinsic
иMicrosoft.Quantum.Convert
.open Microsoft.Quantum.Convert; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Math;
Затем определите
GenerateRandomNumberInRange
операцию. Эта операция многократно вызывает операциюGenerateRandomBit
для создания строки битов./// Generates a random number between 0 and `max`. operation GenerateRandomNumberInRange(max : Int) : Int { // Determine the number of bits needed to represent `max` and store it // in the `nBits` variable. Then generate `nBits` random bits which will // represent the generated random number. mutable bits = []; let nBits = BitSizeI(max); for idxBit in 1..nBits { set bits += [GenerateRandomBit()]; } let sample = ResultArrayAsInt(bits); // Return random number if it is within the requested range. // Generate it again if it is outside the range. return sample > max ? GenerateRandomNumberInRange(max) | sample; }
Рассмотрим этот новый код.
- Необходимо вычислить количество битов, необходимых для выражения целых чисел, вплоть до
max
. ФункцияBitSizeI
изMicrosoft.Quantum.Math
пространства имен преобразует целое число в число битов, необходимых для его представления. - Операция
SampleRandomNumberInRange
использует циклfor
для создания случайных чисел до тех пор, пока не будет получено значение, которое меньше или равноmax
. Циклfor
работает точно так же, какfor
цикл в других языках программирования. - Переменная
bits
является изменяемой переменной. Изменяемая переменная может изменяться во время вычисления. Для изменения значения изменяемой переменной используется директиваset
. - Функция
ResultArrayAsInt
поступает изMicrosoft.Quantum.Convert
пространства имен . Эта функция преобразует битовую строку в положительное целое число.
- Необходимо вычислить количество битов, необходимых для выражения целых чисел, вплоть до
Наконец, вы добавляете точку входа. В этом примере
Main
операция является точкой входа программы. Он вызываетGenerateRandomNumberInRange
операцию для создания случайного числа в диапазоне от 0 до 100.@EntryPoint() operation Main() : Int { let max = 100; Message($"Sampling a random number between 0 and {max}: "); // Generate random number in the 0..max range. return GenerateRandomNumberInRange(max); }
Директива
let
объявляет переменные, которые не меняются во время вычисления. Здесь мы определяем максимальное значение как 100.Полный код генератора случайных чисел выглядит следующим образом:
namespace QuantumRandomNumberGenerator {
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Math;
@EntryPoint()
operation Main() : Int {
let max = 100;
Message($"Sampling a random number between 0 and {max}: ");
// Generate random number in the 0..max range.
return GenerateRandomNumberInRange(max);
}
/// Generates a random number between 0 and `max`.
operation GenerateRandomNumberInRange(max : Int) : Int {
// Determine the number of bits needed to represent `max` and store it
// in the `nBits` variable. Then generate `nBits` random bits which will
// represent the generated random number.
mutable bits = [];
let nBits = BitSizeI(max);
for idxBit in 1..nBits {
set bits += [GenerateRandomBit()];
}
let sample = ResultArrayAsInt(bits);
// Return random number if it is within the requested range.
// Generate it again if it is outside the range.
return sample > max ? GenerateRandomNumberInRange(max) | sample;
}
operation GenerateRandomBit() : Result {
// Allocate a qubit.
use q = Qubit();
// Set the qubit into superposition of 0 and 1 using the Hadamard
H(q);
// At this point the qubit `q` has 50% chance of being measured in the
// |0〉 state and 50% chance of being measured in the |1〉 state.
// Measure the qubit value using the `M` operation, and store the
// measurement value in the `result` variable.
let result = M(q);
// Reset qubit to the |0〉 state.
// Qubits must be in the |0〉 state by the time they are released.
Reset(q);
// Return the result of the measurement.
return result;
}
}
Запуск программы генератора случайных чисел
Программу можно запустить в Copilot в Azure Quantum, а также в Visual Studio Code как автономное Q# приложение или с помощью хост-программы Python.
Вы можете бесплатно протестировать Q# код с помощью Copilot в Azure Quantum. Вам потребуется только учетная запись электронной почты Майкрософт (MSA). Дополнительные сведения о Copilot в Azure Quantum см. в статье Изучение Azure Quantum.
Откройте Copilot в Azure Quantum в браузере.
Скопируйте и вставьте следующий код в редактор кода.
namespace Tutorial { open Microsoft.Quantum.Convert; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Math; @EntryPoint() operation Main() : Int { let max = 100; Message($"Sampling a random number between 0 and {max}: "); // Generate random number in the 0..max range. return GenerateRandomNumberInRange(max); } /// # Summary /// Generates a random number between 0 and `max`. operation GenerateRandomNumberInRange(max : Int) : Int { // Determine the number of bits needed to represent `max` and store it // in the `nBits` variable. Then generate `nBits` random bits which will // represent the generated random number. mutable bits = []; let nBits = BitSizeI(max); for idxBit in 1..nBits { set bits += [GenerateRandomBit()]; } let sample = ResultArrayAsInt(bits); // Return random number if it is within the requested range. // Generate it again if it is outside the range. return sample > max ? GenerateRandomNumberInRange(max) | sample; } /// # Summary /// Generates a random bit. operation GenerateRandomBit() : Result { // Allocate a qubit. use q = Qubit(); // Set the qubit into superposition of 0 and 1 using the Hadamard // operation `H`. H(q); // At this point the qubit `q` has 50% chance of being measured in the // |0〉 state and 50% chance of being measured in the |1〉 state. // Measure the qubit value using the `M` operation, and store the // measurement value in the `result` variable. let result = M(q); // Reset qubit to the |0〉 state. // Qubits must be in the |0〉 state by the time they are released. Reset(q); // Return the result of the measurement. return result; // Note that Qubit `q` is automatically released at the end of the block. } }
Выберите количество снимков для выполнения и нажмите кнопку Выполнить.
Результаты отображаются в гистограмме и в полях Результаты .
Щелкните Объяснить код , чтобы предложить Copilot объяснить код.
Совет
В Copilot в Azure Quantum можно открыть программу в VS Code для Интернета , нажав кнопку с логотипом VS Code в правом углу редактора кода.
Примечание
Этот фрагмент кода в настоящее время не выполняется на доступном оборудовании targetsAzure Quantum, так как вызываемому объекту требуется ResultArrayAsInt
QPU с полным профилем вычислений.
Дальнейшие действия
Ознакомьтесь с другими учебниками по Q#:
- Квантовая запутанность показывает, как написать Q# программу, которая управляет кубитами и измеряет их, а также демонстрирует эффекты суперпозиции и запутанности.
- Алгоритм поиска Гровера показывает, как написать Q# программу, которая использует алгоритм поиска Гровера.
- Квантовые преобразования Фурье исследует, как написать Q# программу, которая непосредственно обращается к конкретным кубитам.
- Quantum Katas — это учебники в произвольном темпе и упражнения по программированию, направленные на одновременное обучение элементам квантовых вычислений и Q# программирования.
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по