def LongestRunOfOnes(e): ce = list(e) n = len(ce) run_test = True outstr = "Test for the Longest Run of Ones in a Block:\n" outstr += "n = %d\n" % n if n < 128: run_test = False else: if n >= 750000: # set constants & instantiate the v_i table M, K, N, iv = 10000, 6, 75, 10 vt = {10: 0, 11: 0, 12: 0, 13: 0, 14: 0, 15: 0, 16: 0} elif n >= 6272: M, K, N, iv = 128, 5, 49, 4 vt = {4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0} else: # 128 <= n < 6272 M, K, N, iv = 8, 3, 16, 1 vt = {1: 0, 2: 0, 3: 0, 4: 0} ce = ce[:n - (n % M)] # discard bits that don't fit n = len(ce) block_list = split_list(ce, M) # list of M-bit blocks runs = [] for block in block_list: # Tabulate freq.s of longest runs lr = longest_run(block) runs.append((block, lr)) if lr in vt.keys(): vt[lr] += 1 elif lr < min(vt.keys()): vt[min(vt.keys())] += 1 elif lr > max(vt.keys()): vt[max(vt.keys())] += 1 pre_Chi2_l = [] for i in xrange(K + 1): idx = iv + i num = pow((vt[idx] - N * pi_i[(K, M)][iv + i]), 2) den = float(N * pi_i[(K, M)][idx]) pre_Chi2_l.append(num / den) Chi2_obs = sum(pre_Chi2_l) p = 1 - igamc(K / 2.0, Chi2_obs / 2.0) if n <= 256: outstr += "Blocks (& longest runs):" for i in xrange(len(runs)): (b, l) = runs[i] outstr += " %s (%d)\t" % ("".join([str(c) for c in b]), l) if i % 2: outstr += '\n' outstr += "V_i values:\n" for i in sorted(vt.keys()): outstr += " V_%d = %d\n" % (i - iv, vt[i]) outstr += "Chi2_obs = %.6f\n" % Chi2_obs outstr += "P-value = %.6f\n" % p if not run_test: outstr += 'Test not run: pre-test condition not met: ' outstr += 'n >= 128\n' open("./test_results/LongestRunOfOnes.txt", "w").write(outstr) if run_test: if p < 0.01: return False return True
def Serial(e): m = 2 # not fixed, but should be small and >=2 ce = list(e) n = len(ce) ce += list(e)[:m-1] v = {} bs = map(bin_strings, [m-2, m-1, m]) for l in bs: for idx in l: v[idx] = 0 for curb in [m, m-1, m-2]: if curb: for i in xrange(n): curpat = tuple(ce[i:i+curb]) v[curpat] += 1 def rvs(i): return pow(v[i], 2) def psi2(b): return pow(2.0, b) / n * sum(map(rvs, bin_strings(b))) - n psi2_m = psi2(m) psi2_m_1 = psi2(m-1) if m == 2: psi2_m_2 = 0.0 else: psi2_m_2 = psi2(m-2) d_psi2_m = psi2_m - psi2_m_1 d2_psi2_m = psi2_m - 2 * psi2_m_1 + psi2_m_2 p_1 = 1 - igamc(pow(2, m-2), d_psi2_m / 2.0) # BUG Wrong for 10b ex p_2 = 1 - igamc(pow(2, m-3), d2_psi2_m / 2.0) outstr = 'The Serial Test:\n' outstr += 'n = %d\n' % n outstr += 'm = %d\n' % m outstr += 'psi2_%d = %.6f; ' % (m, psi2_m) outstr += 'psi2_%d = %.6f; ' % (m-1, psi2_m_1) outstr += 'psi2_%d = %.6f\n' % (m-2, psi2_m_2) outstr += 'd_psi2_%d = %.6f; ' % (m, d_psi2_m) outstr += 'd2_psi2_%d = %.6f\n' % (m, d2_psi2_m) outstr += 'P-value_1 = %.6f; ' % p_1 outstr += 'P-value_2 = %.6f\n' % p_2 open("./test_results/Serial.txt", "w").write(outstr) if p_1 < 0.01 or p_2 < 0.01: return False else: return True
def NonOverlappingTemplateMatching(e, m=6): n = len(e) # m = 6 # min 2, max 16, rec 9 or 10 N = 8 # fixed value as per spec M = int(n / float(N)) ce = list(e) ce = ce[:len(ce) - (len(ce) % M)] blocks = split_list(ce, M) templates = sorted(get_templates(m)) outstr = "Non-Overlapping Template Matching Test:\n" outstr += "n = %d\n" % n outstr += "N = %d\n" % N outstr += "M = %d\n" % M outstr += "%d templates to iterate over:\n" % len(templates) p_l = [] first = True for B in templates: W = map(int, xrange(N)) for j in xrange(N): block = blocks[j] hits = 0 idx = 0 while idx < M - m: if block[idx:idx + m] == B: hits += 1 increment = m else: increment = 1 idx += increment if block[idx:idx + m] == []: raise LengthError() W[j] = hits mu = float(M - m + 1) / pow(2, m) sigma2 = M * (1.0 / pow(2, m) - float(2 * m - 1) / pow(2, (2 * m))) pre_Chi2_l = map(lambda j: pow((W[j] - mu), 2) / sigma2, xrange(N)) Chi2_obs = sum(pre_Chi2_l) p = igamc(N / 2.0, Chi2_obs / 2.0) if not first: outstr += '\n----------------' else: first = False outstr += "\nB = %s\n" % ''.join(map(str, B)) outstr += "mu = %.6f\n" % mu outstr += "sigma2 = %.6f\n" % sigma2 outstr += "Chi2_obs = %.6f\n" % Chi2_obs outstr += "W = %s\n" % W outstr += "P-value = %.6f\n" % p p_l.append(p) open("./test_results/NonOverlappingTemplateMatching.txt", "w").write(outstr) for j in xrange(len(p_l)): p = p_l[j] if p < 0.01: return False return True
def ApproximateEntropy(e): m = 3 # not fixed, but should be small and >=2 ce = list(e) n = len(ce) ce += list(e)[:m] C = {} bs = bin_strings(m) def rc(i): if C[i]: return C[i] * log(C[i]) else: return 0 for idx in bs: C[idx] = 0 for i in xrange(n): curpat = tuple(ce[i:i + m]) C[curpat] += 1.0 / n phi_m = sum(map(rc, bs)) C = {} bs = bin_strings(m + 1) for idx in bs: C[idx] = 0 for i in xrange(n): curpat = tuple(ce[i:i + m + 1]) C[curpat] += 1.0 / n phi_m_1 = sum(map(rc, bs)) ApEn = phi_m - phi_m_1 chi2_obs = 2 * n * (log(2) - ApEn) p = 1 - igamc(pow(2, m - 1), chi2_obs / 2.0) outstr = 'Approximate Entropy Test:\n' outstr += 'n = %d\n' % n outstr += 'm = %d\n' % m outstr += 'ApEn = %.6f\n' % ApEn outstr += 'chi2_obs = %.6f\n' % chi2_obs outstr += 'P-value = %.6f\n' % p open("./test_results/ApproximateEntropy.txt", "w").write(outstr) if p < 0.01: return False else: return True
def RandomExcursions(e): ce = list(e) n = len(ce) X = map(lambda i: 2 * i - 1, ce) S = [0] s = 0 for bit in X: s += bit S.append(s) S.append(0) J = -1 idx = 0 cycles = [] for step in xrange(1, len(S)): if S[step] == 0: J += 1 cycles.append(S[idx:step + 1]) idx = step run_test = True outstr = 'Random Excursions Test:\n' # potential BUG outstr += 'n = %d\n' % n outstr += 'J = %d\n' % J if J < 500: run_test = False else: states = {} for state in range(-4, 0) + range(1, 5): states[state] = map(lambda x: 0, cycles) # initialise states for idx in xrange(len(cycles)): for jdx in cycles[idx]: if jdx and -5 < jdx < 5: states[jdx][idx] += 1 v_k = {} for state in range(-4, 0) + range(1, 5): v_k[state] = [0 * i for i in range(6)] # initialise v_k for idx in xrange(len(cycles)): for state in range(-4, 0) + range(1, 5): v_k[state][min(states[state][idx], 5)] += 1 out = {} for state in range(-4, 0) + range(1, 5): out[state] = {'chi2': 0, 'p': 0} for state in out: # chi2_obs = 0 for k in range(6): # BUG wrong chi2 for state in -3..-1 term = pow(v_k[state][k] - J * pi_k[abs(state)][k], 2) term /= J * pi_k[abs(state)][k] out[state]['chi2'] += term out[state]['p'] = 1 - igamc(5 / 2.0, out[state]['chi2'] / 2.0) outstr += 'State=x\tchi2\tP-value\tConclusion' c = ['Random', 'Non-random'] for state in sorted(out.keys()): chi2 = out[state]['chi2'] p = out[state]['p'] outstr += '\n%d\t%.6f\t%.6f\t%s\n' % (state, chi2, p, c[p < 0.01]) if not run_test: outstr += 'Test not run: pre-test condition not met: ' outstr += 'J >= 500\n' open("./test_results/RandomExcursions.txt", "w").write(outstr) if run_test: for x in states: if out[x]['p'] < 0.01: return False return True
def OverlappingTemplateMatching(e, m=6): n = len(e) # m = 6 # min 2, max 16, rec 9 or 10 N = 968 # fixed value as per spec M = 1032 # fixed, but could be: int(n/float(N)) outstr = "Overlapping Template Matching Test:\n" outstr += "n = %d\n" % n outstr += "N = %d\n" % N outstr += "M = %d\n" % M run_test = True if n < 1000000: run_test = False else: ce = list(e) ce = ce[:len(ce) - (len(ce) % M)] blocks = split_list(ce, M) templates = sorted(get_templates(m))[::-1] pi = [0.364091, 0.185659, 0.139381, 0.100571, 0.070432, 0.139865] p_lambda = (M - m + 1.0) / pow(2, m) p_eta = p_lambda / 2.0 p_l = [] first = True prevlen = 0 for tidx in xrange(len(templates)): B = templates[tidx] v = [0, 0, 0, 0, 0, 0] # given B for j in xrange(N): block = blocks[j] hits = 0 idx = 0 while idx < M - m: if block[idx:idx + m] == B: hits += 1 idx += 1 if block[idx:idx + m] == []: raise LengthError() if hits <= 5: v[hits] += 1 else: v[5] += 1 pre_Chi2_l = [] for i in xrange(6): pre_Chi2_l.append(pow((v[i] - N * pi[i]), 2) / (N * pi[i])) Chi2_obs = sum(pre_Chi2_l) p = igamc(5 / 2.0, Chi2_obs / 2.0) p_l.append(p) if not first: outstr += '\n----------------' if first: outstr += "lambda = %d\n" % p_lambda outstr += "%d templates to iterate over:\n" % len(templates) first = False outstr += "\nB = %s\n" % ''.join([str(i) for i in B]) outstr += "v = %s\n" % v outstr += "Chi2_obs = %.6f\n" % Chi2_obs outstr += "P-value = %.6f\n" % p if not run_test: outstr += 'Test not run: pre-test condition not met: ' outstr += 'n >= 1000000\n' open("./test_results/OverlappingTemplateMatching.txt", "w").write(outstr) if run_test: for p in p_l: if p < 0.01: return False return True