1*0f4c859eSApple OSS Distributions#!/usr/bin/env python3 2*0f4c859eSApple OSS Distributions 3*0f4c859eSApple OSS Distributionsfrom fractions import Fraction 4*0f4c859eSApple OSS Distributionsfrom math import ceil 5*0f4c859eSApple OSS Distributionsfrom math import comb 6*0f4c859eSApple OSS Distributions 7*0f4c859eSApple OSS Distributions 8*0f4c859eSApple OSS Distributions# The inverse of 2, i.e. 2^-1. To be used as a base in exponentiations 9*0f4c859eSApple OSS Distributions# representing probabilities. 10*0f4c859eSApple OSS DistributionsINV2 = Fraction(1, 2) 11*0f4c859eSApple OSS Distributions 12*0f4c859eSApple OSS Distributions 13*0f4c859eSApple OSS Distributions# The probability of a false positive health test failure expressed as 14*0f4c859eSApple OSS Distributions# the negative logarithm of the *actual* probability. In simpler 15*0f4c859eSApple OSS Distributions# terms, the actual probability is: 16*0f4c859eSApple OSS Distributions# 17*0f4c859eSApple OSS Distributions# INV2 ** A 18*0f4c859eSApple OSS Distributions# 19*0f4c859eSApple OSS Distributions# It is simpler to keep this representation when computing the bound 20*0f4c859eSApple OSS Distributions# of the Repetition Count Test (below). 21*0f4c859eSApple OSS DistributionsA = 40 22*0f4c859eSApple OSS Distributions 23*0f4c859eSApple OSS Distributions 24*0f4c859eSApple OSS Distributions# The estimated min-entropy per sample in bits. Min-entropy is the 25*0f4c859eSApple OSS Distributions# negative logarithm of the probability of the *most likely* outcome. 26*0f4c859eSApple OSS Distributions# 27*0f4c859eSApple OSS Distributions# We consider this estimate to be conservative. 28*0f4c859eSApple OSS DistributionsH = 1 29*0f4c859eSApple OSS Distributions 30*0f4c859eSApple OSS Distributions 31*0f4c859eSApple OSS Distributions# The probability of the most likely outcome occurring in a given 32*0f4c859eSApple OSS Distributions# sample. This derives from the definition of min-entropy (see above). 33*0f4c859eSApple OSS DistributionsP = INV2 ** H 34*0f4c859eSApple OSS Distributions 35*0f4c859eSApple OSS Distributions 36*0f4c859eSApple OSS Distributions# 4.4.1 Repetition Count Test 37*0f4c859eSApple OSS Distributions# 38*0f4c859eSApple OSS Distributions# The Repetition Count Test (RCT) detects catastrophic failures in the 39*0f4c859eSApple OSS Distributions# noise source when it becomes "stuck" generating a single value over 40*0f4c859eSApple OSS Distributions# many consecutive samples. 41*0f4c859eSApple OSS Distributions# 42*0f4c859eSApple OSS Distributions# The probability of generating C consecutive identical samples is: 43*0f4c859eSApple OSS Distributions# 44*0f4c859eSApple OSS Distributions# P^(C-1) 45*0f4c859eSApple OSS Distributions# 46*0f4c859eSApple OSS Distributions# Or equivalently: 47*0f4c859eSApple OSS Distributions# 48*0f4c859eSApple OSS Distributions# 2^(-H * (C-1)) 49*0f4c859eSApple OSS Distributions# 50*0f4c859eSApple OSS Distributions# To keep this under our rate of acceptable false positives, we need 51*0f4c859eSApple OSS Distributions# to satisfy this inequality: 52*0f4c859eSApple OSS Distributions# 53*0f4c859eSApple OSS Distributions# 2^-A >= 2^(-H * (C-1)) 54*0f4c859eSApple OSS Distributions# 55*0f4c859eSApple OSS Distributions# Taking the logarithm of both sides, we have: 56*0f4c859eSApple OSS Distributions# 57*0f4c859eSApple OSS Distributions# -A >= -H * (C-1) 58*0f4c859eSApple OSS Distributions# 59*0f4c859eSApple OSS Distributions# Solving for C, we have: 60*0f4c859eSApple OSS Distributions# 61*0f4c859eSApple OSS Distributions# (A / H) + 1 >= C 62*0f4c859eSApple OSS Distributionsdef repetition_count_bound(): 63*0f4c859eSApple OSS Distributions return 1 + ceil(Fraction(A, H)) 64*0f4c859eSApple OSS Distributions 65*0f4c859eSApple OSS Distributions 66*0f4c859eSApple OSS Distributions# 4.4.2 Adaptive Proportion Test 67*0f4c859eSApple OSS Distributions# 68*0f4c859eSApple OSS Distributions# The Adaptive Proportion Test (APT) tries to detect more subtle noise 69*0f4c859eSApple OSS Distributions# source failures causing certain values to occur with unexpected 70*0f4c859eSApple OSS Distributions# frequency. It does this by taking a sample from the noise source and 71*0f4c859eSApple OSS Distributions# counting how many times the same sample occurs within a fixed-size 72*0f4c859eSApple OSS Distributions# window. 73*0f4c859eSApple OSS Distributions 74*0f4c859eSApple OSS Distributions 75*0f4c859eSApple OSS Distributions# The size of the window for non-binary alphabets for the APT. 76*0f4c859eSApple OSS DistributionsW = 512 77*0f4c859eSApple OSS Distributions 78*0f4c859eSApple OSS Distributions 79*0f4c859eSApple OSS Distributions# The probability mass function measuring the probability of exactly k 80*0f4c859eSApple OSS Distributions# occurrences of a given value within the observation window of size 81*0f4c859eSApple OSS Distributions# W. We use the probability of the most likely event (as above). 82*0f4c859eSApple OSS Distributions# 83*0f4c859eSApple OSS Distributions# There are three terms: 84*0f4c859eSApple OSS Distributions# 85*0f4c859eSApple OSS Distributions# 1. The binomial coefficient of k, i.e. W-choose-k. Simply, how many 86*0f4c859eSApple OSS Distributions# ways are there to get exactly k outcomes given W chances. 87*0f4c859eSApple OSS Distributions# 88*0f4c859eSApple OSS Distributions# 2. The probability of each of those k events occurring. 89*0f4c859eSApple OSS Distributions# 90*0f4c859eSApple OSS Distributions# 3. The probability that the other W-k events have some other 91*0f4c859eSApple OSS Distributions# outcome. 92*0f4c859eSApple OSS Distributionsdef pmf(k): 93*0f4c859eSApple OSS Distributions return comb(W, k) * P**k * (1 - P)**(W-k) 94*0f4c859eSApple OSS Distributions 95*0f4c859eSApple OSS Distributions 96*0f4c859eSApple OSS Distributions# The sum of probabilties of all possible counts of occurrences is 1. 97*0f4c859eSApple OSS Distributionsassert sum(map(pmf, range(W+1))) == 1 98*0f4c859eSApple OSS Distributions 99*0f4c859eSApple OSS Distributions 100*0f4c859eSApple OSS Distributions# We want to find the minimal count of occurrences such that the 101*0f4c859eSApple OSS Distributions# cumulative probability of seeing *at least* that count of 102*0f4c859eSApple OSS Distributions# occurrences (but possibly more) is no more than our false 103*0f4c859eSApple OSS Distributions# positive threshold. 104*0f4c859eSApple OSS Distributionsdef adaptive_proportion_bound(): 105*0f4c859eSApple OSS Distributions # The list of probabilities for each of the possible counts of 106*0f4c859eSApple OSS Distributions # occurrences. 107*0f4c859eSApple OSS Distributions probs = [pmf(x) for x in range(W+1)] 108*0f4c859eSApple OSS Distributions 109*0f4c859eSApple OSS Distributions # The list of cumulative distributions for each of the possible 110*0f4c859eSApple OSS Distributions # counts of occurrences. 111*0f4c859eSApple OSS Distributions # 112*0f4c859eSApple OSS Distributions # Whereas probs is a list of probabilities of *exactly* k 113*0f4c859eSApple OSS Distributions # occurrences, this is a list of probabilities of *k or more* 114*0f4c859eSApple OSS Distributions # occurrences. 115*0f4c859eSApple OSS Distributions # 116*0f4c859eSApple OSS Distributions # These are just sums of probabilities across a range of counts. 117*0f4c859eSApple OSS Distributions dists = [sum(probs[x:]) for x in range(W+1)] 118*0f4c859eSApple OSS Distributions 119*0f4c859eSApple OSS Distributions # Because we have constructed dists as an ordered list of 120*0f4c859eSApple OSS Distributions # cumulative probabilities, we can simply return the index of the 121*0f4c859eSApple OSS Distributions # first value that is below our threshold. 122*0f4c859eSApple OSS Distributions for i, d in enumerate(dists): 123*0f4c859eSApple OSS Distributions if d <= INV2**A: 124*0f4c859eSApple OSS Distributions return i 125*0f4c859eSApple OSS Distributions 126*0f4c859eSApple OSS Distributions 127*0f4c859eSApple OSS Distributionsdef main(): 128*0f4c859eSApple OSS Distributions print('Estimated min-entropy:', H) 129*0f4c859eSApple OSS Distributions print('False positive rate: 2^-{}'.format(A)) 130*0f4c859eSApple OSS Distributions print('Repetition Count Test bound:', repetition_count_bound()) 131*0f4c859eSApple OSS Distributions print('Adaptive Proportion Test bound:', adaptive_proportion_bound()) 132*0f4c859eSApple OSS Distributions 133*0f4c859eSApple OSS Distributions 134*0f4c859eSApple OSS Distributionsif __name__ == '__main__': 135*0f4c859eSApple OSS Distributions main() 136