def _match_lists(
    a_objs: list[Any],
    b_objs: list[Any],
    *,
    distance: Callable[[Any, Any], bool],
) -> tuple[list[tuple[Any, Any]], list[Any], list[Any]] | NoReturn:
    """
    Matches two lists of objects using a distance function.
    The distance function should return True if the objects are equal, and False otherwise.

    Returns: (matches, a_unmatched, b_unmatched)
    """

    if len(a_objs) != len(b_objs):
        raise ValueError("The number of objects in the lists should be equal")

    distances = np.asarray([1 - int(distance(a, b)) for a in a_objs for b in b_objs])
    distances = distances.reshape((len(a_objs), len(b_objs)))

    # O(n^3) complexity or better
    a_matches, b_matches = linear_sum_assignment(distances)

    matches = []
    a_unmatched = []
    b_unmatched = []

    for a_idx, b_idx in zip(a_matches, b_matches):
        dist = distances[a_idx, b_idx]
        if dist == 1:
            if a_idx < len(a_objs):
                a_unmatched.append(a_objs[a_idx])
            if b_idx < len(b_objs):
                b_unmatched.append(b_objs[b_idx])
        else:
            matches.append((a_objs[a_idx], b_objs[b_idx]))

    return matches, a_unmatched, b_unmatched

    Matches two lists of objects using a distance function.
    The distance function should return True if the objects are equal, and False otherwise.

    Returns: (matches, a_unmatched, b_unmatched)
    
cvat/apps/engine/tests/utils.py