human
Complete this python program:
def exptrigsimp(expr, simplify=True):
assistant
#Here is the Python code you requested.

    """Simplifies exponential / trigonometric / hyperbolic functions.
    When ``simplify`` is True (default) the expression obtained after the
    simplification step will be then be passed through simplify to
    precondition it so the final transformations will be applied.
    Examples
    >>> from sympy import exptrigsimp, exp, cosh, sinh
    >>> from sympy.abc import z
    >>> exptrigsimp(exp(z) + exp(-z))
    2*cosh(z)
    >>> exptrigsimp(cosh(z) - sinh(z))
    exp(-z)
    """
    from sympy.simplify.fu import hyper_as_trig, TR2i
    from sympy.simplify.simplify import bottom_up
    def exp_trig(e):
        choices = [e]
        if e.has(*_trigs):
            choices.append(e.rewrite(exp))
        choices.append(e.rewrite(cos))
        return min(key=count_ops, *choices)
    newexpr = bottom_up(expr, exp_trig)
    if simplify:
        newexpr = newexpr.simplify()
    ex = newexpr.atoms(exp, S.Exp1)
    ex = [ei for ei in ex if ((1 / ei) not in ex)]
    for ei in ex:
        e2 = (ei ** (-2))
        if (e2 in ex):
            a = ((e2.args[0] / 2) if (not (e2 is S.Exp1)) else S.Half)
            newexpr = newexpr.subs(((e2 + 1) * ei), (2 * cosh(a)))
            newexpr = newexpr.subs(((e2 - 1) * ei), (2 * sinh(a)))
    for ei in ex:
        (n, d) = ((ei - 1), (ei + 1))
        et = (n / d)
        etinv = (d / n)
        a = (ei.args[0] if (ei.func is exp) else S.One)
        if (a.is_Mul or (a is S.ImaginaryUnit)):
            c = a.as_coefficient(I)
            if c:
                t = (S.ImaginaryUnit * tan((c / 2)))
                newexpr = newexpr.subs(etinv, (1 / t))
                newexpr = newexpr.subs(et, t)
                continue
        t = tanh((a / 2))
        newexpr = newexpr.subs(etinv, (1 / t))
        newexpr = newexpr.subs(et, t)
    if newexpr.has(HyperbolicFunction):
        (e, f) = hyper_as_trig(newexpr)
        newexpr = f(TR2i(e))
    if newexpr.has(TrigonometricFunction):
        newexpr = TR2i(newexpr)
    if (not (newexpr.has(I) and (not expr.has(I)))):
        expr = newexpr
    return expr