blob: 72ecf610049d56e92c6a392f0434e74fcecce901 [file] [log] [blame]
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Utility functions for math calculations."""
import logging
from math import sqrt
from dto.float_range import FloatRange
_ALPHA_TO_Z = {
# Generated using scipy.stats.norm.ppf(1 - alpha).
0.0001: 3.7190164854557088,
0.0005: 3.2905267314919255,
0.001: 3.0902323061678132,
0.005: 2.5758293035489004,
0.01: 2.3263478740408408,
0.05: 1.6448536269514722,
0.1: 1.2815515655446004,
}
def _GetZFromAlpha(alpha):
"""Gets a z score given alpha.
Libraries used to compute z score may not be available in Appengine. Alpha
values not in _ALPHA_TO_Z will be rounded to the nearest available.
Args:
alpha (float): The desired alpha value.
Returns:
z (float): The corresponding z value to the nearest alpha.
"""
assert alpha > 0, 'Usage: Alpha must be > 0'
if not alpha in _ALPHA_TO_Z:
precomputed_alpha = min(_ALPHA_TO_Z.keys(), key=lambda x: abs(x - alpha))
logging.warning(
'Precomputed z value for alpha %s unavailable. Falling back to nearest '
'alpha %s' % (alpha, precomputed_alpha))
return _ALPHA_TO_Z[precomputed_alpha]
return _ALPHA_TO_Z[alpha]
def WilsonScoreConfidenceInterval(pass_rate, iterations, alpha):
"""Determines the possible range a pass rate is likely to span.
https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval
Args:
pass_rate (float): The observed number of times a test was measured to have
passed divided by number of iterations.
iterations (int): The number of times the test was run.
alpha (float): The confidence level of uncertainty of the result. For
example, a confidence level of 95% would have an alpha of 5%, or 0.05.
Returns:
(FloatRange): The lower and upper bounds of possible pass rates that the
measured pass rate is likely to span given alpha.
"""
assert iterations, 'Usage: iterations must be > 0'
z = _GetZFromAlpha(alpha)
center = (pass_rate + z**2 / (2 * iterations)) / (1 + z**2 / iterations)
distance = (z / (1 + z**2 / iterations)) * sqrt(
pass_rate * (1 - pass_rate) / iterations + z**2 / (4 * iterations**2))
return FloatRange(lower=(center - distance), upper=(center + distance))