Упражнение, часть 2. Создание генератора квантовых случайных чисел
В этом уроке вы реализуете вторую часть генератора квантовых случайных чисел. Вы объединяете несколько случайных битов для формирования большего случайного числа. Эта часть основана на генераторе случайных битов, который вы уже создали в предыдущем уроке.
Объединение нескольких случайных битов для формирования большего числа
В предыдущем уроке вы создали генератор случайных битов, который помещает кубит в состояние суперпозиции, а затем измеряет его, чтобы получить случайное значение бита, либо 0, либо 1, с вероятностью 50% для каждого. Значение этого бита действительно случайно, нет способа заранее узнать, какой результат измерения будет. Но как можно использовать это поведение для создания больших случайных чисел?
Если повторить процесс четыре раза, можно создать эту последовательность двоичных цифр:
$${0, 1, 1, 0}$$
При объединении этих битов в битовую строку можно сформировать большее число. В этом примере битовая последовательность ${0110}$ в двоичном файле эквивалентна числу 6 в десятичном разряде.
$${0110_{\ binary} \equiv 6_{\ decimal}} $$
Чтобы создать произвольно большое случайное число, просто повторите этот процесс много раз. Затем объедините все биты в двоичное число и преобразуйте это двоичное число в десятичное число.
Определение логики генератора случайных чисел
Перед написанием кода Q# давайте рассмотрим логику для создания случайного числа:
- Определите
maxкак максимальное десятичное число, которое требуется создать. - Определите количество случайных битов,
nBitsкоторые необходимы для созданияmax. - Создание случайной битовой строки, длина которой равна
nBits. - Если битовая строка представляет число больше
max, а затем вернитесь к предыдущему шагу. - В противном случае процесс завершается. Возвращает созданное число в виде десятичного целого числа.
Например, давайте определим max значение 12. То есть 12 — это наибольшее число, которое генератор случайных чисел должен выводить.
Используйте следующее уравнение, чтобы определить количество битов, необходимых для представления числа 12 в двоичном файле:
$${\lfloor ln(12) / ln(2) + 1 \rfloor}$$
В соответствии с этим уравнением необходимо 4 бита, чтобы представить число от 0 до 12.
Например, предположим, что вы создаете случайный бит четыре раза и получаете битовую строку ${1101_{\ binary}}$. Это значение в двоичном файле равно 13 в десятичном разряде. Так как 13 больше 12, вы повторяете процесс.
Затем вы создайте битовую строку ${0110_{\ binary}}$, которая равна ${6_{\ decimal}}$. Так как 6 меньше 12, процесс завершен.
Генератор квантовых случайных чисел возвращает число 6.
Создание полного генератора случайных чисел в Q#
Здесь вы развернете Main.qs файл из предыдущего урока, чтобы создать генератор случайных чисел.
Импорт необходимых библиотек
Сначала импортируйте пространства имен из стандартной библиотеки Q#, содержащей функции и операции, необходимые для записи программы. Компилятор Q# автоматически загружает множество распространенных функций и операций. Но для генератора квантовых случайных чисел вам потребуется несколько дополнительных функций и операций из двух пространств имен Q#: Microsoft.Quantum.Math и Microsoft.Quantum.Convert.
Скопируйте и вставьте следующие import директивы в начале Main.qs файла:
import Std.Convert.*;
import Std.Math.*;
Примечание.
Вместо импорта функций и операций из стандартной библиотеки можно использовать StdMicrosoft.Quantum .
Переименование операции в MainGenerateRandomBit
Программа генератора случайных чисел использует Main операцию, написанную в предыдущем уроке, для создания случайного бита. Переименуйте операцию с Main на GenerateRandomBit, чтобы операция получила более описательное имя и не служила точкой входа в программу.
Скопируйте и вставьте следующий код в Main.qs:
import Std.Convert.*;
import Std.Math.*;
operation GenerateRandomBit() : Result {
// Allocate a qubit.
use q = Qubit();
// Set the qubit into superposition of 0 and 1 using the Hadamard
H(q);
// Measure the qubit and store the result.
let result = M(q);
// Reset qubit to the |0〉 state.
Reset(q);
// Return the result of the measurement.
return result;
}
Определение операции генератора случайных чисел
Создайте новую операцию с именем GenerateRandomNumberInRange. Эта операция многократно вызывает операцию GenerateRandomBit для создания строки битов.
Скопируйте следующий код и поместите его непосредственно перед операцией GenerateRandomBit в Main.qs файле:
/// 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's within the requested range.
// Generate it again if it's outside the range.
return sample > max ? GenerateRandomNumberInRange(max) | sample;
}
Ниже приведен обзор кода в GenerateRandomNumberInRange:
-
BitSizeIВызовите функцию изStd.Mathбиблиотеки, чтобы вычислить количество битов, необходимых для представления целого числа, хранящегося вmax. -
forИспользуйте цикл для создания числа случайных битов, равныхnBits. Вызовите вашу операциюGenerateRandomBit, чтобы создать случайные биты. - Внутри цикла
forиспользуйте операторsetдля обновления переменнойbitsс каждым новым случайным битом. Переменная — это изменяемая переменнаяbits, которая означает, что значениеbitsможет изменяться во время вычисления. - Вызовите функцию
ResultArrayAsIntиз библиотекиStd.Convert, чтобы преобразовать массив битов в положительное целое число вbits, хранящееся вsample. - В инструкции
returnпроверьте, является лиsampleбольшеmax. Еслиsampleбольшеmax, вызовитеGenerateRandomNumberInRangeеще раз и начните. В противном случае верните случайное число, хранящееся вsample.
Добавление точки входа
Наконец, добавьте операцию точки входа в код, чтобы компилятор смог запустить программу. По умолчанию компилятор Q# ищет Main операцию и использует Main ее в качестве точки входа независимо от того, где Main находится в файле.
Main операция задает значение для max и вызывает операцию GenerateRandomNumberInRange, чтобы создать случайное число от 0 до max.
Например, чтобы создать случайное число от 0 до 100, скопируйте следующий код в Main.qs файл:
operation Main() : Int {
let max = 100;
Message($"Generating a random number between 0 and {max}: ");
// Generate random number in the 0..max range.
return GenerateRandomNumberInRange(max);
}
Окончательная программа
Вот полный код Q# для вашей программы в Main.qs:
import Std.Convert.*;
import Std.Math.*;
operation Main() : Int {
let max = 100;
Message($"Generating 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's within the requested range.
// Generate it again if it's 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 operation
H(q);
// 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.
Reset(q);
// Return the result of the measurement.
return result;
}
Запуск программы
Попробуйте новый генератор квантовых случайных чисел!
Чтобы запустить программу, выберите линзу кода запуска из списка команд над операцией Main. Или нажмите клавиши CTRL+F5. Выходные данные отображаются в консоли отладки. Запустите программу несколько раз и обратите внимание на изменение результата.
Поздравляем! Вы создали действительно случайный генератор квантовых чисел в Q#.
Дополнительное упражнение
Попробуйте изменить программу таким образом, чтобы она также требует, чтобы созданное случайное число было больше некоторого минимального положительного числа, minа не нуля.