Optimize the following code:

import itertools as it


def powerset(lst):
    """Return the powerset of a list."""
    n = len(lst)
    powerset = []
    for i in range(1 << n):
        subset = [lst[j] for j in range(n) if (i & (1 << j))]
        powerset.append(subset)
    return powerset



def chain(graph, tail=[[0]]):
    """
    (co)Recursively construct the chain for a graph.
    """
    acceptable = set()
    blacklist = set()

    for node in tail[-1]:
        options = graph[node]
        for target in options:
            if target in acceptable:
                blacklist.add(target)
                acceptable.remove(target)
            elif target in blacklist:
                pass
            else:
                acceptable.add(target)

    acceptable = list(acceptable)
    if not acceptable:
        return tail
    if acceptable in tail:
        return tail + [acceptable]
    else:
        return chain(graph, tail=tail + [acceptable])


def cycles(order):
    """
    Generate all cycles for a given order.
    """
    nodes = range(order)
    outoptions = powerset(nodes)
    graphs = it.product(outoptions, repeat=order)

    for graph in graphs:
        yield (graph, chain(graph))


def complete(cycle, left):
    """
    Check if a cycle is complete.
    """
    cycle_set = set().union(*cycle)
    left_set = set(left)

    if not left_set:
        return True

    return left_set.issubset(cycle_set)



# Example test:
lim = 5
found_cycle = False

for graph, cycle in cycles(lim):
    if complete(cycle, set(range(lim))):
        if cycle[0] == cycle[-1] and len(cycle) == 2 ** lim:
            print(graph, cycle)
            found_cycle = True

    if found_cycle:
        break