コード例 #1
0
    def __call__(self, n, t, y_t):
        if self.min_stop_check(t):
            return False
        y = y_t
        not_y = t - y

        # The amount for winner under alternative
        p1N = int(n * self.p)
        # The amount for winner under null
        p0N = int(n * self.p_0)

        # The amount for winner is greater than alternative
        if y >= p1N:
            return True
        # The amount for loser is greater than votes in null hypothesis for loser
        elif not_y >= n - p0N:
            return False

        # log(top)
        log_prob_p1 = hypergeom_pmf(y, n, p1N, t, log=True)
        # log(bot)
        log_prob_p0 = hypergeom_pmf(y, n, p0N, t, log=True)

        inf_p0 = isinf(log_prob_p0)
        inf_p1 = isinf(log_prob_p1)
        # Both return null, means the chance is in between
        if inf_p0 and inf_p1:
            #
            if y > p0N:
                return True
            return False
        # Chance for null is zero
        elif inf_p0:
            return True
        # Chance for alternative is zero
        elif inf_p1:
            return False

        # total log(top) - log(bottom)
        ratio = log_prob_p1 - log_prob_p0

        # print(n, t, y_t, log_prob_p0, log_prob_p1, ratio, self.critical_value)
        return ratio >= self.critical_value
コード例 #2
0
def single_node_update(rejection_fn, n, t, y_t, p_t, step, p, replacement,
                       *args, **kwargs):
    rejection_dict = defaultdict(float)
    q = OrderedDict()
    # Take the floor for winner's share
    w = floor(n * p)

    t_next = t + step
    n_remain = n - t
    w_remain = w - y_t

    # All possible generated sa for next batch
    for i in range(step + 1):
        y_t_next = y_t + i

        if not replacement:
            # If no replacement sample from hypergeometric distribution
            p_next = hypergeom_pmf(i, n_remain, w_remain, step)
        else:
            # Else use binomial compute probability
            p_next = binom_pmf(i, step, p)

        # Is this state rejected?
        reject = rejection_fn(n, t_next, y_t_next, *args, **kwargs)

        # Compose the node
        node = (t_next, y_t_next, p_next * p_t)
        if isnull(node[2]):
            node = (t_next, y_t_next, 0)

        # Don't add to queue or dict if there is no chance for it
        if node[2] == 0:
            continue

        # if null is rejected, put it in the risk dict
        if reject:
            rejection_dict[node[:2]] += node[2]
        else:
            q.append(node[:2], node[2])
    return rejection_dict, q
コード例 #3
0
def audit_process_simulation_serial(rejection_fn,
                                    election: Election,
                                    progression=False,
                                    *args,
                                    **kwargs):

    m = election.m
    n = election.n
    step = election.step
    replacement = election.replacement
    p = election.p

    if m == -1:
        m = n + 1

    w = floor(n * p)

    progression_bar = null_bar

    if progression:
        progression_bar = SimpleProgressionBar(m)

    rejection_dict = defaultdict(float)

    # first element: t,
    # second element: y_t, (observe every step time)
    # third element: probability going to this state
    source = (0, 0, 1)

    q = OrderedDict()
    q.append(source[:2], source[2])

    # While q is not empty
    while len(q):
        # get next node to explore
        key, value = q.peek()

        # Update progression
        progression_bar(key[0])

        # If sampled to the max number already, break (max number exclusive)
        if isinstance(m, int) and key[0] >= m:
            break

        if replacement and key[0] > n:
            break

        # Remove the value
        q.popitem(last=False)

        t, y_t, p_t = *key, value
        console_logger.debug("         poped: {}".format((t, y_t, p_t)))

        n_remain = n - t
        w_remain = w - y_t

        t_next = t + step
        reject = False
        # All possible generated sa for next batch
        for i in range(0, step + 1):
            y_t_next = y_t + i
            if not replacement:
                n_remain_next = n - t_next
                w_remain_next = w - y_t_next
                l_remain_next = n_remain_next - w_remain_next
                if n_remain_next < 0 or w_remain_next < 0 or l_remain_next < 0:
                    continue

            if y_t_next < 0:
                break

            if not replacement:
                # If no replacement sample from hypergeometric distribution
                p_next = hypergeom_pmf(i, n_remain, w_remain, step)
            else:
                # Else use binomial compute probability
                p_next = binom_pmf(i, step, p)

            # Update reject if it's False, don't need to compute reject if it's True already (as is tested sequentially)
            if not reject:
                # Remainder: Don't use is to compare True False
                reject = rejection_fn(n, t_next, y_t_next, *args, **kwargs)

            # Compose the node
            node = (t_next, y_t_next, p_next * p_t)
            if isnull(p_next * p_t):
                node = (t_next, y_t_next, 0)

            # if null is rejected, put it in the risk dict
            if reject:
                rejection_dict[node[:2]] += node[2]
            else:
                q.append(node[:2], node[2])

    # The information in this is enough to determine the result
    return rejection_dict
コード例 #4
0
from utility.program_utility import CachedMethod, string_to_num