human
Complete this python program:
def as_string(i, o, leaf_formatter=default_leaf_formatter, node_formatter=default_node_formatter):
assistant
#Here is the Python code you requested.

    """Returns a string representation of the subgraph between i and o
    Parameters
    i : list
    Input `Variable` s.
    o : list
    Output `Variable` s.
    leaf_formatter : callable
    Takes a `Variable`  and returns a string to describe it.
    node_formatter : callable
    Takes an `Op`  and the list of strings corresponding to its arguments
    and returns a string to describe it.
    Returns
    str
    Returns a string representation of the subgraph between i and o. If the
    same op is used by several other ops, the first occurrence will be
    marked as :literal:`*n -> description` and all subsequent occurrences
    will be marked as :literal:`*n`, where n is an id number (ids are
    attributed in an unspecified order and only exist for viewing
    convenience).
    """
    i = set(i)
    orph = orphans(i, o)
    multi = set()
    seen = set()
    for output in o:
        op = output.owner
        if (op in seen):
            multi.add(op)
        else:
            seen.add(op)
    for op in ops(i, o):
        for input in op.inputs:
            op2 = input.owner
            if ((input in i) or (input in orph) or (op2 is None)):
                continue
            if (op2 in seen):
                multi.add(op2)
            else:
                seen.add(input.owner)
    multi = [x for x in multi]
    done = set()
    def multi_index(x):
        return (multi.index(x) + 1)
    def describe(r):
        if ((r.owner is not None) and (r not in i) and (r not in orph)):
            op = r.owner
            idx = op.outputs.index(r)
            if (len(op.outputs) == 1):
                idxs = ''
            else:
                idxs = ('::%i' % idx)
            if (op in done):
                return ('*%i%s' % (multi_index(op), idxs))
            else:
                done.add(op)
                s = node_formatter(op, [describe(input) for input in op.inputs])
                if (op in multi):
                    return ('*%i    ->    %s' % (multi_index(op), s))
                else:
                    return s
        else:
            return leaf_formatter(r)
    return [describe(output) for output in o]