Ejemplo n.º 1
0
def in_words_float(amount, _gender=FEMALE):
    """
    Float in words

    @param amount: float numeral
    @type amount: C{float} or C{Decimal}

    @return: in-words reprsentation of float numeral
    @rtype: C{unicode}

    @raise L{pytils.err.InputParameterError}: input parameters' check failed
        (when amount is not C{float})
    @raise ValueError: when ammount is negative
    """
    utils.check_positive(amount)

    pts = []
    # преобразуем целую часть
    pts.append(sum_string(int(amount), 2,
                          (u"целая", u"целых", u"целых")))
    # теперь то, что после запятой
    remainder = _get_float_remainder(amount)
    signs = len(str(remainder)) - 1
    pts.append(sum_string(int(remainder), 2, FRACTIONS[signs]))

    return u" ".join(pts)
Ejemplo n.º 2
0
def rubles(amount, zero_for_kopeck=False):
    """
    Get string for money

    @param amount: amount of money
    @type amount: C{int}, C{long}, C{float} or C{Decimal}

    @param zero_for_kopeck: If false, then zero kopecks ignored
    @type zero_for_kopeck: C{bool}

    @return: in-words representation of money's amount
    @rtype: C{unicode}

    @raise L{pytils.err.InputParameterError}: input parameters' check failed
        (amount neither C{int}, no C{float})
    @raise ValueError: amount is negative
    """
    check_positive(amount)

    pts = []
    amount = round(amount, 2)
    pts.append(sum_string(int(amount), 1, (u"рубль", u"рубля", u"рублей")))
    remainder = _get_float_remainder(amount, 2)
    iremainder = int(remainder)

    if iremainder != 0 or zero_for_kopeck:
        # если 3.1, то это 10 копеек, а не одна
        if iremainder < 10 and len(remainder) == 1:
            iremainder *= 10
        pts.append(sum_string(iremainder, 2,
                              (u"копейка", u"копейки", u"копеек")))

    return u" ".join(pts)
Ejemplo n.º 3
0
def exponential_mechanism(x: ndarray, score_function: Callable[[ndarray],
                                                               ndarray],
                          sensitivity: float,
                          privacy_budget: PrivacyBudget) -> Any:
    """Differentially private exponantial mechanism. Each keys sampling by probability proportional to:

    .. math::
        \exp \left (\\frac{\epsilon \\times score}{2 \Delta f}\\right)

    The result guarantees :math:`(\epsilon,\delta)`-differential privacy.

    :param x: Sensitive input data
    :param score_function: a function to receive `x` and return a dictionary with items {`element`: `score`}
    :param sensitivity: The global L1-sensitivity :math:`\Delta f` of `x`
    :param privacy_budget: The privacy budget :math:`(\epsilon,0)` used for the outputs
    :return: The sampled element
    """
    check_positive(privacy_budget.epsilon)
    check_positive(sensitivity)

    R, s = score_function(x)
    s -= np.max(s)
    probability = [
        np.exp(privacy_budget.epsilon * score / (2 * sensitivity))
        for score in s
    ]
    probability /= np.sum(probability)
    return choice(R, p=probability)
Ejemplo n.º 4
0
def sum_string(amount, gender, items=None):
    """
    Get sum in words

    @param amount: amount of objects
    @type amount: C{int} or C{long}

    @param gender: gender of object (MALE, FEMALE or NEUTER)
    @type gender: C{int}

    @param items: variants of object in three forms:
        for one object, for two objects and for five objects
    @type items: 3-element C{sequence} of C{unicode} or
        just C{unicode} (three variants with delimeter ',')

    @return: in-words representation objects' amount
    @rtype: C{unicode}

    @raise L{pytils.err.InputParameterError}: input parameters' check failed
    @raise ValueError: items isn't 3-element C{sequence} or C{unicode}
    @raise ValueError: amount bigger than 10**11
    @raise ValueError: amount is negative
    """
    if isinstance(items, unicode):
        items = utils.split_values(items)
    if items is None:
        items = (u"", u"", u"")

    try:
        one_item, two_items, five_items = items
    except ValueError:
        raise ValueError("Items must be 3-element sequence")

    check_positive(amount)

    if amount == 0:
        return u"ноль %s" % five_items

    into = u''
    tmp_val = amount

    # единицы
    into, tmp_val = _sum_string_fn(into, tmp_val, gender, items)
    # тысячи
    into, tmp_val = _sum_string_fn(into, tmp_val, FEMALE,
                                    (u"тысяча", u"тысячи", u"тысяч"))
    # миллионы
    into, tmp_val = _sum_string_fn(into, tmp_val, MALE,
                                    (u"миллион", u"миллиона", u"миллионов"))
    # миллиарды
    into, tmp_val = _sum_string_fn(into, tmp_val, MALE,
                                    (u"миллиард", u"миллиарда", u"миллиардов"))
    if tmp_val == 0:
        return into
    else:
        raise ValueError("Cannot operand with numbers bigger than 10**11")
Ejemplo n.º 5
0
def _get_float_remainder(fvalue, signs=9):
    """
    Get remainder of float, i.e. 2.05 -> '05'

    @param fvalue: input value
    @type fvalue: C{int}, C{long}, C{float} or C{Decimal}

    @param signs: maximum number of signs
    @type signs: C{int} or C{long}

    @return: remainder
    @rtype: C{str}

    @raise L{pytils.err.InputParameterError}: input parameters' check failed
        (fvalue neither C{int}, no C{float})
    @raise ValueError: fvalue is negative
    @raise ValueError: signs overflow
    """
    check_positive(fvalue)
    if isinstance(fvalue, (int, long)):
        return "0"
    if isinstance(fvalue, Decimal) and fvalue.as_tuple()[2] == 0:
        # Decimal.as_tuple() -> (sign, digit_tuple, exponent)
        # если экспонента "0" -- значит дробной части нет
        return "0"

    signs = min(signs, len(FRACTIONS))

    # нужно remainder в строке, потому что дробные X.0Y
    # будут "ломаться" до X.Y
    remainder = str(fvalue).split('.')[1]
    iremainder = int(remainder)
    orig_remainder = remainder
    factor = len(str(remainder)) - signs

    if factor > 0:
        # после запятой цифр больше чем signs, округляем
        iremainder = int(round(iremainder / (10.0**factor)))
    format = "%%0%dd" % min(len(remainder), signs)

    remainder = format % iremainder

    if len(remainder) > signs:
        # при округлении цифр вида 0.998 ругаться
        raise ValueError("Signs overflow: I can't round only fractional part \
                          of %s to fit %s in %d signs" % \
                         (str(fvalue), orig_remainder, signs))

    return remainder
Ejemplo n.º 6
0
    def _check_params(self):
        """Check PHATE parameters

        This allows us to fail early - otherwise certain unacceptable
        parameter choices, such as mds='mmds', would only fail after
        minutes of runtime.

        Raises
        ------
        ValueError : unacceptable choice of parameters
        """
        utils.check_positive(n_components=self.n_components, k=self.knn)
        utils.check_int(n_components=self.n_components,
                        k=self.knn,
                        n_jobs=self.n_jobs)
        utils.check_between(-1, 1, gamma=self.gamma)
        utils.check_if_not(None, utils.check_positive, a=self.decay)
        utils.check_if_not(None,
                           utils.check_positive,
                           utils.check_int,
                           n_landmark=self.n_landmark,
                           n_pca=self.n_pca)
        utils.check_if_not('auto',
                           utils.check_positive,
                           utils.check_int,
                           t=self.t)
        if not callable(self.knn_dist):
            utils.check_in([
                'euclidean', 'precomputed', 'cosine', 'correlation',
                'cityblock', 'l1', 'l2', 'manhattan', 'braycurtis', 'canberra',
                'chebyshev', 'dice', 'hamming', 'jaccard', 'kulsinski',
                'mahalanobis', 'matching', 'minkowski', 'rogerstanimoto',
                'russellrao', 'seuclidean', 'sokalmichener', 'sokalsneath',
                'sqeuclidean', 'yule', 'precomputed_affinity',
                'precomputed_distance'
            ],
                           knn_dist=self.knn_dist)
        if not callable(self.mds_dist):
            utils.check_in([
                'euclidean', 'cosine', 'correlation', 'braycurtis', 'canberra',
                'chebyshev', 'cityblock', 'dice', 'hamming', 'jaccard',
                'kulsinski', 'mahalanobis', 'matching', 'minkowski',
                'rogerstanimoto', 'russellrao', 'seuclidean', 'sokalmichener',
                'sokalsneath', 'sqeuclidean', 'yule'
            ],
                           mds_dist=self.mds_dist)
        utils.check_in(['classic', 'metric', 'nonmetric'], mds=self.mds)
Ejemplo n.º 7
0
def in_words_int(amount, gender=MALE):
    """
    Integer in words

    @param amount: numeral
    @type amount: C{int} or C{long}

    @param gender: gender (MALE, FEMALE or NEUTER)
    @type gender: C{int}

    @return: in-words reprsentation of numeral
    @rtype: C{unicode}

    @raise L{pytils.err.InputParameterError}: input parameters' check failed
        (when amount is not C{int})
    @raise ValueError: amount is negative
    """
    check_positive(amount)

    return sum_string(amount, gender)
Ejemplo n.º 8
0
def gaussian_mechanism(x: Union[int, float, ndarray], sensitivity: float,
                       privacy_budget: PrivacyBudget) -> Union[float, ndarray]:
    """Differentially private Gaussian mechanism. Add Gaussian noise to the value:

    .. math::
            x + Normal\left(\mu=0, \sigma=\\frac{\sqrt{2\log(1.25/\delta)}\Delta f}{\epsilon} \\right)

    The result guarantees :math:`(\epsilon,\delta)`-differential privacy.

    :param x: Sensitive input data
    :param sensitivity: The global L2-sensitivity :math:`\Delta f` of `x`
    :param privacy_budget: The privacy budget :math:`(\epsilon,\delta)` used for the outputs
    :return: Input data protected by noise
    """
    check_positive(privacy_budget.epsilon)
    check_positive(privacy_budget.delta)
    check_positive(sensitivity)
    assert (privacy_budget.epsilon < 1)

    shape = None if isinstance(x, (int, float)) else x.shape
    noise = normal(loc=0.,
                   scale=np.sqrt(2 * np.log(1.25 / privacy_budget.delta)) *
                   sensitivity / privacy_budget.epsilon,
                   size=shape)
    return x + noise
Ejemplo n.º 9
0
def laplace_mechanism(x: Union[int, float, ndarray], sensitivity: float,
                      privacy_budget: PrivacyBudget) -> Union[float, ndarray]:
    """Differentially private Laplace mechanism. Add Laplacian noise to the value:

    .. math::
            x + Laplace\left(\mu=0, \sigma=\\frac{\Delta f}{\epsilon}\\right)

    The result guarantees :math:`(\epsilon,0)`-differential privacy.

    :param x: Sensitive input data
    :param sensitivity: The global L1-sensitivity :math:`\Delta f` of `x`
    :param privacy_budget: The privacy budget :math:`(\epsilon,0)` used for the outputs
    :return: Input data protected by noise
    """
    check_positive(privacy_budget.epsilon)
    check_positive(sensitivity)

    shape = None if isinstance(x, (int, float)) else x.shape
    noise = laplace(loc=0.,
                    scale=sensitivity / privacy_budget.epsilon,
                    size=shape)
    return x + noise
Ejemplo n.º 10
0
def in_words(amount, gender=None):
    """
    Numeral in words

    @param amount: numeral
    @type amount: C{int}, C{long}, C{float} or C{Decimal}

    @param gender: gender (MALE, FEMALE or NEUTER)
    @type gender: C{int}

    @return: in-words reprsentation of numeral
    @rtype: C{unicode}

    raise L{pytils.err.InputParameterError}: input parameters' check failed
        (when amount not C{int} or C{float}, gender is not C{int} (and not None),
         gender isn't in (MALE, FEMALE, NEUTER))
    raise ValueError: when amount is negative
    """
    check_positive(amount)
    if isinstance(amount, Decimal) and amount.as_tuple()[2] == 0:
        # если целое,
        # т.е. Decimal.as_tuple -> (sign, digits tuple, exponent), exponent=0
        # то как целое
        amount = int(amount)
    if gender is None:
        args = (amount,)
    else:
        args = (amount, gender)
    # если целое
    if isinstance(amount, (int, long)):
        return in_words_int(*args)
    # если дробное
    elif isinstance(amount, (float, Decimal)):
        return in_words_float(*args)
    # ни float, ни int, ни Decimal
    else:
        # до сюда не должно дойти
        raise RuntimeError()
Ejemplo n.º 11
0
 def check_params(self):
     '''
     check netImpute paameter and raise a valueError if needed
     '''
     utils.check_positive(k=self.k)
Ejemplo n.º 12
0
def distance_of_time_in_words(from_time, accuracy=1, to_time=None):
    """
    Represents distance of time in words

    @param from_time: source time (in seconds from epoch)
    @type from_time: C{int}, C{float} or C{datetime.datetime}

    @param accuracy: level of accuracy (1..3), default=1
    @type accuracy: C{int}

    @param to_time: target time (in seconds from epoch),
        default=None translates to current time
    @type to_time: C{int}, C{float} or C{datetime.datetime}

    @return: distance of time in words
    @rtype: unicode

    @raise L{pytils.err.InputParameterError}: input parameters' check failed
    @raise ValueError: accuracy is lesser or equal zero
    """
    current = False

    if to_time is None:
        current = True
        to_time = datetime.datetime.now()

    check_positive(accuracy, strict=True)

    if not isinstance(from_time, datetime.datetime):
        from_time = datetime.datetime.fromtimestamp(from_time)

    if not isinstance(to_time, datetime.datetime):
        to_time = datetime.datetime.fromtimestamp(to_time)

    dt_delta = to_time - from_time
    difference = dt_delta.days * 86400 + dt_delta.seconds

    minutes_orig = int(abs(difference) / 60.0)
    hours_orig = int(abs(difference) / 3600.0)
    days_orig = int(abs(difference) / 86400.0)
    in_future = from_time > to_time

    words = []
    values = []
    alternatives = []

    days = days_orig
    hours = hours_orig - days_orig * 24

    words.append(u"%d %s" % (days, numeral.choose_plural(days, DAY_VARIANTS)))
    values.append(days)

    words.append(u"%d %s" % \
                  (hours, numeral.choose_plural(hours, HOUR_VARIANTS)))
    values.append(hours)

    days == 0 and hours == 1 and current and alternatives.append(u"час")

    minutes = minutes_orig - hours_orig * 60

    words.append(u"%d %s" %
                 (minutes, numeral.choose_plural(minutes, MINUTE_VARIANTS)))
    values.append(minutes)

    days == 0 and hours == 0 and minutes == 1 and current and \
        alternatives.append(u"минуту")

    # убираем из values и words конечные нули
    while values and not values[-1]:
        values.pop()
        words.pop()
    # убираем из values и words начальные нули
    while values and not values[0]:
        values.pop(0)
        words.pop(0)
    limit = min(accuracy, len(words))
    real_words = words[:limit]
    real_values = values[:limit]
    # снова убираем конечные нули
    while real_values and not real_values[-1]:
        real_values.pop()
        real_words.pop()
        limit -= 1

    real_str = u" ".join(real_words)

    # альтернативные варианты нужны только если в real_words одно значение
    # и, вдобавок, если используется текущее время
    alter_str = limit == 1 and current and alternatives and \
                           not (days and hours==1) and \
                           not (hours and minutes==1) and \
                           alternatives[0]
    _result_str = alter_str or real_str
    result_str = in_future and u"%s %s" % (PREFIX_IN, _result_str) \
                           or u"%s %s" % (_result_str, SUFFIX_AGO)

    # если же прошло менее минуты, то real_words -- пустой, и поэтому
    # нужно брать alternatives[0], а не result_str
    zero_str = minutes == 0 and not real_words and \
            (in_future and u"менее чем через минуту" \
                        or u"менее минуты назад")

    # нужно использовать вчера/позавчера/завтра/послезавтра
    # если days 1..2 и в real_words одно значение
    day_alternatives = DAY_ALTERNATIVES.get(days, False)
    alternate_day = day_alternatives and current and limit == 1 and \
                    ((in_future and day_alternatives[1]) \
                                 or day_alternatives[0])

    final_str = not real_words and zero_str or alternate_day or result_str

    return final_str
Ejemplo n.º 13
0
def _sum_string_fn(into, tmp_val, gender, items=None):
    """
    Make in-words representation of single order

    @param into: in-words representation of lower orders
    @type into: C{unicode}

    @param tmp_val: temporary value without lower orders
    @type tmp_val: C{int} or C{long}

    @param gender: gender (MALE, FEMALE or NEUTER)
    @type gender: C{int}

    @param items: variants of objects
    @type items: 3-element C{sequence} of C{unicode}

    @return: new into and tmp_val
    @rtype: C{tuple}

    @raise L{pytils.err.InputParameterError}: input parameters' check failed
    @raise ValueError: tmp_val is negative
    """
    if items is None:
        items = (u"", u"", u"")
    one_item, two_items, five_items = items
    
    check_positive(tmp_val)

    if tmp_val == 0:
        return into, tmp_val

    words = []

    rest = tmp_val % 1000
    tmp_val = tmp_val / 1000
    if rest == 0:
        # последние три знака нулевые
        if into == u"":
            into = u"%s " % five_items
        return into, tmp_val

    # начинаем подсчет с rest
    end_word = five_items

    # сотни
    words.append(HUNDREDS[rest / 100])

    # десятки
    rest = rest % 100
    rest1 = rest / 10
    # особый случай -- tens=1
    tens = rest1 == 1 and TENS[rest] or TENS[rest1]
    words.append(tens)

    # единицы
    if rest1 < 1 or rest1 > 1:
        amount = rest % 10
        end_word = choose_plural(amount, items)
        words.append(ONES[amount][gender-1])
    words.append(end_word)

    # добавляем то, что уже было
    words.append(into)

    # убираем пустые подстроки
    words = filter(lambda x: len(x) > 0, words)

    # склеиваем и отдаем
    return u" ".join(words).strip(), tmp_val