Пример #1
0
def _invert_real(f, g_ys, symbol):
    """ Helper function for invert_real """

    if not f.has(symbol):
        raise ValueError("Inverse of constant function doesn't exist")

    if f is symbol:
        return (f, g_ys)

    n = Dummy('n')
    if hasattr(f, 'inverse') and not isinstance(f, TrigonometricFunction) and \
            not isinstance(f, HyperbolicFunction):
        if len(f.args) > 1:
            raise ValueError("Only functions with one argument are supported.")
        return _invert_real(f.args[0], imageset(Lambda(n,
                                                       f.inverse()(n)), g_ys),
                            symbol)

    if isinstance(f, Abs):
        return _invert_real(
            f.args[0],
            Union(
                imageset(Lambda(n, n), g_ys).intersect(Interval(0, oo)),
                imageset(Lambda(n, -n), g_ys).intersect(Interval(-oo, 0))),
            symbol)

    if f.is_Add:
        # f = g + h
        g, h = f.as_independent(symbol)
        if g != S.Zero:
            return _invert_real(h, imageset(Lambda(n, n - g), g_ys), symbol)

    if f.is_Mul:
        # f = g*h
        g, h = f.as_independent(symbol)

        if g != S.One:
            return _invert_real(h, imageset(Lambda(n, n / g), g_ys), symbol)

    if f.is_Pow:
        base, expo = f.args
        base_has_sym = base.has(symbol)
        expo_has_sym = expo.has(symbol)

        if not expo_has_sym:
            res = imageset(Lambda(n, real_root(n, expo)), g_ys)
            if expo.is_rational:
                numer, denom = expo.as_numer_denom()
                if numer == S.One or numer == -S.One:
                    return _invert_real(base, res, symbol)
                else:
                    if numer % 2 == 0:
                        n = Dummy('n')
                        neg_res = imageset(Lambda(n, -n), res)
                        return _invert_real(base, res + neg_res, symbol)
                    else:
                        return _invert_real(base, res, symbol)
            else:
                if not base.is_positive:
                    raise ValueError("x**w where w is irrational is not "
                                     "defined for negative x")
                return _invert_real(base, res, symbol)

        if not base_has_sym:
            return _invert_real(expo,
                                imageset(Lambda(n,
                                                log(n) / log(base)), g_ys),
                                symbol)

    if isinstance(f, sin):
        n = Dummy('n')
        if isinstance(g_ys, FiniteSet):
            sin_invs = Union(*[imageset(Lambda(n, n*pi + (-1)**n*asin(g_y)), \
                                        S.Integers) for g_y in g_ys])
            return _invert_real(f.args[0], sin_invs, symbol)

    if isinstance(f, csc):
        n = Dummy('n')
        if isinstance(g_ys, FiniteSet):
            csc_invs = Union(*[imageset(Lambda(n, n*pi + (-1)**n*acsc(g_y)), \
                                        S.Integers) for g_y in g_ys])
            return _invert_real(f.args[0], csc_invs, symbol)

    if isinstance(f, cos):
        n = Dummy('n')
        if isinstance(g_ys, FiniteSet):
            cos_invs_f1 = Union(*[imageset(Lambda(n, 2*n*pi + acos(g_y)), \
                                        S.Integers) for g_y in g_ys])
            cos_invs_f2 = Union(*[imageset(Lambda(n, 2*n*pi - acos(g_y)), \
                                        S.Integers) for g_y in g_ys])
            cos_invs = Union(cos_invs_f1, cos_invs_f2)
            return _invert_real(f.args[0], cos_invs, symbol)

    if isinstance(f, sec):
        n = Dummy('n')
        if isinstance(g_ys, FiniteSet):
            sec_invs_f1 = Union(*[imageset(Lambda(n, 2*n*pi + asec(g_y)), \
                                        S.Integers) for g_y in g_ys])
            sec_invs_f2 = Union(*[imageset(Lambda(n, 2*n*pi - asec(g_y)), \
                                        S.Integers) for g_y in g_ys])
            sec_invs = Union(sec_invs_f1, sec_invs_f2)
            return _invert_real(f.args[0], sec_invs, symbol)

    if isinstance(f, tan) or isinstance(f, cot):
        n = Dummy('n')
        if isinstance(g_ys, FiniteSet):
            tan_cot_invs = Union(*[imageset(Lambda(n, n*pi + f.inverse()(g_y)), \
                                        S.Integers) for g_y in g_ys])
            return _invert_real(f.args[0], tan_cot_invs, symbol)
    return (f, g_ys)
Пример #2
0
def _invert_real(f, g_ys, symbol):
    """ Helper function for invert_real """

    if not f.has(symbol):
        raise ValueError("Inverse of constant function doesn't exist")

    if f is symbol:
        return (f, g_ys)

    n = Dummy('n')
    if hasattr(f, 'inverse') and not isinstance(f, TrigonometricFunction) and \
            not isinstance(f, HyperbolicFunction):
        if len(f.args) > 1:
            raise ValueError("Only functions with one argument are supported.")
        return _invert_real(f.args[0],
                            imageset(Lambda(n, f.inverse()(n)), g_ys), symbol)

    if isinstance(f, Abs):
        return _invert_real(f.args[0],
                            Union(imageset(Lambda(n, n), g_ys).intersect(Interval(0, oo)),
                                  imageset(Lambda(n, -n), g_ys).intersect(Interval(-oo, 0))),
                            symbol)

    if f.is_Add:
        # f = g + h
        g, h = f.as_independent(symbol)
        if g != S.Zero:
            return _invert_real(h, imageset(Lambda(n, n - g), g_ys), symbol)

    if f.is_Mul:
        # f = g*h
        g, h = f.as_independent(symbol)

        if g != S.One:
            return _invert_real(h, imageset(Lambda(n, n/g), g_ys), symbol)

    if f.is_Pow:
        base, expo = f.args
        base_has_sym = base.has(symbol)
        expo_has_sym = expo.has(symbol)

        if not expo_has_sym:
            res = imageset(Lambda(n, real_root(n, expo)), g_ys)
            if expo.is_rational:
                numer, denom = expo.as_numer_denom()
                if numer == S.One or numer == - S.One:
                    return _invert_real(base, res, symbol)
                else:
                    if numer % 2 == 0:
                        n = Dummy('n')
                        neg_res = imageset(Lambda(n, -n), res)
                        return _invert_real(base, res + neg_res, symbol)
                    else:
                        return _invert_real(base, res, symbol)
            else:
                if not base.is_positive:
                    raise ValueError("x**w where w is irrational is not "
                                     "defined for negative x")
                return _invert_real(base, res, symbol)

        if not base_has_sym:
            return _invert_real(expo, imageset(Lambda(n, log(n)/log(base)),
                                               g_ys), symbol)

    if isinstance(f, sin):
        n = Dummy('n')
        if isinstance(g_ys, FiniteSet):
            sin_invs = Union(*[imageset(Lambda(n, n*pi + (-1)**n*asin(g_y)), \
                                        S.Integers) for g_y in g_ys])
            return _invert_real(f.args[0], sin_invs, symbol)

    if isinstance(f, csc):
        n = Dummy('n')
        if isinstance(g_ys, FiniteSet):
            csc_invs = Union(*[imageset(Lambda(n, n*pi + (-1)**n*acsc(g_y)), \
                                        S.Integers) for g_y in g_ys])
            return _invert_real(f.args[0], csc_invs, symbol)

    if isinstance(f, cos):
        n = Dummy('n')
        if isinstance(g_ys, FiniteSet):
            cos_invs_f1 = Union(*[imageset(Lambda(n, 2*n*pi + acos(g_y)), \
                                        S.Integers) for g_y in g_ys])
            cos_invs_f2 = Union(*[imageset(Lambda(n, 2*n*pi - acos(g_y)), \
                                        S.Integers) for g_y in g_ys])
            cos_invs = Union(cos_invs_f1, cos_invs_f2)
            return _invert_real(f.args[0], cos_invs, symbol)

    if isinstance(f, sec):
        n = Dummy('n')
        if isinstance(g_ys, FiniteSet):
            sec_invs_f1 = Union(*[imageset(Lambda(n, 2*n*pi + asec(g_y)), \
                                        S.Integers) for g_y in g_ys])
            sec_invs_f2 = Union(*[imageset(Lambda(n, 2*n*pi - asec(g_y)), \
                                        S.Integers) for g_y in g_ys])
            sec_invs = Union(sec_invs_f1, sec_invs_f2)
            return _invert_real(f.args[0], sec_invs, symbol)

    if isinstance(f, tan) or isinstance(f, cot):
        n = Dummy('n')
        if isinstance(g_ys, FiniteSet):
            tan_cot_invs = Union(*[imageset(Lambda(n, n*pi + f.inverse()(g_y)), \
                                        S.Integers) for g_y in g_ys])
            return _invert_real(f.args[0], tan_cot_invs, symbol)
    return (f, g_ys)