Ejemplo n.º 1
0
def _futrig(e, **kwargs):
    """Helper for futrig."""
    from sympy.simplify.fu import (
        TR1, TR2, TR3, TR2i, TR10, L, TR10i,
        TR8, TR6, TR15, TR16, TR111, TR5, TRmorrie, TR11, TR14, TR22,
        TR12)
    from sympy.core.compatibility import _nodes

    if not e.has(TrigonometricFunction):
        return e

    if e.is_Mul:
        coeff, e = e.as_independent(TrigonometricFunction)
    else:
        coeff = S.One

    Lops = lambda x: (L(x), x.count_ops(), _nodes(x), len(x.args), x.is_Add)
    trigs = lambda x: x.has(TrigonometricFunction)

    tree = [identity,
        (
        TR3,  # canonical angles
        TR1,  # sec-csc -> cos-sin
        TR12,  # expand tan of sum
        lambda x: _eapply(factor, x, trigs),
        TR2,  # tan-cot -> sin-cos
        [identity, lambda x: _eapply(_mexpand, x, trigs)],
        TR2i,  # sin-cos ratio -> tan
        lambda x: _eapply(lambda i: factor(i.normal()), x, trigs),
        TR14,  # factored identities
        TR5,  # sin-pow -> cos_pow
        TR10,  # sin-cos of sums -> sin-cos prod
        TR11, TR6, # reduce double angles and rewrite cos pows
        lambda x: _eapply(factor, x, trigs),
        TR14,  # factored powers of identities
        [identity, lambda x: _eapply(_mexpand, x, trigs)],
        TRmorrie,
        TR10i,  # sin-cos products > sin-cos of sums
        [identity, TR8],  # sin-cos products -> sin-cos of sums
        [identity, lambda x: TR2i(TR2(x))],  # tan -> sin-cos -> tan
        [
            lambda x: _eapply(expand_mul, TR5(x), trigs),
            lambda x: _eapply(
                expand_mul, TR15(x), trigs)], # pos/neg powers of sin
        [
            lambda x:  _eapply(expand_mul, TR6(x), trigs),
            lambda x:  _eapply(
                expand_mul, TR16(x), trigs)], # pos/neg powers of cos
        TR111,  # tan, sin, cos to neg power -> cot, csc, sec
        [identity, TR2i],  # sin-cos ratio to tan
        [identity, lambda x: _eapply(
            expand_mul, TR22(x), trigs)],  # tan-cot to sec-csc
        TR1, TR2, TR2i,
        [identity, lambda x: _eapply(
            factor_terms, TR12(x), trigs)],  # expand tan of sum
        )]
    e = greedy(tree, objective=Lops)(e)

    return coeff*e
Ejemplo n.º 2
0
def test_TR2i():
    # just a reminder that ratios of powers only simplify if both
    # numerator and denominator satisfy the condition that each
    # has a positive base or an integer exponent; e.g. the following,
    # at y=-1, x=1/2 gives sqrt(2)*I != -sqrt(2)*I
    assert powsimp(2**x / y**x) != (2 / y)**x

    assert TR2i(sin(x) / cos(x)) == tan(x)
    assert TR2i(sin(x) * sin(y) / cos(x)) == tan(x) * sin(y)
    assert TR2i(1 / (sin(x) / cos(x))) == 1 / tan(x)
    assert TR2i(1 / (sin(x) * sin(y) / cos(x))) == 1 / tan(x) / sin(y)
    assert TR2i(sin(x) / 2 / (cos(x) + 1)) == sin(x) / (cos(x) + 1) / 2

    assert TR2i(sin(x) / 2 / (cos(x) + 1), half=True) == tan(x / 2) / 2
    assert TR2i(sin(1) / (cos(1) + 1), half=True) == tan(S.Half)
    assert TR2i(sin(2) / (cos(2) + 1), half=True) == tan(1)
    assert TR2i(sin(4) / (cos(4) + 1), half=True) == tan(2)
    assert TR2i(sin(5) / (cos(5) + 1), half=True) == tan(5 * S.Half)
    assert TR2i((cos(1) + 1) / sin(1), half=True) == 1 / tan(S.Half)
    assert TR2i((cos(2) + 1) / sin(2), half=True) == 1 / tan(1)
    assert TR2i((cos(4) + 1) / sin(4), half=True) == 1 / tan(2)
    assert TR2i((cos(5) + 1) / sin(5), half=True) == 1 / tan(5 * S.Half)
    assert TR2i((cos(1) + 1)**(-a) * sin(1)**a, half=True) == tan(S.Half)**a
    assert TR2i((cos(2) + 1)**(-a) * sin(2)**a, half=True) == tan(1)**a
    assert TR2i((cos(4) + 1)**(-a) * sin(4)**a,
                half=True) == (cos(4) + 1)**(-a) * sin(4)**a
    assert TR2i((cos(5) + 1)**(-a) * sin(5)**a,
                half=True) == (cos(5) + 1)**(-a) * sin(5)**a
    assert TR2i((cos(1) + 1)**a * sin(1)**(-a), half=True) == tan(S.Half)**(-a)
    assert TR2i((cos(2) + 1)**a * sin(2)**(-a), half=True) == tan(1)**(-a)
    assert TR2i((cos(4) + 1)**a * sin(4)**(-a),
                half=True) == (cos(4) + 1)**a * sin(4)**(-a)
    assert TR2i((cos(5) + 1)**a * sin(5)**(-a),
                half=True) == (cos(5) + 1)**a * sin(5)**(-a)

    i = symbols('i', integer=True)
    assert TR2i(((cos(5) + 1)**i * sin(5)**(-i)),
                half=True) == tan(5 * S.Half)**(-i)
    assert TR2i(1 / ((cos(5) + 1)**i * sin(5)**(-i)),
                half=True) == tan(5 * S.Half)**i
Ejemplo n.º 3
0
def exptrigsimp(expr):
    """
    Simplifies exponential / trigonometric / hyperbolic functions.

    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):
        # select the better of e, and e rewritten in terms of exp or trig
        # functions
        choices = [e]
        if e.has(*_trigs):
            choices.append(e.rewrite(exp))
        choices.append(e.rewrite(cos))
        return min(*choices, key=count_ops)

    newexpr = bottom_up(expr, exp_trig)

    def f(rv):
        if not rv.is_Mul:
            return rv
        commutative_part, noncommutative_part = rv.args_cnc()
        # Since as_powers_dict loses order information,
        # if there is more than one noncommutative factor,
        # it should only be used to simplify the commutative part.
        if (len(noncommutative_part) > 1):
            return f(Mul(*commutative_part)) * Mul(*noncommutative_part)
        rvd = rv.as_powers_dict()
        newd = rvd.copy()

        def signlog(expr, sign=1):
            if expr is S.Exp1:
                return sign, 1
            elif isinstance(expr, exp):
                return sign, expr.args[0]
            elif sign == 1:
                return signlog(-expr, sign=-1)
            else:
                return None, None

        ee = rvd[S.Exp1]
        for k in rvd:
            if k.is_Add and len(k.args) == 2:
                # k == c*(1 + sign*E**x)
                c = k.args[0]
                sign, x = signlog(k.args[1] / c)
                if not x:
                    continue
                m = rvd[k]
                newd[k] -= m
                if ee == -x * m / 2:
                    # sinh and cosh
                    newd[S.Exp1] -= ee
                    ee = 0
                    if sign == 1:
                        newd[2 * c * cosh(x / 2)] += m
                    else:
                        newd[-2 * c * sinh(x / 2)] += m
                elif newd[1 - sign * S.Exp1**x] == -m:
                    # tanh
                    del newd[1 - sign * S.Exp1**x]
                    if sign == 1:
                        newd[-c / tanh(x / 2)] += m
                    else:
                        newd[-c * tanh(x / 2)] += m
                else:
                    newd[1 + sign * S.Exp1**x] += m
                    newd[c] += m

        return Mul(*[k**newd[k] for k in newd])

    newexpr = bottom_up(newexpr, f)

    # sin/cos and sinh/cosh ratios to tan and tanh, respectively
    if newexpr.has(HyperbolicFunction):
        e, f = hyper_as_trig(newexpr)
        newexpr = f(TR2i(e))
    if newexpr.has(TrigonometricFunction):
        newexpr = TR2i(newexpr)

    # can we ever generate an I where there was none previously?
    if not (newexpr.has(I) and not expr.has(I)):
        expr = newexpr
    return expr
Ejemplo n.º 4
0
def exptrigsimp(expr, simplify=True):
    """
    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):
        # select the better of e, and e rewritten in terms of exp or trig
        # functions
        choices = [e]
        if e.has(*_trigs):
            choices.append(e.rewrite(exp))
        choices.append(e.rewrite(cos))
        return min(*choices, key=count_ops)

    newexpr = bottom_up(expr, exp_trig)

    if simplify:
        newexpr = newexpr.simplify()

    # conversion from exp to hyperbolic
    ex = newexpr.atoms(exp, S.Exp1)
    ex = [ei for ei in ex if 1 / ei not in ex]
    ## sinh and cosh
    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))
    ## exp ratios to tan and tanh
    for ei in ex:
        n, d = ei - 1, ei + 1
        et = n / d
        etinv = d / n  # not 1/et or else recursion errors arise
        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)

    # sin/cos and sinh/cosh ratios to tan and tanh, respectively
    if newexpr.has(HyperbolicFunction):
        e, f = hyper_as_trig(newexpr)
        newexpr = f(TR2i(e))
    if newexpr.has(TrigonometricFunction):
        newexpr = TR2i(newexpr)

    # can we ever generate an I where there was none previously?
    if not (newexpr.has(I) and not expr.has(I)):
        expr = newexpr
    return expr