# Path: pyltr/util/group.py
# def check_qids(qids):
#     """Asserts that query ids are grouped into contiguous blocks.
# 
#     Note that query ids do not have to be sorted.
# 
#     Parameters
#     ----------
#     qids : array_like of shape = [n_samples]
#         List of query ids.
# 
#     Returns
#     -------
#     int
#         Number of unique query ids in `qids`.
# 
#     Raises
#     ------
#     ValueError
#         If any two query ids are not in the same contiguous block.
#         e.g. ``[1, 1, 3, 3, 2, 2, 3]``
# 
#     """
#     seen_qids = set()
#     prev_qid = None
# 
#     for qid in qids:
#         assert qid is not None
#         if qid != prev_qid:
#             if qid in seen_qids:
#                 raise ValueError('Samples must be grouped by qid.')
#             seen_qids.add(qid)
#             prev_qid = qid
# 
#     return len(seen_qids)
# 
# def get_groups(qids):
#     """Makes an iterator of query groups on the provided list of query ids.
# 
#     Parameters
#     ----------
#     qids : array_like of shape = [n_samples]
#         List of query ids.
# 
#     Yields
#     ------
#     row : (qid, int, int)
#         Tuple of query id, from, to.
#         ``[i for i, q in enumerate(qids) if q == qid] == range(from, to)``
# 
#     """
#     prev_qid = None
#     prev_limit = 0
#     total = 0
# 
#     for i, qid in enumerate(qids):
#         total += 1
#         if qid != prev_qid:
#             if i != prev_limit:
#                 yield (prev_qid, prev_limit, i)
#             prev_qid = qid
#             prev_limit = i
# 
#     if prev_limit != total:
#         yield (prev_qid, prev_limit, total)
# 
# Path: pyltr/util/sort.py
# def get_sorted_y(y, y_pred, check=True):
#     """Returns a copy of `y` sorted by position in `y_pred`.
# 
#     Parameters
#     ----------
#     y : array_like of shape = [n_samples_in_query]
#         List of sample scores for a query.
#     y_pred : array_like of shape = [n_samples_in_query]
#         List of predicted scores for a query.
# 
#     Returns
#     -------
#     y_sorted : array_like of shape = [n_samples_in_query]
#         Copy of `y` sorted by descending order of `y_pred`.
#         Ties are broken in ascending order of `y`.
# 
#     """
#     return y[get_sorted_y_positions(y, y_pred, check=check)]


import numpy as np
from six.moves import range
from ..util.group import check_qids, get_groups
from ..util.sort import get_sorted_y

        Returns
        -------
        float
            Mean of the metric over provided query groups.

        """
        check_qids(qids)
        query_groups = get_groups(qids)
        return np.mean([self.evaluate_preds(qid, targets[a:b], preds[a:b])
                        for qid, a, b in query_groups])

    def calc_mean_random(self, qids, targets):
        """Calculates the EV of the mean of the metric with random ranking.

        Parameters
        ----------
        qids : array_like of shape = [n_targets]
            See `calc_mean`.
        targets : array_like of shape = [n_targets]
            See `calc_mean`.

        Returns
        -------
        float
            Expected value of the mean of the metric on random orderings of the
            provided query groups.

        """
        check_qids(qids)

# Path: pyltr/util/group.py
# def check_qids(qids):
#     """Asserts that query ids are grouped into contiguous blocks.
# 
#     Note that query ids do not have to be sorted.
# 
#     Parameters
#     ----------
#     qids : array_like of shape = [n_samples]
#         List of query ids.
# 
#     Returns
#     -------
#     int
#         Number of unique query ids in `qids`.
# 
#     Raises
#     ------
#     ValueError
#         If any two query ids are not in the same contiguous block.
#         e.g. ``[1, 1, 3, 3, 2, 2, 3]``
# 
#     """
#     seen_qids = set()
#     prev_qid = None
# 
#     for qid in qids:
#         assert qid is not None
#         if qid != prev_qid:
#             if qid in seen_qids:
#                 raise ValueError('Samples must be grouped by qid.')
#             seen_qids.add(qid)
#             prev_qid = qid
# 
#     return len(seen_qids)
# 
# def get_groups(qids):
#     """Makes an iterator of query groups on the provided list of query ids.
# 
#     Parameters
#     ----------
#     qids : array_like of shape = [n_samples]
#         List of query ids.
# 
#     Yields
#     ------
#     row : (qid, int, int)
#         Tuple of query id, from, to.
#         ``[i for i, q in enumerate(qids) if q == qid] == range(from, to)``
# 
#     """
#     prev_qid = None
#     prev_limit = 0
#     total = 0
# 
#     for i, qid in enumerate(qids):
#         total += 1
#         if qid != prev_qid:
#             if i != prev_limit:
#                 yield (prev_qid, prev_limit, i)
#             prev_qid = qid
#             prev_limit = i
# 
#     if prev_limit != total:
#         yield (prev_qid, prev_limit, total)
# 
# Path: pyltr/util/sort.py
# def get_sorted_y(y, y_pred, check=True):
#     """Returns a copy of `y` sorted by position in `y_pred`.
# 
#     Parameters
#     ----------
#     y : array_like of shape = [n_samples_in_query]
#         List of sample scores for a query.
#     y_pred : array_like of shape = [n_samples_in_query]
#         List of predicted scores for a query.
# 
#     Returns
#     -------
#     y_sorted : array_like of shape = [n_samples_in_query]
#         Copy of `y` sorted by descending order of `y_pred`.
#         Ties are broken in ascending order of `y`.
# 
#     """
#     return y[get_sorted_y_positions(y, y_pred, check=check)]


# Path: pyltr/metrics/_metrics.py
import numpy as np
from six.moves import range
from ..util.group import check_qids, get_groups
from ..util.sort import get_sorted_y


        Returns
        -------
        float
            Mean of the metric over provided query groups.

        """
        check_qids(qids)
        query_groups = get_groups(qids)
        return np.mean([self.evaluate_preds(qid, targets[a:b], preds[a:b])
                        for qid, a, b in query_groups])

    def calc_mean_random(self, qids, targets):
        """Calculates the EV of the mean of the metric with random ranking.

        Parameters
        ----------
        qids : array_like of shape = [n_targets]
            See `calc_mean`.
        targets : array_like of shape = [n_targets]
            See `calc_mean`.

        Returns
        -------
        float
            Expected value of the mean of the metric on random orderings of the
            provided query groups.

        """
        check_qids(qids)

        query_groups = get_groups(qids)