def compute_ngrams(tokens, max_len = None, min_len = 1):
    """
    tokens  :   iterable of string
                    a single sentence of tokens. Assumes start and stop tokens omitted
    max_len :   int
                    maximum ngram length
    min_len :   int
                    minimum ngram length

    """
    if max_len == None:
        max_len = len(tokens)

    if min_len > max_len:
        raise Exception("min_len cannot be more than max_len")

    ngrams = set()
    # unigrams
    for ngram_size in range(min_len, max_len + 1):
        for start in range(0, len(tokens) - ngram_size + 1):
            end = start + ngram_size -1
            words = []
            for i in range(start, end + 1):
                words.append(tokens[i])
            ngrams.add(tuple(words)) # make a tuple so hashable
    return ngrams