html随机数生成器(html随机选数代码介绍)

用量子计算模拟器ProjectQ生成随机数,并用pytest进行单元测试与覆盖率测试,以及基于flake8的编码规范测试

目录

  • 技术背景
    • 随机数的应用
    • 量子计算与随机数
    • 基于pytest的python单元测试框架
  • 量子计算产生随机数
    • 注意!!!
  • pytest测试
    • 安装pytest库
    • pytest单元测试用例撰写
    • pytest初始化配置文件
    • pytest生成html格式报告
    • pytest覆盖率测试
  • 使用flake8进行python编码规范检查
  • 总结概要
  • 版权声明
  • 参考链接

技术背景

本文中主要包含有三个领域的知识点:随机数的应用、量子计算模拟产生随机数与基于pytest框架的单元测试与覆盖率测试,这里先简单分别介绍一下背景知识。

随机数的应用

在上一篇介绍量子态模拟采样的算法中,我们就使用到了随机数,随机数在各种蒙特卡洛方法与数值计算中,扮演着非常重要的角色。在金融领域,随机数则是在加密算法中扮演重要角色,其风险在于,如果随机数可被预测,那么恶意用户就可以利用这一特点,破解对称加密甚至是非对称加密的算法(非对称加密如RSA算法的私钥的挑选其实也有可能使用到随机数)。在python代码中,可以通过调用random库或者numpy.random库进行随机数的生成,仅需要通过如下的代码即可实现:

import randomrandom_number = random.random() # 产生[0,1)之间的均匀随机数import numpy as nprandom_array = random.randn(10) # 产生10个随机数并存储到np格式的一维数组中

这些库所产生的随机数,往往被认为是不安全的随机数,其主要特点是通过随机数生成算法,结合硬件的一些独有编号来产生一系列数串。但是随机数生成算法一般都是已知的,因此还是有一定的潜在风险。有一个python库函数叫secrets可以产生”安全随机数”,其特点在于不仅利用了一些硬件系统独有信息,如ip和MAC等,主要还利用了系统熵源来生成随机数,增强了所产生随机数的不可预测性。关于secrets的使用方法, 可以参考其官方文档。但是,即使是这里所谓的安全随机数,也并不是真随机数,真随机数的产生不依赖于算法。

量子计算与随机数

前面写过一篇博客介绍两比特量子系统的模拟,读者可以从中了解到量子计算的一些基本原理与模拟实现。而另一篇关于量子线路模拟的博客,则介绍了关于开源量子计算框架ProjectQ的一些基本使用方法,在这篇文章中我们也会使用到。通过量子硬件,我们可以直接读取一系列的随机串,由于这些随机串是由硬件直接给出来的结果,不是通过算法来生成的,因此是完成不可预测的,被称为”真随机数”。

基于pytest的python单元测试框架

在使用python编程实现算法时,需要对算法函数或者类进行功能验证,这就需要写测试用例。python第三方库pytest提供了非常好的自动化测试的功能,配合html插件和覆盖率测试插件,还可以进行更多的测试以及更好的展示测试的结果。

量子计算产生随机数

量子计算是基于量子叠加与量子纠缠两种特性进行计算的方案,其结合量子算法的复杂性优势,在量子处理器上可以实现经典计算机无法在有效时间内完成的任务,一般称之为量子优越性。量子叠加是对量子比特重要特性的一个总结,如下图所示(图片来自于参考链接1),区分于经典比特,量子比特不仅可以表示0和1,还可以表示处于0和1之间的状态,比如0.5,0.2243等等。这些状态我们不能直接读取,在硬件上我们只能够读取到0或者1两种状态,这跟经典比特是一样的。区别在于,即使我们不改变量子比特的状态,不同的测试却会给出不同的结果,而0.5等中间状态,则表示的是出现0或者1状态分别的概率。

html随机数生成器(html随机选数代码介绍)

这里我们直接使用开源量子计算框架ProjectQ来实现这个门操作,就省去了自己去模拟实习的繁琐操作:

# random_number.pyfrom projectq import MainEnginefrom projectq.ops import H, Measuredef random_number_generator():    eng = MainEngine()    qubit = eng.allocate_qubit()    H | qubit    eng.flush()    Measure | qubit    random_number = int(qubit)    eng.flush(deallocate_qubits=True)    return random_numberif __name__ == '__main__':    random_number = random_number_generator()    print ('Random number generated by quantum simulator is: {}'.format(random_number))

这里顺带的介绍下ProjectQ的一些操作实现的方法,在ProjectQ中将众多的量子比特作为寄存器来进行调用,这些寄存器都在给定的engine下赋予了各种操作,如量子门操作、打印线路、编译优化等。编程框架与实际的量子比特并不在架构上的同一个层次,每次传送指令都是通过eng.flush()打包进行编译优化之后,再传送到后端去逐一执行。因此如果要测量量子比特(在ProjectQ模拟器中必须只能全部执行测量操作,不能只测量其中的某一个部分),或者是读取某一个量子态的概率时,都需要先执行eng.flush()才行。接下来简单看下上述代码的执行效果:

[dechin@dechin-manjaro pytest]$ python3 random_number.py Random number generated by quantum simulator is: 1[dechin@dechin-manjaro pytest]$ python3 random_number.py Random number generated by quantum simulator is: 1[dechin@dechin-manjaro pytest]$ python3 random_number.py Random number generated by quantum simulator is: 0[dechin@dechin-manjaro pytest]$ python3 random_number.py Random number generated by quantum simulator is: 0[dechin@dechin-manjaro pytest]$ python3 random_number.py Random number generated by quantum simulator is: 1

在这个案例中,每一次都会产生一个新的随机数0或者1,并且在量子比特使用结束之后,通过eng.flush(deallocate_qubits=True)可以初始化该寄存器,所有的振幅和测量结果都会被丢弃。

注意!!!

需要注意的是,由于这里我们是使用了模拟器来模拟量子计算机的行为,因此得到的随机数结果还是伪随机数。只有当这一串代码执行在量子处理器上时,我们才能得到真随机数。

pytest测试

安装pytest库

首先我们可以通过pip来更新安装pytest:

[dechin@dechin-manjaro pytest]$ python3 -m pip install -U pytestCollecting pytest  Downloading pytest-6.2.2-py3-none-any.whl (280 kB)     |████████████████████████████████| 280 kB 464 kB/s Requirement already satisfied, skipping upgrade: iniconfig in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest) (1.1.1)Requirement already satisfied, skipping upgrade: pluggy<1.0.0a1,>=0.12 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest) (0.13.1)Requirement already satisfied, skipping upgrade: attrs>=19.2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest) (20.3.0)Requirement already satisfied, skipping upgrade: toml in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest) (0.10.1)Requirement already satisfied, skipping upgrade: packaging in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest) (20.4)Requirement already satisfied, skipping upgrade: py>=1.8.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest) (1.9.0)Requirement already satisfied, skipping upgrade: pyparsing>=2.0.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest) (2.4.7)Requirement already satisfied, skipping upgrade: six in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest) (1.15.0)Installing collected packages: pytest  Attempting uninstall: pytest    Found existing installation: pytest 6.2.1    Uninstalling pytest-6.2.1:      Successfully uninstalled pytest-6.2.1Successfully installed pytest-6.2.2

安装完成后,可以通过如下指令来查看安装的pytest版本:

[dechin@dechin-manjaro pytest]$ pytest --versionpytest 6.2.2

pytest单元测试用例撰写

根据前面一个章节中的random_number.py文件,我们可以对照的写一个简单测试用例:

# test_random_number.pyimport pytestfrom random_number import random_number_generator as rngdef test_random_number_generator():    for i in range(10):        random_number = rng()        assert random_number == 0 or random_number == 1

该测试用例的含义为:导入rng函数之后,测试10次该函数的返回值,所返回的值必须是0或者1的随机数,如果输出了这两个数字以外的返回结果,那么说明这个随机数产生器功能上存在问题。基于pytest的测试代码可以通过如下的指令来运行:

[dechin@dechin-20n2s01200 pytest]$ py.test=========================================== test session starts ============================================platform linux -- Python 3.8.5, pytest-6.2.2, py-1.9.0, pluggy-0.13.1rootdir: /home/dechin/projects/2021-python/pytestplugins: cov-2.11.1, metadata-1.11.0, html-3.1.1collected 1 item                                                                                           test_random_number.py .                                                                              [100%]============================================= warnings summary =============================================../../../anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:118  /home/dechin/anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:118: PendingDeprecationWarning: the matrix subclass is not the recommended way to represent matrices or deal with linear algebra (see https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). Please adjust your code to use regular ndarray.    return np.matrix([[1, 0], [0, 1j]])../../../anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:133  /home/dechin/anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:133: PendingDeprecationWarning: the matrix subclass is not the recommended way to represent matrices or deal with linear algebra (see https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). Please adjust your code to use regular ndarray.    return np.matrix([[1, 0], [0, cmath.exp(1j * cmath.pi / 4)]])test_random_number.py: 40 warnings  /home/dechin/anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:69: PendingDeprecationWarning: the matrix subclass is not the recommended way to represent matrices or deal with linear algebra (see https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). Please adjust your code to use regular ndarray.    return 1. / cmath.sqrt(2.) * np.matrix([[1, 1], [1, -1]])-- Docs: https://docs.pytest.org/en/stable/warnings.html====================================== 1 passed, 42 warnings in 0.50s ======================================

从返回的结果来看,出现了1 passed而没有failed,说明所有的测试用例都已经执行成功了,但是这里存在不少的告警warnings信息。

pytest初始化配置文件

在上一节的测试结果中,我们发现有非常多的测试告警。假如我们确认这些告警信息可以忽略,那么我们可以通过在指令中配置忽略告警信息,或者直接使用这里介绍的pytest.ini来忽略相应的告警信息:

# pytest.ini[pytest]filterwarnings =         ignore::PendingDeprecationWarning

在当前目录下的ini配置文件中,我们添加了PendingDeprecationWarning作为忽略项,然后我们再回头看一下上述用例的测试结果:

[dechin@dechin-manjaro pytest]$ py.test=========================================== test session starts ============================================platform linux -- Python 3.8.5, pytest-6.2.2, py-1.9.0, pluggy-0.13.1rootdir: /home/dechin/projects/2021-python/pytest, configfile: pytest.iniplugins: cov-2.11.1, metadata-1.11.0, html-3.1.1collected 1 item                                                                                           test_random_number.py .                                                                              [100%]============================================ 1 passed in 0.50s =============================================

这里返回的结果中就没有告警信息了。

pytest生成html格式报告

为了更好的展现测试的结果,这里我们需要先安装一个组件pytest-html:

[dechin@dechin-manjaro pytest]$ python3 -m pip install pytest-htmlCollecting pytest-html  Downloading pytest_html-3.1.1-py3-none-any.whl (14 kB)Collecting pytest-metadata  Downloading pytest_metadata-1.11.0-py2.py3-none-any.whl (10 kB)Requirement already satisfied: pytest!=6.0.0,>=5.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest-html) (6.2.1)Requirement already satisfied: attrs>=19.2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (20.3.0)Requirement already satisfied: py>=1.8.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (1.9.0)Requirement already satisfied: toml in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (0.10.1)Requirement already satisfied: packaging in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (20.4)Requirement already satisfied: pluggy<1.0.0a1,>=0.12 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (0.13.1)Requirement already satisfied: iniconfig in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (1.1.1)Requirement already satisfied: six in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest!=6.0.0,>=5.0->pytest-html) (1.15.0)Requirement already satisfied: pyparsing>=2.0.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest!=6.0.0,>=5.0->pytest-html) (2.4.7)Installing collected packages: pytest-metadata, pytest-htmlSuccessfully installed pytest-html-3.1.1 pytest-metadata-1.11.0

安装成功后,执行如下指令,可以在当前目录下生成一个指定文件名的html文件,如下图所示,就比较全面且美观的展示了测试中的信息:

[dechin@dechin-manjaro pytest]$ py.test --html=pytest_report.html=========================================== test session starts ============================================platform linux -- Python 3.8.5, pytest-6.2.2, py-1.9.0, pluggy-0.13.1rootdir: /home/dechin/projects/2021-python/pytest, configfile: pytest.iniplugins: cov-2.11.1, metadata-1.11.0, html-3.1.1collected 1 item                                                                                           test_random_number.py .                                                                              [100%]--------- generated html file: file:///home/dechin/projects/2021-python/pytest/pytest_report.html ----------============================================ 1 passed in 0.51s =============================================

html随机数生成器(html随机选数代码介绍)

这里我们看到random_number.py文件的测试覆盖率为86%,我们可以点开链接查看剩下未覆盖的测试是什么内容:

html随机数生成器(html随机选数代码介绍)

我们可以点击进入相应文件的issue清单中去查看:

html随机数生成器(html随机选数代码介绍)

经过一番修改之后,我们得到的flake8配置文件和源代码文件如下:

# .flake8[flake8]exclude = ./test*ignore = W391
# random_number.pyfrom projectq import MainEnginefrom projectq.ops import H, Measuredef random_number_generator():    eng = MainEngine()    qubit = eng.allocate_qubit()    H | qubit    eng.flush()    Measure | qubit    random_number = int(qubit)    eng.flush(deallocate_qubits=True)    return random_numberif __name__ == '__main__':    random_number = random_number_generator()    print('Random number generated by quantum simulator is:            {}'.format(random_number))

最终我们的目的是使得flake8执行的issue清零:

[dechin@dechin-manjaro pytest]$ flake8 --format=html --htmldir=flake-report[dechin@dechin-manjaro pytest]$

总结概要

本文通过引入一个随机数生成器的案例,介绍了在量子计算中产生真随机数的方案,同时给出了量子计算模拟实现。借此机会也同时介绍了python的单元测试库pytest的一些常规和扩展使用方法,以及python的编码规范测试库flake8的基本使用方法,希望能够对大家有所启发以及帮助。

(0)
小多多的头像小多多创始人

相关推荐

发表回复

登录后才能评论