예제 #1
0
def interpret_complete_cdf(
    cdfs_p: List[Union[list, np.ndarray]],
    cdfs_v: List[Union[list, np.ndarray]],
    distribution: str = None,
) -> Union[List[Union[list, np.ndarray]], Tuple[List[Union[list, np.ndarray]],
                                                List[Union[list, np.ndarray]]],
           ot.DistributionImplementation, ]:
    """Interpret the given points on the cumulative distribution function to represent a complete CDF. The default
    policy is to assume discrete probabilities.
    If a distribution name is specified, the CDF is returned as an openturns distribution object.
    Supported openturns distributions are the following:
    - discrete: all residual probability is attributed to the highest given value
    - normal or gaussian: derived from the first two point only
    - uniform: interpolates linearly between points, with residual probability attributed to the min and max values
    """
    # Todo: refactor, currently too many possible types of output

    if distribution is None:
        for cdf_p in cdfs_p:
            cdf_p[-1] = 1  # Last value is the highest
        return cdfs_p, cdfs_v
    cdfs = []
    if distribution == "discrete":
        for cdf_p, cdf_v in zip(cdfs_p, cdfs_v):
            cdf_p[-1] = 1  # Last value is the highest
            cdfs.append(ot.UserDefined([[v] for v in cdf_v], cp_to_p(cdf_p)))
    elif distribution in ["normal", "gaussian"]:
        for cdf_p, cdf_v in zip(cdfs_p, cdfs_v):
            if len(cdf_v) > 1:
                x1 = cdf_v[0]
                x2 = cdf_v[1]
                y1 = cdf_p[0]
                y2 = cdf_p[1]
                mu = (x1 * pyerf.erfinv(1 - 2 * y2) -
                      x2 * pyerf.erfinv(1 - 2 * y1)) / (
                          pyerf.erfinv(1 - 2 * y2) - pyerf.erfinv(1 - 2 * y1))
                sigma = (2**0.5 * x1 -
                         2**0.5 * x2) / (2 * pyerf.erfinv(1 - 2 * y2) -
                                         2 * pyerf.erfinv(1 - 2 * y1))
                cdfs.append(ot.Normal(mu, sigma))
            else:
                cdfs.append(ot.UserDefined([[v] for v in cdf_v], cdf_p))
    elif distribution == "uniform":
        for cdf_p, cdf_v in zip(cdfs_p, cdfs_v):
            if len(cdf_v) == 1:
                cdfs.append(ot.UserDefined([cdf_v]))
            elif len(cdf_v) > 1:
                coll = ([ot.UserDefined([[cdf_v[0]]])] + [
                    ot.Uniform(float(cdf_v[i]), float(cdf_v[i + 1]))
                    for i in range(len(cdf_v) - 1)
                ] + [ot.UserDefined([[cdf_v[-1]]])])
                weights = np.append(cp_to_p(cdf_p), 1 - cdf_p[-1])
                cdfs.append(ot.Mixture(coll, weights))
    else:
        return NotImplementedError
    return cdfs
def interpret_complete_cdf(
    cdfs_p: List[Union[list, np.ndarray]],
    cdfs_v: List[Union[list, np.ndarray]],
    distribution: str = None,
) -> Union[List[Union[list, np.ndarray]], Tuple[List[Union[list, np.ndarray]],
                                                List[Union[list, np.ndarray]]],
           ot.DistributionImplementation, ]:
    """Interpret the given points on the cumulative distribution function to represent a complete CDF. The default
    policy is to assume discrete probabilities.
    If a distribution name is specified, the CDF is returned as an openturns distribution object.
    Supported openturns distributions are the following:
    - discrete: all residual probability is attributed to the highest given value
    - normal or gaussian: derived from the first two point only
    - uniform: derived from the first and last points and extended to range from cp=0 to cp=1
    """
    # Todo: refactor, currently too many possible types of output

    if distribution is None:
        for cdf_p in cdfs_p:
            cdf_p[-1] = 1  # Last value is the highest
        return cdfs_p, cdfs_v
    cdfs = []
    if distribution == "discrete":
        for cdf_p, cdf_v in zip(cdfs_p, cdfs_v):
            cdf_p[-1] = 1  # Last value is the highest
            cdfs.append(ot.UserDefined([[v] for v in cdf_v], cdf_p))
    elif distribution in ["normal", "gaussian"]:
        for cdf_p, cdf_v in zip(cdfs_p, cdfs_v):
            x1 = cdf_v[0]
            x2 = cdf_v[1]
            y1 = cdf_p[0]
            y2 = cdf_p[1]
            mu = (x1 * pyerf.erfinv(1 - 2 * y2) - x2 * pyerf.erfinv(1 - 2 * y1)
                  ) / (pyerf.erfinv(1 - 2 * y2) - pyerf.erfinv(1 - 2 * y1))
            sigma = (2**0.5 * x1 - 2**0.5 * x2) / (
                2 * pyerf.erfinv(1 - 2 * y2) - 2 * pyerf.erfinv(1 - 2 * y1))
            cdfs.append(ot.Normal(mu, sigma))
    elif distribution is "uniform":
        for cdf_p, cdf_v in zip(cdfs_p, cdfs_v):
            x1 = cdf_v[0]
            x2 = cdf_v[-1]
            y1 = cdf_p[0]
            y2 = cdf_p[-1]
            dydx = (y2 - y1) / (x2 - x1)
            a = x1 - y1 / dydx
            b = x2 + (1 - y2) / dydx
            cdfs.append(ot.Uniform(a, b))
    else:
        return NotImplementedError
    return cdfs
예제 #3
0
def _nppf_py(x):
    return s2 * pyerf.erfinv(2 * x - 1)
예제 #4
0
 def fractile(p):
     return math.sqrt(2) * pyerf.erfinv(2 * p - 1)