Function calculates minimum description length for discrete features. If feature is continuous it is firstly discretized.

    x: numpy array - numerical or discrete feature
    y: numpy array - labels

def mdl_nominal(x, y, separate_max):
    """
    Function calculates minimum description length for discrete features. If feature is continuous it is firstly discretized.

    x: numpy array - numerical or discrete feature
    y: numpy array - labels
    """
    x_vals = np.unique(x)  # unique values
    if len(x_vals) == 1:  # if there is just one unique value
        return None

    y_dist = Counter(y)  # label distribution
    # calculate distributions and splits in accordance with feature type
    dist, splits = nominal_splits(x, y, x_vals, y_dist, separate_max)
    prior_mdl = calc_mdl(dist, y_dist)

    max_mdl, max_i = 0, 1
    for i in range(1, len(dist)):
        # iter 0: take first distribution
        dist0_x = [el for el in dist[:i]]
        dist0_y = np.sum(dist0_x)
        post_mdl0 = calc_mdl(dist0_x, dist0_y)

        # iter 0: take the other distributions without first
        dist1_x = [el for el in dist[i:]]
        dist1_y = np.sum(dist1_x)
        post_mdl1 = calc_mdl(dist1_x, dist1_y)

        coef = np.true_divide([sum(dist0_y.values()), sum(dist1_y.values())], len(x))
        mdl_val = prior_mdl - np.dot(coef, [post_mdl0, post_mdl1])  # calculate mdl
        if mdl_val > max_mdl:
            max_mdl, max_i = mdl_val, i

            # store splits of maximal mdl in accordance with feature type
    split = [splits[:max_i], splits[max_i:]]
    return (max_mdl, split)