import collections


def compute_f1(hypothesis_list, reference_list, eps=1e-8):
    """
    Computes token F1 given a hypothesis and reference. This is defined as
    F1 = 2 * ((P * R) / (P + R + eps)) where P = precision, R = recall, and eps
    = epsilon for smoothing zero denominators. By default, eps = 1e-8.
    """

    hypothesis_set = collections.Counter(hypothesis_list)
    reference_set = collections.Counter(reference_list)
    overlapping_set = hypothesis_set & reference_set

    hypothesis_count = len(hypothesis_list)
    reference_count = len(reference_list)
    overlapping_count = sum(overlapping_set.values())

    precision = overlapping_count / hypothesis_count if hypothesis_count > 0 else 0
    recall = overlapping_count / reference_count if reference_count > 0 else 0
    f1 = (2.0 * precision * recall) / (precision + recall + eps)

    return f1