作者:1.丘秉宜,2.邵伟,3.黄文,4.郭梦杰
*1.亚马逊云科技 HERO;2.开发者生态负责人;3.DEVOPS 工程师;4.资深研发工程师*
## **1、概述**
随机性(Randomness)是偶然性的一种形式,具有某一概率的事件集合中的各个事件所表现出来的不确定性。对于一个随机事件可以探讨其可能出现的概率,反映该事件发生的可能性的大小。随机性在自然科学和哲学上有着重要的地位,也吸引大量的学者在这方面的研究,随机性在实际应用中也是一种极其重要的资源,当前在许多的领域中发挥着重要的作用,例如博弈,统计抽样,计算机模拟,密码学等。
那么,什么是随机数呢?通俗地讲,随机数序列是对一个均匀分布随机变量的一组抽样,其结果是不可预测的,序列中的每个数都是独立的,且服从均匀分布的。随机数通常是由随机数发生器(Random Number Generator 简称 RNG)来产生的。随机数生成是通过随机数生成器(RNG)生成一系列数字或者符号的过程,这些数字和符号无法比随机机会获更好合理预测。这意味着,特定的结果序列将包含一些事后可察觉但无法预见的模式。
## **2、真随机数和伪随机数**
在计算中,硬件随机数生成器(HRNG)或真随机数生成器是一种从物理过程而不是通过算法生成随机数的设备。这种装置通常基于微观现象,这些微观现象产生低水平的、统计上随机的“噪声”信号,如热噪声、光电效应(涉及分束器)和其他量子现象。理论上,这些随机过程是完全不可预测的,只要控制这种现象的方程是未知的或不可计算的。这与通常在计算机程序中实现的伪随机数生成的范例形成对比。
伪随机数生成器(PRNG),也称为确定性随机位生成器(DRBG),是一种用于生成其属性近似于随机数序列属性的数字序列的算法。PRNG生成的序列不是真正随机的,因为它完全由称为 PRNG 的种子(可能包括真正随机的值)的初始值确定。虽然可以使用硬件随机数生成器生成更接近真实随机的序列,但伪随机数生成器在实际中对其生成数字的速度和再现性非常重要。随机数发生器在模拟(例如,蒙特卡洛方法)、电子游戏(例如,程序生成)和密码学等应用中至关重要。密码应用要求输出不能从早期输出中预测,需要更复杂的算法,这些算法不继承简单 PRNG 的线性。
如何才能生成随机数?生成随机数有两种主要方法:
- 第一种方法测量一些预期随机的物理现象,然后补偿测量过程中可能的偏差。示例源包括测量大气噪声、热噪声和其他外部电磁和量子现象。例如,在短时间尺度上测量的宇宙背景辐射或放射性衰变代表了自然熵的来源。从自然来源获得熵的速度取决于所测量的基本物理现象。因此,自然产生的“真实”熵的来源被称为是阻塞的——在获得足够的熵以满足需求之前,它们是速率受限的。在一些类 Unix 系统(包括大多数 Linux 发行版)上,伪设备文件 /dev/random 将被阻止,直到从环境中获得足够的熵。由于这种阻止行为,在使用这种类型的熵源的系统上,从 /dev/random 进行大容量读取(例如用随机位填充硬盘驱动器)通常会很慢。
- 第二种方法使用计算算法,可以产生长序列的明显随机结果,这些结果实际上完全由一个较短的初始值(称为种子值或密钥)决定。结果,如果种子值已知,则可以再现整个看似随机的序列。这种类型的随机数生成器通常被称为伪随机数生成器。这种类型的生成器通常不依赖于自然产生的熵源,尽管它可以由自然源周期性地播种。这种生成器类型是非阻塞的,因此它们不受外部事件的速率限制,因此可以进行大容量读取。
还有一些系统采用真随机和伪随机混合的方法,在可用时提供从自然来源获取的随机性,并返回到基于加密安全伪随机数生成器(CSPRNG)的定期重新播种软件。当期望的随机读取速率超过自然收获方法跟上需求的能力时,会发生回退。该方法避免了基于较慢和纯环境方法的随机数生成器的速率受限阻塞行为。
虽然仅基于确定性逻辑的伪随机数生成器永远不能被视为最纯粹意义上的“真实”随机数源,但实际上,它们通常足以满足要求严格的安全关键应用。精心设计和实现的伪随机数生成器可以被认证用于安全关键的加密目的,正如 yarrow 算法和 fortuna 的情况一样。前者是 FreeBSD、AIX、OS X、NetBSD 和其他平台上的 /dev/random 熵源的基础。OpenBSD 使用一种称为 arc4random 的伪随机数算法。
## **3、量子随机数**
现在常用的依靠计算机模拟产生的伪随机数,或者从某些经典物理噪声(如热噪声,电噪声等)中提取随机数,实际上并不是正真正的随机数,因为从理论上讲,经典物理过程在考虑到所有变量的情况下是可以被模拟的。那么是否存在真正的随机数呢,随着量子力学的发展,通过量子系统产生随机数已经成为可能。
量子物理过程所产生的随机性是完全真随机的,比如量子态的坍缩过程。考虑处于叠加状态的一个量子比特:
![1.png](https://dev-media.amazoncloud.cn/b7f6c23071fd41d3974f5aa57d0d51fb_1.png "1.png")
当使用 Z 基对此比特进行操作然后测量该量子比特时,将以1/2的概率测得
![image.png](https://dev-media.amazoncloud.cn/20cbe74a09c34b8dac47719940b405cf_image.png "image.png")
1/2的概率测得
![image.png](https://dev-media.amazoncloud.cn/702597b8045a4dc6808c5440712bad66_image.png "image.png")
值得注意的是,量子态的测量与抛硬币情况不同,这里出现的随机性是量子系统所固有的,而不是因为对系统的不了解而产生的。也就是说,用这样的测量方式来观测这样的态(两者均明确已知),其观测结果就是随机的,这是由量子力学基本原理决定的。使用量子系统的这种内禀随机性产生的随机数就是真随机数。
## **4、启科 QuSaaS 量子真随机数解决方案**
针对应用中需要使用真随机数的场景,启科推出了自己真随机数方案。在介绍启科真随机数解决方案之前,启科旗下的几个软件平台需要先和大家简要介绍一下:
**QuSaaS**:启科量子的开发者社区平台,提供量子计算 API 调用,量子应用创建及应用部署调用接口。
**QuPot**:启科量子私有云平台,管理启科的模 拟量子计算、量子计算应用集成与解耦部署,例如Qubox。
**QuTrunK**:QuTrunk 是启科量子自主研发的一款免费、开源、跨平台的量子计算编程框架,包括量子编程 API、量子命令转译、量子计算后端接口等。 Qutrunk 使用 Python 作为宿主语言,利用 Python 的语法特性实现针对量子程序的 DSL (领域专用语言),基于量子逻辑门、量子线路等概念提供量子编程所需各类 API。它也可以作为其他上层量子计算的应用的基础。
**QuSprout**:QuSprout 是启科量子自主研发的一款免费、开源的量子计算模拟后端,用户在 QuTrunk 量子编程框架生成量子线路后, 如果需要更高的运行效率,需要连接到 QuSprout 计算后端来进行模拟计算。QuSprout 使用 C++ 作为宿主语言, 支持多个量子线路的任务管理、MPI 多进程并行计算。
**QuBox**:预装 QuSprout 的 PKS 体系硬件,以产品形态 为用户提供量子模拟资源
用户使用启科真量子随机数解决方案,有两个使用场景可以采用:
1)使用启科开源量子编程框架 Qutrunk 开发量子计算程序,采用自建模拟量子计算资源。即用户采购Qubox部署到自己机房,本地开发直接通过访问本地机房的 qubox 硬件资源,调用 qusprout 的 API 访问 QRNG 产生随机数。
2)直接使用启科量子提供的云上资源,用户注册 QuSaaS,根据 QuSaaS 应用部署创建模板要求开发量子应用,注册应用获取 AK,SK,调测中通过 API 网关调用随机数卡的接口,QuSaaS 进行认证授权通过 Qusprout 调用 qubox 随机数卡生成随机数。开发完成后通过 QuSaaS 部署应用到 QuPot,此时应用运行在一个 qutrunk 环境中,掉用随机数过程与本地调用流程一致。逻辑图如下:
![1.png](https://dev-media.amazoncloud.cn/73b2da49d0b24d5da6f9e21135415902_1.png "1.png")
## **5、QuSaaS 真随机数与 Amazon Braket 结合示例**
[Amazon Braket](https://aws.amazon.com/cn/braket/?trk=cndc-detail) 是一项完全托管式量子计算服务,旨在帮助加快量子计算的科学研究和软件开发。用户可以通过本地 Jupyter Notebook/IDE 或者 Amazon console 使用 [Amazon Braket](https://aws.amazon.com/cn/braket/?trk=cndc-detail) SDK 开发量子程序,调用亚马逊云科技提供量子硬件或者模拟资源运行量子计算程序。
![2.png](https://dev-media.amazoncloud.cn/aa3691d7f3574d8b869b34c57adfa85b_2.png "2.png")
此前不久我们针对 Qutrunk,QuSprout 与 [Amazon Braket](https://aws.amazon.com/cn/braket/?trk=cndc-detail) 结合实践上已经有了一些文章发布,我们本次在此基础上进一步拓展到其他服务。本文将针对 QuTrunk 结合 Amazon Barket后端然利用 QuSaaS 的真随机数接入服务来完成一个小的演示示例。下面我们将分布进行说明。
如果需要使用 QuSaaS 真随机数需要按照如下流程操作:
![3.png](https://dev-media.amazoncloud.cn/a7ab730c133c427abbd92fdd76b8aa48_3.png "3.png")
### **5.1 QuSaaS 真随机数获取操作步骤**
1、注册 QuSaaS
登录 QuSasS 网站:http://developer.queco.cn/ 点击右上角注册按钮,完成注册
![4.png](https://dev-media.amazoncloud.cn/96ee67a91f004f22854b32fea81475d0_4.png "4.png")
2、通过 QuSaaS 下载中心下载 QuBranch 和 QuTrunk,并完成本地开发环境部署。详细的安装及部署材质指导请参考 QuSaaS 上的学习文档:http://developer.queco.cn/learn/doc/detail?id=12&childrenid=14
3、点击 API 商城采购 Qutrunk 云接口,新注册用户提供一定配额的免费额度。
![5.png](https://dev-media.amazoncloud.cn/56d789ebf57642bca35223d6d92693c7_5.png "5.png")
4、点击右上角个人用户名,选择我的应用,打开应用注册页面。
![6.png](https://dev-media.amazoncloud.cn/a7a6d4d2da7b432e9fb53220c2629dfa_6.png "6.png")
然后点击创建应用,完成应用创建,并可以获取到 API 的 AK 和 SK 信息。
![7.png](https://dev-media.amazoncloud.cn/2e574b31f4c747bd9315431f541c445b_7.png "7.png")
5、使用 QuTrunk 开发程序调用随机数
1)首先导入 qutrunk 使用的后端模块,使用 QuSaaS 作为后端。
2)从 QuSaaS 上获取的 AK 和 SK 信息,指定调用的 ak 和 sk 参数的值
3)调用 QuSaaS 后端获取真随机数
4)打印获取的随机数的值
代码如下:
```
from qutrunk.backends import BackendQuSaas, BackendQuSprout
ak = "BNwHKbBIkVT8DSfDlWnZl4rosB7Ie7hhvDvRehyz"
sk = "V2ZfqQJPiaCQhrzAeIIZjNilBrTdqQEujkqXrUP3MtYt1vPCbBo47e8gwRjJcJlaXNJSParPOudhaX8WesvfXSAeb1yYfvC6gbElHoNoH7ali4jLvuxI87v3NCjPMCmu"
# use BackendQuSaas
be = BackendQuSaas(ak, sk)
# generate random number
rands = be.get_rand(20, 2)
print(rands)
```
打印结果如下:
```
[b"V\\xf1\\xcf\\x1c\\xd2p?\\xa3Z`d\\xdc'6\\x8c2\\xbfj\\xee\\x90", b"su\\x073'&\\xce\\xfe\\xfbF%\\xf3\\xb3\\x93\\x13\\xc5\\x83\\x8a\\xa3s"]
```
### **5.2 Amazon Braket 使用 QuSaaS 真随机数**
我们展示一个使用 [Amazon Braket](https://aws.amazon.com/cn/braket/?trk=cndc-detail) 后端运行贝尔电路的例子。使用模拟量子计算的时候需要用到随机数,我们这里通过 QuSaaS 获取的真随机数作为随机数种子来产生随机数,以运行贝尔电路。
1、首先准备环境,导入需要用到的模块
```
import numpy as np
from qutrunk.backends import BackendQuSaas
from qutrunk.backends.braket import BackendAWSLocal
from qutrunk.circuit import QCircuit
from qutrunk.circuit.gates import H, CNOT, All, Measure
```
2、调用 SaaS 后端获取真随机数
设置获取真随机数的长度为4,指定 ak 和 sk 为我们账号下注册应用的 AK 和 SK,然后指定使用 QuSaaS 后端,通过 get_rand() 函数获得随机数。
```
BYTE_LEN4INT = 4
ak = "BNwHKbBIkVT8DSfDlWnZl4rosB7Ie7hhvDvRehyz"
sk = "V2ZfqQJPiaCQhrzAeIIZjNilBrTdqQEujkqXrUP3MtYt1vPCbBo47e8gwRjJcJlaXNJSParPOudhaX8WesvfXSAeb1yYfvC6gbElHoNoH7ali4jLvuxI87v3NCjPMCmu"
saas_be = BackendQuSaas(ak, sk)
rand_bytes = saas_be.get_rand(BYTE_LEN4INT, 1)
print(rand_bytes)
```
输出的随机数:
```
b'v\\x1b\\xd6\\xaf'
```
3、随机数转换
我们生成的随机数默认是16进制数,需要转换成10进制整数。
```
rand_int = int.from_bytes(rand_bytes[0], byteorder='big')
print(rand_int)
1981535919
```
4、亚马逊云科技后端使用真随机数,运行贝尔电路
亚马逊云科技本地模拟是使用 numpy 实现,我们将生成的随机数用于亚马逊云科技本地后端的模拟,使用真随机数作为 numpy 随机数生成的种子。然后通过亚马逊云科技后端运行贝尔电路。
```
np.random.seed(rand_int)
qc = QCircuit(backend=BackendAWSLocal())
qr = qc.allocate(2)
# Apply quantum gate
H * qr[0]
CNOT * (qr[0], qr[1])
# Measure all quantum qubits
All(Measure) * qr
# Print quantum circuit as operqasm grammar
qc.print(format="openqasm")
# Run quantum circuit
res = qc.run(1024)
print(res.get_counts())
运行结果如下:
OPENQASM 2.0;
include "qulib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0],q[1];
measure q[0] -> c[0];
measure q[1] -> c[1];
[{"00": 493}, {"11": 531}]
```
**作者:**
![丘秉宜.png](https://dev-media.amazoncloud.cn/5cdb499fb00a441693dd6cd8015fcd6f_%E4%B8%98%E7%A7%89%E5%AE%9C.png "丘秉宜.png")
Keith Yan(丘秉宜)中国首位亚马逊云科技 Community Hero。
![邵伟.png](https://dev-media.amazoncloud.cn/5dca4d9f50384f959d279eeef2ac87ab_%E9%82%B5%E4%BC%9F.png "邵伟.png")
Bertran Shao(邵伟),启科量子开发者关系负责人,国内首个开源量子计算社区发起者。
![黄文.jpg](https://dev-media.amazoncloud.cn/f8067819219f4cbdbe47b419c1e0b12f_%E9%BB%84%E6%96%87.jpg "黄文.jpg")
黄文,启科量子 DEVOPS 工程师
![郭梦杰.jpg](https://dev-media.amazoncloud.cn/e977fc3bd68942deb14918d3908ae802_%E9%83%AD%E6%A2%A6%E6%9D%B0.jpg "郭梦杰.jpg")
Marz Kuo(郭梦杰),启科量子资深研发工程师,量子计算开源框架维护人