# Path: craft_ai/errors.py
# class CraftAiError(Exception):
#     """Base class for exceptions in the craft ai client."""
# 
#     def __init__(self, message=None, metadata=None):
#         self.message = message
#         self.metadata = metadata
#         super(CraftAiError, self).__init__(message, metadata)
# 
#     def __str__(self):
#         return repr(self.message)
# 
# Path: craft_ai/formatters.py
# def format_decision_rules(rules):
#     return " and ".join([_format_decision_rule(rule) for rule in rules])
# 
# Path: craft_ai/operators.py
# OPERATORS = OPERATORS_V2


from functools import reduce as ft_reduce
from .errors import CraftAiError
from .formatters import format_decision_rules
from .operators import OPERATORS
            """Unable to reduce decision rules '{}' and '{}': """
            """the resulting rule is not fulfillable.""".format(
                format_decision_rules([rule_1]), format_decision_rules([rule_2])
            )
        )
    return {
        "property": rule_1["property"],
        "operator": OPERATORS["IN_INTERVAL"],
        "operand": [new_lower_bound, new_upper_bound],
    }


REDUCER_FROM_DECISION_RULE = {
    OPERATORS["IS"]: {OPERATORS["IS"]: _is_is_reducer},
    OPERATORS["IN_INTERVAL"]: {
        OPERATORS["IN_INTERVAL"]: _in_in_reducer,
        OPERATORS["GTE"]: _in_gte_reducer,
        OPERATORS["LT"]: _in_lt_reducer,
    },
    OPERATORS["GTE"]: {
        OPERATORS["IN_INTERVAL"]: lambda rule_1, rule_2: _in_gte_reducer(
            rule_2, rule_1
        ),
        OPERATORS["GTE"]: lambda rule_1, rule_2: {
            "property": rule_1["property"],
            "operator": OPERATORS["GTE"],
            "operand": max(rule_1["operand"], rule_2["operand"]),
        },
        OPERATORS["LT"]: _gte_lt_reducer,
    },

# Path: craft_ai/errors.py
# class CraftAiError(Exception):
#     """Base class for exceptions in the craft ai client."""
# 
#     def __init__(self, message=None, metadata=None):
#         self.message = message
#         self.metadata = metadata
#         super(CraftAiError, self).__init__(message, metadata)
# 
#     def __str__(self):
#         return repr(self.message)
# 
# Path: craft_ai/formatters.py
# def format_decision_rules(rules):
#     return " and ".join([_format_decision_rule(rule) for rule in rules])
# 
# Path: craft_ai/operators.py
# OPERATORS = OPERATORS_V2


# Path: craft_ai/reducer.py
from functools import reduce as ft_reduce
from .errors import CraftAiError
from .formatters import format_decision_rules
from .operators import OPERATORS

            """Unable to reduce decision rules '{}' and '{}': """
            """the resulting rule is not fulfillable.""".format(
                format_decision_rules([rule_1]), format_decision_rules([rule_2])
            )
        )
    return {
        "property": rule_1["property"],
        "operator": OPERATORS["IN_INTERVAL"],
        "operand": [new_lower_bound, new_upper_bound],
    }


REDUCER_FROM_DECISION_RULE = {
    OPERATORS["IS"]: {OPERATORS["IS"]: _is_is_reducer},
    OPERATORS["IN_INTERVAL"]: {
        OPERATORS["IN_INTERVAL"]: _in_in_reducer,
        OPERATORS["GTE"]: _in_gte_reducer,
        OPERATORS["LT"]: _in_lt_reducer,
    },
    OPERATORS["GTE"]: {
        OPERATORS["IN_INTERVAL"]: lambda rule_1, rule_2: _in_gte_reducer(
            rule_2, rule_1
        ),
        OPERATORS["GTE"]: lambda rule_1, rule_2: {
            "property": rule_1["property"],
            "operator": OPERATORS["GTE"],
            "operand": max(rule_1["operand"], rule_2["operand"]),
        },
        OPERATORS["LT"]: _gte_lt_reducer,
    },

    OPERATORS["LT"]: {