Source code for cyclic_boosting.flags

from __future__ import absolute_import, division, print_function

from enum import Enum
from typing import Optional, Union


class _FeatureProbBit(Enum):
    """Each bit may only be used once in the feature-property flag mask"""

    continuous = 0
    ordered = 1
    unordered = 2
    monotonic = 3
    missing = 4
    missing_not_learned = 5
    use_original = 6
    corr_to_width = 7
    is_linear = 8
    is_seasonal = 9
    magic_int_missing = 10
    increasing = 11
    decreasing = 12


IS_CONTINUOUS = 1 << _FeatureProbBit.continuous.value
IS_ORDERED = 1 << _FeatureProbBit.ordered.value
IS_UNORDERED = 1 << _FeatureProbBit.unordered.value
IS_MONOTONIC = IS_CONTINUOUS | (1 << _FeatureProbBit.monotonic.value)
HAS_MISSING = 1 << _FeatureProbBit.missing.value
MISSING_NOT_LEARNED = HAS_MISSING | (1 << _FeatureProbBit.missing_not_learned.value)
USE_ORIGINAL = 1 << _FeatureProbBit.use_original.value
CORR_TO_WIDTH = 1 << _FeatureProbBit.corr_to_width.value
IS_LINEAR = 1 << _FeatureProbBit.is_linear.value
IS_SEASONAL = 1 << _FeatureProbBit.is_seasonal.value
HAS_MAGIC_INT_MISSING = HAS_MISSING | (1 << _FeatureProbBit.magic_int_missing.value)
INCREASING = 1 << _FeatureProbBit.increasing.value
DECREASING = 1 << _FeatureProbBit.decreasing.value

_FLAG_LIST = [
    "IS_CONTINUOUS",
    "IS_ORDERED",
    "IS_UNORDERED",
    "IS_MONOTONIC",
    "HAS_MISSING",
    "MISSING_NOT_LEARNED",
    "USE_ORIGINAL",
    "CORR_TO_WIDTH",
    "IS_LINEAR",
    "IS_SEASONAL",
]


[docs] def is_continuous_set(feature_prop: int) -> bool: """Is IS_CONTINUOUS included in the feature properties? :param feature_prop: feature properties for one feature :type feature_prop: int :rtype: bool >>> from cyclic_boosting.flags import is_continuous_set >>> from cyclic_boosting import flags >>> is_continuous_set(flags.IS_CONTINUOUS) True >>> is_continuous_set(flags.IS_CONTINUOUS | flags.HAS_MISSING) True >>> is_continuous_set(flags.IS_ORDERED) False IS_MONOTONIC implies IS_CONTINUOUS: >>> is_continuous_set(flags.IS_MONOTONIC) True """ return feature_prop & IS_CONTINUOUS == IS_CONTINUOUS
[docs] def is_ordered_set(feature_prop: int) -> bool: """Is IS_ORDERED included in the feature properties? :param feature_prop: feature properties for one feature :type feature_prop: int :rtype: bool >>> from cyclic_boosting.flags import is_ordered_set >>> from cyclic_boosting import flags >>> is_ordered_set(flags.IS_ORDERED) True >>> is_ordered_set(flags.IS_ORDERED | flags.HAS_MISSING) True >>> is_ordered_set(flags.IS_CONTINUOUS) False """ return feature_prop & IS_ORDERED == IS_ORDERED
[docs] def is_unordered_set(feature_prop: int) -> bool: """Is IS_UNORDERED included in the feature properties? :param feature_prop: feature properties for one feature :type feature_prop: int :rtype: bool >>> from cyclic_boosting.flags import is_unordered_set >>> from cyclic_boosting import flags >>> is_unordered_set(flags.IS_UNORDERED) True >>> is_unordered_set(flags.IS_UNORDERED | flags.HAS_MISSING) True >>> is_unordered_set(flags.IS_ORDERED) False >>> is_unordered_set(flags.IS_CONTINUOUS) False """ return feature_prop & IS_UNORDERED == IS_UNORDERED
[docs] def is_monotonic_set(feature_prop: int) -> bool: """Is IS_MONOTONIC included in the feature properties? :param feature_prop: feature properties for one feature :type feature_prop: int :rtype: bool >>> from cyclic_boosting.flags import is_monotonic_set >>> from cyclic_boosting import flags >>> is_monotonic_set(flags.IS_MONOTONIC) True >>> is_monotonic_set(flags.IS_MONOTONIC | flags.HAS_MISSING) True >>> is_monotonic_set(flags.IS_CONTINUOUS) False >>> is_monotonic_set(flags.IS_CONTINUOUS | flags.IS_MONOTONIC) True >>> is_monotonic_set(flags.IS_ORDERED) False >>> is_monotonic_set(flags.IS_MONOTONIC_INCREASING) True """ return feature_prop & IS_MONOTONIC == IS_MONOTONIC
[docs] def increasing_set(feature_prop: int) -> bool: """Is INCREASING included in the feature properties? :param feature_prop: feature properties for one feature :type feature_prop: int :rtype: bool >>> from cyclic_boosting.flags import _set >>> from cyclic_boosting import flags >>> _increasing_set(flags.INCREASING) True >>> increasing_set(flags.INCREASING | flags.HAS_MISSING) True >>> increasing_set(flags.IS_MONOTONIC) False """ return feature_prop & INCREASING == INCREASING
[docs] def decreasing_set(feature_prop: int) -> bool: """Is DECREASING included in the feature properties? :param feature_prop: feature properties for one feature :type feature_prop: int :rtype: bool >>> from cyclic_boosting.flags import _set >>> from cyclic_boosting import flags >>> decreasing_set(flags.DECREASING) True >>> decreasing_set(flags.DECREASING | flags.HAS_MISSING) True >>> decreasing_set(flags.IS_MONOTONIC) False """ return feature_prop & DECREASING == DECREASING
[docs] def has_magic_missing_set(feature_prop: int) -> bool: return feature_prop & HAS_MAGIC_INT_MISSING == HAS_MAGIC_INT_MISSING
[docs] def has_missing_set(feature_prop: int) -> bool: """Is HAS_MISSING included in the feature properties? :param feature_prop: feature properties for one feature :type feature_prop: int :rtype: bool >>> from cyclic_boosting.flags import has_missing_set >>> from cyclic_boosting import flags >>> has_missing_set(flags.HAS_MISSING) True >>> has_missing_set(flags.IS_CONTINUOUS | flags.HAS_MISSING) True >>> has_missing_set(flags.IS_CONTINUOUS) False MISSING_NOT_LEARNED implies HAS_MISSING: >>> has_missing_set(flags.MISSING_NOT_LEARNED) True """ return feature_prop & HAS_MISSING == HAS_MISSING
[docs] def missing_not_learned_set(feature_prop: int) -> bool: """Is MISSING_NOT_LEARNED included in the feature properties? :param feature_prop: feature properties for one feature :type feature_prop: int :rtype: bool >>> from cyclic_boosting.flags import missing_not_learned_set >>> from cyclic_boosting import flags >>> missing_not_learned_set(flags.MISSING_NOT_LEARNED) True >>> missing_not_learned_set(flags.IS_CONTINUOUS | flags.MISSING_NOT_LEARNED) True >>> missing_not_learned_set(flags.HAS_MISSING) False >>> missing_not_learned_set(flags.IS_CONTINUOUS) False """ return feature_prop & MISSING_NOT_LEARNED == MISSING_NOT_LEARNED
def is_linear_set(feature_prop: int) -> bool: return feature_prop & IS_LINEAR == IS_LINEAR def is_seasonal_set(feature_prop: int) -> bool: return feature_prop & IS_SEASONAL == IS_SEASONAL
[docs] def check_flags_consistency(feature_prop: int) -> None: """Check that exactly one of ``IS_CONTINUOUS, IS_ORDERED, IS_UNORDERED`` has been set. Parameters ---------- feature_prop: int value to check for consistency Examples -------- >>> from cyclic_boosting.flags import check_flags_consistency >>> from cyclic_boosting import flags The following flags will just work: >>> check_flags_consistency(flags.IS_CONTINUOUS) >>> check_flags_consistency(flags.IS_ORDERED) >>> check_flags_consistency(flags.IS_UNORDERED) Flags that fail: >>> check_flags_consistency(flags.HAS_MISSING) Traceback (most recent call last): ValueError: Exactly one of IS_CONTINUOUS, IS_ORDERED, IS_UNORDERED ... >>> check_flags_consistency(flags.IS_CONTINUOUS | flags.IS_UNORDERED) Traceback (most recent call last): ValueError: Exactly one of IS_CONTINUOUS, IS_ORDERED, IS_UNORDERED ... >>> check_flags_consistency(flags.IS_CONTINUOUS | flags.IS_ORDERED) Traceback (most recent call last): ValueError: Exactly one of IS_CONTINUOUS, IS_ORDERED, IS_UNORDERED ... >>> check_flags_consistency(flags.IS_ORDERED | flags.IS_UNORDERED) Traceback (most recent call last): ValueError: Exactly one of IS_CONTINUOUS, IS_ORDERED, IS_UNORDERED ... >>> check_flags_consistency(flags.DECREASING | flags.INCREASING) Traceback (most recent call last): ValueError: One feature can either be ... """ if ( int(is_continuous_set(feature_prop)) + int(is_ordered_set(feature_prop)) + int(is_unordered_set(feature_prop)) != 1 ): raise ValueError( "Exactly one of IS_CONTINUOUS, IS_ORDERED, " "IS_UNORDERED must be set in a " "flags value for the feature properties." ) if int(increasing_set(feature_prop)) + int(decreasing_set(feature_prop)) == 2: raise ValueError("One feature can either be INCREASING" " or DECREASING")
[docs] def flags_to_string(flags_value: Union[int, tuple]) -> Union[tuple, str]: """ This function converts the numeric flags to the corresponding strings that are defined in the flag list. Parameters ---------- flags_value: int/tuple preprocessing flag (see :mod:`cyclic_boosting.flags`) Returns ------- str Flag value Examples -------- >>> from cyclic_boosting.flags import flags_to_string >>> from cyclic_boosting import flags >>> flags_to_string(flags.IS_CONTINUOUS) 'IS_CONTINUOUS' >>> flags_to_string(flags.IS_UNORDERED) 'IS_UNORDERED' >>> flags_to_string(flags.IS_ORDERED) 'IS_ORDERED' >>> flags_to_string(flags.IS_MONOTONIC) 'IS_CONTINUOUS | IS_MONOTONIC' >>> flags_to_string(flags.HAS_MISSING | flags.IS_CONTINUOUS) 'IS_CONTINUOUS | HAS_MISSING' >>> flags_to_string(flags.IS_UNORDERED | flags.HAS_MISSING ... | flags.MISSING_NOT_LEARNED) 'IS_UNORDERED | HAS_MISSING | MISSING_NOT_LEARNED' >>> flags_to_string((flags.IS_ORDERED, flags.HAS_MISSING ... | flags.IS_CONTINUOUS)) ('IS_ORDERED', 'IS_CONTINUOUS | HAS_MISSING') >>> flags_to_string(flags.IS_CONTINUOUS | flags.IS_UNORDERED) 'IS_CONTINUOUS | IS_UNORDERED' """ if isinstance(flags_value, tuple): return tuple(_convert_flags_to_string(flags_val) for flags_val in flags_value) else: return _convert_flags_to_string(flags_value)
def _convert_flags_to_string( flags_value: int, alternative_flag_list: Optional[int] = None, alternative_flags: Optional[dict] = None ) -> str: """ This function converts the numeric flags to the corresponding strings that are defined in the flag list. Parameters ---------- flags_value: int preprocessing flag (see :mod:`cyclic_boosting.flags`) alternative_flag_list: int alternative list of possible flags alternative_flags: dict alternative flags Returns ------- str string representation of flag """ if alternative_flag_list is None: alternative_flag_list = _FLAG_LIST lst = [] flags1 = flags_value glob_vars = globals() if alternative_flags is not None: glob_vars.update(alternative_flags) for flag_name in alternative_flag_list: flag = glob_vars[flag_name] if flag & flags_value == flag: lst.append(flag_name) flags1 &= ~flag if flags1 != 0: raise ValueError("Unknown flags %d found" % flags1) return " | ".join(lst)
[docs] def read_feature_property( feature_properties: dict, feature_group: Union[tuple, str], default: int ) -> Union[tuple, int]: """Read a feature property out of the ``feature_properties`` dict which may be None. If no value is found, return ``default`` as the default value. :param feature_properties: the `feature_properties` dict :type feature_properties: dict :param feature_group: feature group name :type feature_group: str or tuple of str :param default: the default value to return if ``feature_properties`` is `None` or doesn't contain ``feature_group`` as a key. :type default: int >>> from cyclic_boosting.flags import read_feature_property, flags_to_string >>> from cyclic_boosting import flags >>> feature_properties = {'a': flags.IS_ORDERED, 'b': flags.IS_UNORDERED} >>> flags_to_string(read_feature_property(feature_properties, 'b', flags.HAS_MISSING)) 'IS_UNORDERED' >>> flags_to_string(read_feature_property(feature_properties, 'c', flags.HAS_MISSING)) 'HAS_MISSING' """ if isinstance(feature_group, tuple): return tuple(read_feature_property(feature_properties, col, default=default) for col in feature_group) else: feature_prop = None if feature_properties is not None: feature_prop = feature_properties.get(feature_group) if feature_prop is None: feature_prop = default return feature_prop
__all__ = [ "IS_CONTINUOUS", "IS_LINEAR", "IS_ORDERED", "IS_UNORDERED", "IS_MONOTONIC", "HAS_MISSING", "HAS_MAGIC_INT_MISSING", "MISSING_NOT_LEARNED", "is_continuous_set", "is_unordered_set", "is_ordered_set", "is_monotonic_set", "has_missing_set", "missing_not_learned_set", "increasing_set", "decreasing_set", "check_flags_consistency", "flags_to_string", "read_feature_property", "has_magic_missing_set", ]