NIST Suite Test для нелинейной динамической системы
В моем следующем коде я запускаю хаотическое уравнение Лоренца, из которого я получу случайные числа в терминах xs, ys и zs
import numpy as np
def lorenz(x, y, z, a=10,b=8/3,c=28 ):
x_dot = a*(y -x)
y_dot = - y +c*x - x*z
z_dot = -b*z + x*y
return x_dot, y_dot, z_dot
dt = 0.01
num_steps = 10000
# Need one more for the initial values
xs = np.empty(num_steps + 1)
ys = np.empty(num_steps + 1)
zs = np.empty(num_steps + 1)
# Set initial values
xs[0], ys[0], zs[0]= (1,1,1)
# Step through "time", calculating the partial derivatives at the current point
# and using them to estimate the next point
for i in range(num_steps):
x_dot, y_dot, z_dot= lorenz(xs[i], ys[i], zs[i])
xs[i + 1] = xs[i] + (x_dot * dt)
ys[i + 1] = ys[i] + (y_dot * dt)
zs[i + 1] = zs[i] + (z_dot * dt)
На самом деле я пытаюсь проверить значение xs, ys и zs для теста генерации случайных чисел через NIST 800, используя приведенный ниже код.
from __future__ import print_function
import math
from fractions import Fraction
from scipy.special import gamma, gammainc, gammaincc
# from gamma_functions import *
import numpy
import cmath
import random
#ones_table = [bin(i)[2:].count('1') for i in range(256)]
def count_ones_zeroes(bits):
ones = 0
zeroes = 0
for bit in bits:
if (bit == 1):
ones += 1
else:
zeroes += 1
return (zeroes,ones)
def runs_test(bits):
n = len(bits)
zeroes,ones = count_ones_zeroes(bits)
prop = float(ones)/float(n)
print(" prop ",prop)
tau = 2.0/math.sqrt(n)
print(" tau ",tau)
if abs(prop-0.5) > tau:
return (False,0.0,None)
vobs = 1.0
for i in range(n-1):
if bits[i] != bits[i+1]:
vobs += 1.0
print(" vobs ",vobs)
p = math.erfc(abs(vobs - (2.0*n*prop*(1.0-prop)))/(2.0*math.sqrt(2.0*n)*prop*(1-prop) ))
success = (p >= 0.01)
return (success,p,None)
print(runs_test(xs))
#%%
from __future__ import print_function
import math
def count_ones_zeroes(bits):
ones = 0
zeroes = 0
for bit in bits:
if (bit == 1):
ones += 1
else:
zeroes += 1
return (zeroes,ones)
def monobit_test(bits):
n = len(bits)
zeroes,ones = count_ones_zeroes(bits)
s = abs(ones-zeroes)
print(" Ones count = %d" % ones)
print(" Zeroes count = %d" % zeroes)
p = math.erfc(float(s)/(math.sqrt(float(n)) * math.sqrt(2.0)))
success = (p >= 0.01)
return (success,p,None)
print(runs_test(xs))
вывод, который я получаю, является ложным, т.е.
вывод: prop 0,00019998000199980003 tau 0,01999900007499375 (False,0.0,None)
Что мне теперь делать?
1 ответ
Система Лоренца хаотична, а не случайна. Вы хорошо реализовали другой решатель уравнений, но кажется, что
count_ones_zeroes
не делает того, что подразумевает его название, по крайней мере, не на предоставленных вами данных. на xs возвращает нули, единицы = 9999, 2, а это не то, что вы хотите. Код проверяет значение в пределах xs, то есть значение x (например, 8.2) против 1, но это число с плавающей запятой между -20 и 20, поэтому обычно оно не равно 1 и будет считаться 0.
В python int/int приводит к float, поэтому нет необходимости приводить его к float, в отличие, например, от C или C++, поэтому вместо
prop = float(ones)/float(n)
, ты можешь написать
prop = ones/n
Аналогичные утверждения справедливы для +, - и *