r"""
    Finds how predictions need to be modified to match the true grouping.

    Notes:
        pred_merges - the merges needed that would need to be done for the
            pred_groups to match true_groups.
        pred_hybrid - the hybrid split/merges needed that would need to be done
            for the pred_groups to match true_groups.

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_alg import *  # NOQA
        >>> import utool as ut
        >>> true_groups = [
        >>>   [20, 21], [22, 23], [1, 2], [12, 13, 14], [4], [5, 6, 3], [7, 8],
        >>>   [9, 10, 11], [31, 32, 33, 34, 35],   [41, 42, 43, 44], [45], [50]
        >>> ]
        >>> pred_groups = [
        >>>     [20, 21, 22, 23], [1, 2], [12], [13, 14], [3, 4], [5, 6,11],
        >>>     [7], [8, 9], [10], [31, 32], [33, 34, 35], [41, 42, 43, 44, 45]
        >>> ]
        >>> comparisons = ut.compare_groups(true_groups, pred_groups)
        >>> print(comparisons)
        >>> result = ut.repr4(comparisons)
        >>> print(result)
        {
            'common': {{1, 2}},
            'pred_hybrid': {{10}, {3, 4}, {5, 6, 11}, {7}, {8, 9}},
            'pred_merges': [{{12}, {13, 14}}, {{31, 32}, {33, 34, 35}}],
            'pred_splits': [{20, 21, 22, 23}, {41, 42, 43, 44, 45}],
            'true_hybrid': {{3, 5, 6}, {4}, {50}, {7, 8}, {9, 10, 11}},
            'true_merges': [{12, 13, 14}, {31, 32, 33, 34, 35}],
            'true_splits': [{{20, 21}, {22, 23}}, {{41, 42, 43, 44}, {45}}],
        }

def compare_groups(true_groups, pred_groups):
    r"""
    Finds how predictions need to be modified to match the true grouping.

    Notes:
        pred_merges - the merges needed that would need to be done for the
            pred_groups to match true_groups.
        pred_hybrid - the hybrid split/merges needed that would need to be done
            for the pred_groups to match true_groups.

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_alg import *  # NOQA
        >>> import utool as ut
        >>> true_groups = [
        >>>   [20, 21], [22, 23], [1, 2], [12, 13, 14], [4], [5, 6, 3], [7, 8],
        >>>   [9, 10, 11], [31, 32, 33, 34, 35],   [41, 42, 43, 44], [45], [50]
        >>> ]
        >>> pred_groups = [
        >>>     [20, 21, 22, 23], [1, 2], [12], [13, 14], [3, 4], [5, 6,11],
        >>>     [7], [8, 9], [10], [31, 32], [33, 34, 35], [41, 42, 43, 44, 45]
        >>> ]
        >>> comparisons = ut.compare_groups(true_groups, pred_groups)
        >>> print(comparisons)
        >>> result = ut.repr4(comparisons)
        >>> print(result)
        {
            'common': {{1, 2}},
            'pred_hybrid': {{10}, {3, 4}, {5, 6, 11}, {7}, {8, 9}},
            'pred_merges': [{{12}, {13, 14}}, {{31, 32}, {33, 34, 35}}],
            'pred_splits': [{20, 21, 22, 23}, {41, 42, 43, 44, 45}],
            'true_hybrid': {{3, 5, 6}, {4}, {50}, {7, 8}, {9, 10, 11}},
            'true_merges': [{12, 13, 14}, {31, 32, 33, 34, 35}],
            'true_splits': [{{20, 21}, {22, 23}}, {{41, 42, 43, 44}, {45}}],
        }
    """
    import utool as ut
    true = {frozenset(_group) for _group in true_groups}
    pred = {frozenset(_group) for _group in pred_groups}

    # Find the groups that are exactly the same
    common = true.intersection(pred)

    true_sets = true.difference(common)
    pred_sets = pred.difference(common)

    # connected compoment lookups
    pred_conn = {p: frozenset(ps) for ps in pred for p in ps}
    true_conn = {t: frozenset(ts) for ts in true for t in ts}

    # How many predictions can be merged into perfect pieces?
    # For each true sets, find if it can be made via merging pred sets
    pred_merges = []
    true_merges = []
    for ts in true_sets:
        ccs = set([pred_conn.get(t, frozenset()) for t in ts])
        if frozenset.union(*ccs) == ts:
            # This is a pure merge
            pred_merges.append(ccs)
            true_merges.append(ts)

    # How many predictions can be split into perfect pieces?
    true_splits = []
    pred_splits = []
    for ps in pred_sets:
        ccs = set([true_conn.get(p, frozenset()) for p in ps])
        if frozenset.union(*ccs) == ps:
            # This is a pure merge
            true_splits.append(ccs)
            pred_splits.append(ps)

    pred_merges_flat = ut.flatten(pred_merges)
    true_splits_flat = ut.flatten(true_splits)

    pred_hybrid = frozenset(map(frozenset, pred_sets)).difference(
        set(pred_splits + pred_merges_flat))

    true_hybrid = frozenset(map(frozenset, true_sets)).difference(
        set(true_merges + true_splits_flat))

    comparisons = {
        'common': common,
        # 'true_splits_flat': true_splits_flat,
        'true_splits': true_splits,
        'true_merges': true_merges,
        'true_hybrid': true_hybrid,
        'pred_splits': pred_splits,
        'pred_merges': pred_merges,
        # 'pred_merges_flat': pred_merges_flat,
        'pred_hybrid': pred_hybrid,
    }
    return comparisons