def check_denotation(target_values, predicted_values):
    """Return True if the predicted denotation is correct.

    Args:
        target_values (list[Value] or set[Value])
        predicted_values (list[Value] or set[Value])
    Returns:
        bool
    """
    if isinstance(predicted_values, Exception):
        # the executor can return Exceptions as the denotation, if the logical form does not make sense
        return False
    # Check size
    if len(target_values) != len(predicted_values):
        return False
    # Check items
    for target in target_values:
        if not any(target.match(pred) for pred in predicted_values):
            return False
    return True