随机数检测(二)- 扑克检测、重叠子序列、游程总数、游程分布
- 3.4 扑克检测方法
- 3.5 重叠子序列检测方法
- 3.6 游程总数检测
- 3.7 游程分布检测
3.4 扑克检测方法
扑克检测方法如下图。
以下实现代码供参考。
def alterOffsetBit(m, offset, listSub:list):
ret = []
listSub[offset] = 0
if offset == (m-1):
ret.append(listSub.copy())
else:
ret += (alterOffsetBit(m, offset+1, listSub))
listSub[offset] = 1
if offset == (m-1):
ret.append(listSub.copy())
else:
ret += (alterOffsetBit(m, offset+1, listSub))
return ret
def seedSequence(m):
sequencelist = [0]*m
return alterOffsetBit(m, 0, sequencelist)
#get poker param, follow GM/T 0005-2021 appendix A
def getpokerM(len):
if len < 20000:
m = [2]
else:
m = [4, 8]
return m
def poker(epsilon:bitarray, m):
seedList = seedSequence(m)
listNi = [0]*(2**m)
N = int(len(epsilon)/m)
epsilonList = epsilon.tolist()
for i in range(N):
listNi[seedList.index(epsilonList[i*m:(i+1)*m:1])] += 1
sum = 0
for i in range(2**m):
sum += listNi[i]**2
V = (2**m)*sum/N - N
pvalue = scipy.special.gammaincc((2**m - 1)/2, V/2)
qvalue = pvalue
return {'p':pvalue, 'q':qvalue}
3.5 重叠子序列检测方法
重叠子序列检测方法如下图。
以下实现代码供参考。
#get serial param, follow GM/T 0005-2021 appendix A
def getserialM(len):
if len < 20000:
m = [2]
elif len < 100000000:
m = [3, 5]
else:
m = [3, 5, 7]
return m
def alterOffsetBit(m, offset, listSub:list):
ret = []
listSub[offset] = 0
if offset == (m-1):
ret.append(listSub.copy())
else:
ret += (alterOffsetBit(m, offset+1, listSub))
listSub[offset] = 1
if offset == (m-1):
ret.append(listSub.copy())
else:
ret += (alterOffsetBit(m, offset+1, listSub))
return ret
def seedSequence(m):
sequencelist = [0]*m
# print('sequencelist:' , sequencelist)
return alterOffsetBit(m, 0, sequencelist)
def getV2(epsilonList:list, mlen):
seedList = seedSequence(mlen)
# print(seedList)
V = [0] * (2**mlen)
for i in range(len(epsilonList)-mlen+1):
# print(epsilonList[i:i+mlen:1])
seedindex = seedList.index(epsilonList[i:i+mlen:1])
V[seedindex] += 1
for i in range(len(V)):
V[i] = V[i]**2
return V
def calcPhym(epsilonlist:list, m):
if m <= 0:#phy0 and phy-1 is 0
return 0
prefixM = epsilonlist[:m-1:1]
n = len(epsilonlist)
epsilonlist += prefixM
Vm = getV2(epsilonlist, m)
return (2**m)*sum(Vm)/n - n
def serial(epsilon:bitarray, m):
# n = int(len(epsilon))
epsilonList = epsilon.tolist()
phym2 = calcPhym(epsilonList, m)
phym_12 = calcPhym(epsilonList, m-1)
phym_22 = calcPhym(epsilonList, m-2)
deltaPhyM2 = phym2 - phym_12
delta2PhyM2 = phym2 - 2*phym_12 + phym_22
pvalue1 = scipy.special.gammaincc(2**(m-2), deltaPhyM2/2)
pvalue2 = scipy.special.gammaincc(2**(m-3), delta2PhyM2/2)
qvalue1 = pvalue1
qvalue2 = pvalue2
return {'p1':pvalue1, 'q1':qvalue1, 'p2':pvalue2, 'q2':qvalue2}
3.6 游程总数检测
游程总数检测方法如下图。
以下实现代码供参考。
def runs(epsilon:bitarray):
n = int(len(epsilon))
epsilonList = epsilon.tolist()
Vn = 1
for i in range(int(len(epsilonList))-1):
#r.append([1,0][epsilonList[i] == epsilonList[i+1]])
if epsilonList[i] != epsilonList[i+1]:
Vn += 1
pi = sum(epsilonList)/n
if abs(pi - 0.5) > (2.0 / sqrt(n)):
pvalue = 0.0
print('runs Test Failed : pvalue ', pvalue)
return 1
pvalue = math.erfc(abs(Vn-2*n*pi*(1-pi))/(2*sqrt(2*n)*pi*(1-pi)))
qvalue = math.erfc((Vn-2*n*pi*(1-pi))/(2*sqrt(2*n)*pi*(1-pi)))/2
return {'p':pvalue, 'q':qvalue}
3.7 游程分布检测
游程分布检测方法如下图。
以下实现代码供参考。
def runsDistribution(epsilon:bitarray):
n = int(len(epsilon))
epsilonList = epsilon.tolist()
e = []
for i in range(1,int(len(epsilonList)+1)):
e.append((n-i+3)/(2**(2+i)))
if e[i-1] >= 5:
k = i
else:
break;
gi = [0]*n
bi = [0]*n
runFlag = epsilonList[0]
j = 1
for i in range(1, n):
if epsilonList[i] != runFlag:
if runFlag == 0x00:
gi[j - 1] += 1
else:
bi[j - 1] += 1
runFlag = epsilonList[i]
j = 1
else:
j += 1
#GM/T 0005-2021 demands add all subfix to bk and gk
bi[14] = sum(bi[14:len(bi)])
gi[14] = sum(gi[14:len(gi)])
#calc T
T = 0
for i in range(k):
T += bi[i] + gi[i]
#calc e'
epie = [T/(2**(i+1)) for i in range(1, k+1)]
epie[k-1] = T/(2**k)
#calc V
V1 = []
V2 = []
for i in range(k):
V1.append(((bi[i] - epie[i])**2)/epie[i])
#V1.append((bi[i] - e[i])**2/e[i])
for i in range(k):
V2.append(((gi[i] - epie[i])**2)/epie[i])
#V2.append((gi[i] - e[i])**2/e[i])
V = sum(V1) + sum(V2)
pvalue = scipy.special.gammaincc(k-1, V/2)
qvalue = pvalue
return {'p':pvalue, 'q':qvalue}