def transitive_closure(implications):
    """
    Computes the transitive closure of a list of implications

    Notes
    =====

    Uses Warshall's algorithm [1]_.

    References
    ==========

    * http://www.cs.hope.edu/~cusack/Notes/Notes/DiscreteMath/Warshall.pdf

    """
    full_implications = set(implications)
    literals = set().union(*map(set, full_implications))
    for k in literals:
        for i in literals:
            if (i, k) in full_implications:
                for j in literals:
                    if (k, j) in full_implications:
                        full_implications.add((i, j))
    return full_implications
