human
Complete this python program:
def devise_plan(target, origin, z):
assistant
#Here is the Python program you requested.

    """Devise a plan (consisting of shift and un-shift operators) to be applied
    to the hypergeometric function ``target`` to yield ``origin``.
    Returns a list of operators.
    >>> from sympy.simplify.hyperexpand import devise_plan, Hyper_Function
    >>> from sympy.abc import z
    Nothing to do:
    >>> devise_plan(Hyper_Function((1, 2), ()), Hyper_Function((1, 2), ()), z)
    >>> devise_plan(Hyper_Function((), (1, 2)), Hyper_Function((), (1, 2)), z)
    Very simple plans:
    >>> devise_plan(Hyper_Function((2,), ()), Hyper_Function((1,), ()), z)
    [<Increment upper 1.>]
    >>> devise_plan(Hyper_Function((), (2,)), Hyper_Function((), (1,)), z)
    [<Increment lower index #0 of [], [1].>]
    Several buckets:
    >>> from sympy import S
    >>> devise_plan(Hyper_Function((1, S.Half), ()),
    ...             Hyper_Function((2, S(\3/2\)), ()), z) #doctest: +NORMALIZE_WHITESPACE
    [<Decrement upper index #0 of [3/2, 1], [].>,
    <Decrement upper index #0 of [2, 3/2], [].>]
    A slightly more complicated plan:
    >>> devise_plan(Hyper_Function((1, 3), ()), Hyper_Function((2, 2), ()), z)
    [<Increment upper 2.>, <Decrement upper index #0 of [2, 2], [].>]
    Another more complicated plan: (note that the ap have to be shifted first!)
    >>> devise_plan(Hyper_Function((1, -1), (2,)), Hyper_Function((3, -2), (4,)), z)
    [<Decrement lower 3.>, <Decrement lower 4.>,
    <Decrement upper index #1 of [-1, 2], [4].>,
    <Decrement upper index #1 of [-1, 3], [4].>, <Increment upper -2.>]
    """
    (abuckets, bbuckets, nabuckets, nbbuckets) = [sift(params, _mod1) for params in (target.ap, target.bq, origin.ap, origin.bq)]
    if ((len(list(abuckets.keys())) != len(list(nabuckets.keys()))) or (len(list(bbuckets.keys())) != len(list(nbbuckets.keys())))):
        raise ValueError(('%s    not    reachable    from    %s' % (target, origin)))
    ops = []
    def do_shifts(fro, to, inc, dec):
        ops = []
        for i in range(len(fro)):
            if ((to[i] - fro[i]) > 0):
                sh = inc
                ch = 1
            else:
                sh = dec
                ch = (-1)
            while (to[i] != fro[i]):
                ops += [sh(fro, i)]
                fro[i] += ch
        return ops
    def do_shifts_a(nal, nbk, al, aother, bother):
        '    Shift    us    from    (nal,    nbk)    to    (al,    nbk).    '
        return do_shifts(nal, al, (lambda p, i: ShiftA(p[i])), (lambda p, i: UnShiftA((p + aother), (nbk + bother), i, z)))
    def do_shifts_b(nal, nbk, bk, aother, bother):
        '    Shift    us    from    (nal,    nbk)    to    (nal,    bk).    '
        return do_shifts(nbk, bk, (lambda p, i: UnShiftB((nal + aother), (p + bother), i, z)), (lambda p, i: ShiftB(p[i])))
    for r in sorted((list(abuckets.keys()) + list(bbuckets.keys())), key=default_sort_key):
        al = ()
        nal = ()
        bk = ()
        nbk = ()
        if (r in abuckets):
            al = abuckets[r]
            nal = nabuckets[r]
        if (r in bbuckets):
            bk = bbuckets[r]
            nbk = nbbuckets[r]
        if ((len(al) != len(nal)) or (len(bk) != len(nbk))):
            raise ValueError(('%s    not    reachable    from    %s' % (target, origin)))
        (al, nal, bk, nbk) = [sorted(list(w), key=default_sort_key) for w in [al, nal, bk, nbk]]
        def others(dic, key):
            l = []
            for (k, value) in dic.items():
                if (k != key):
                    l += list(dic[k])
            return l
        aother = others(nabuckets, r)
       ...