import copy


def simplify(mapping, name, **params):
    """
    Reduce the mapping.

    The method modifies the self object.

    Args:
        mapping (Mapping): the mapping to be reduced
        name (str): name of the reduced mapping
        params (**kwargs):
           'k' (int): desired number of classes (default: None).
           'thresholds' (list): list of thresholds (default: None).
           'centroids' (list): list of centroids (default: None).
           'labels' (list): list of labels (default: None).
           'method' (str): method for reduction of the mapping:
                'linear', 'kmeans' (default: 'auto'=='kmeans')
                Applicable if neither thresholds nor centroids given.
           'iters' (int): number of iterations if method is 'kmeans'
                (default: 0)
           'label_from' (int): numerical label of the first class.
                Applicable if 'mean_labels' is False.
           'mean_labels' (bool): whether class labels are to be numerical
                (False, default) or be means of elements
                in the class (True).
           'default': default value if an input value not in the mapping
               keys (the default default is 'self.default' if 'mean_labels'
               is True; otherwise None).

    Returns the reduced mapping.

    Raises:
        ValueError if:
            if more than one from 'thresholds', 'centroids' and 'k'
                are provided at the same time.
            if neither 'thresholds' nor 'centroids' nor 'k'
                are provided and also 'labels' are not provided.
            'k' < 1,
            'method' is neither 'linear' nor 'kmeans' nor 'auto',
            number of 'labels' is less than number of classes.

    Method simplifies the mapping according to provided 'thresholds'
    or 'centroids' or cluster the data to 'k' classes. If none of these
    is specified, the desired number of classes is deduced from the number
    of labels.

    Clustering using the 'linear' method simply divide the 1d space evenly.
    Clustering using the 'kmeans' method divide the 1d space using even
    percentiles of the original mapping values distribution. Then k-means
    iterations are performed if 'iters' > 0.

    If 'labels' are given, they are assigned to classes. Otherwise, if
    'mean_labels' are set to True, mean values in each class is assigned
    as the class label; otherwise, class number + 'label_from" is assigned
    as the class label. So created class labels become the mapping values
    of the new reduced mapping.

    Note that it is often required to adjust the 'default' value for the
    input values not in the mapping keys (except if new mapping labels are
    'mean_labels').
    """

    new_mapping = copy.deepcopy(mapping)
    new_mapping.__name__ = name
    return new_mapping.simplify(**params)