练习第 2 部分 - 创建量子随机数生成器
在此单元中,你将实现量子随机数生成器的第二个阶段:组合多个随机位以形成更大的随机数。 此阶段基于在上一单元中创建的随机位生成器而构建。
将多个随机位组合成一个较大的数
在上一个单元中,你创建了一个随机位生成器,该生成器将一个量子比特置于叠加态并对其进行测量,从而生成随机位。
当你测量量子比特时,你将得到一个随机位,值为 0 或 1,概率均为 50%。 此位的值是真正随机的,没有办法知道在测量之后你会得到什么。 但如何才能通过这种行为生成更大的随机数?
假设重复这个过程四次,生成以下二进制数字序列:
$${0, 1, 1, 0}$$
如果将这些位连接或合并成一个位字符串,就可以形成更大的数字。 在此示例中,位序列 ${0110}$ 等同于十进制的 6。
$${0110_{\ binary} \equiv 6_{\ decimal}}$$
如果多次重复执行此过程,则可以将多个比特组合成任何一个大数字。
定义随机数生成器逻辑
让我们概述一下随机数生成器的逻辑应该是什么(假设前面的单元中内置了随机比特生成器):
- 将
max
定义为要生成的最大数字。 - 通过计算表示最高到
max
的整数所需的位数nBits
,定义需要生成的随机位数。 - 生成长度为
nBits
的随机位字符串。 - 如果位字符串表示一个大于
max
的数,则返回到步骤 3。 - 否则,此过程完成。 返回生成的数字(整数形式)。
例如,我们将 max
设置为 12。 也就是说,12 是你想要从随机数生成器获得的最大数字。
需要 ${\lfloor ln(12) / ln(2) + 1 \rfloor}$ 或 4 比特来表示一个介于 0 和 12 之间的数字。 (为简便起见,我们跳过推导此公式的过程。)
假设生成了位字符串 ${1101_{\ binary}}$,它等同于 ${13_{\ decimal}}$。 由于 13 大于 12,因此将复该过程。
接下来,生成位字符串 ${0110_{\ binary}}$,它等同于 ${6_{\ decimal}}$。 由于 6 小于 12,因此该过程完成。
量子随机数生成器返回数字 6。
创建完整的随机数生成器
在这里,你将展开 Main.qs
文件以生成更大的随机数。
导入所需的库
首先,需要将所需的命名空间从 Q# 标准库导入到程序。 Q# 编译器会自动加载许多常见函数和操作,但对于完整的量子随机数生成器,需要使用两个 Q# 命名空间中的一些其他函数和操作:Microsoft.Quantum.Math
和 Microsoft.Quantum.Convert
。
将以下 import
指令复制并粘贴到 Main.qs
文件顶部:
import Microsoft.Quantum.Convert.*;
import Microsoft.Quantum.Math.*;
将 Main
操作重命名为 GenerateRandomBit
对于完整的随机数生成器,你将重用在上一单元中定义的操作。 但操作名称 Main
是程序的入口点,并且应该是唯一的。 要避免混淆,需要将 Main
操作重命名为 GenerateRandomBit
。
GenerateRandomBit
操作现在应如下所示:
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
操作以生成位字符串。
复制以下代码并将其粘贴到 Main.qs
文件中 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
的整数所需的位数。Microsoft.Quantum.Math
库中的BitSizeI
函数将整数转换为表示该整数所需的位数。 GenerateRandomNumberInRange
操作使用for
循环来生成随机数,直到生成的数字等于或小于max
为止。for
循环的工作方式与其他编程语言中的for
循环完全相同。- 变量
bits
是可变变量。 可变变量是计算过程中可以更改的变量。 使用set
指令可以更改可变变量的值。 ResultArrayAsInt
函数来自Microsoft.Quantum.Convert
库。 此函数将位字符串转换为正整数。
添加入口点
最后,向程序添加入口点。 默认情况下,无论 Main
操作位于何处,Q# 编译器都会查找它并在该处开始处理。 该 Main
操作会调用 GenerateRandomNumberInRange
操作以生成介于 0 和数字 max
之间的随机数。 在此示例中,你将最大值定义为 100。
将以下代码复制并粘贴到 Main.qs
文件中:
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);
}
最终程序
Main.qs
文件应如下所示:
import Microsoft.Quantum.Convert.*;
import Microsoft.Quantum.Math.*;
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 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;
}
运行程序
让我们尝试使用新的随机数生成器!
- 在运行程序之前,需要将目标配置文件设置为“不受限制”。 选择“视图”>“命令面板”,搜索 QIR,然后选择“Q#:设置 Azure Quantum QIR 目标配置文件”,然后选择“Q#: 不受限制”。
- 要运行程序,请从
Main
操作上方的命令列表中选择“运行”,或按 Ctrl+F5。 输出会显示在调试控制台中。 - 再次运行程序以查看不同的结果。
注意
如果未将目标配置文件设置为“不受限制”,则运行程序时会出现错误。
祝贺你! 现在,你已了解如何结合使用传统逻辑和 Q# 来创建量子随机数生成器。
额外练习
尝试修改程序,同时要求生成的随机数还需要大于某个最小数 min
而不是 0。