Beispiel #1
0
def test_Mul_is_infinite():
    x = Symbol('x')
    f = Symbol('f', finite=True)
    i = Symbol('i', infinite=True)
    z = Dummy(zero=True)
    nzf = Dummy(finite=True, zero=False)
    from diofant import Mul
    assert (x * f).is_finite is None
    assert (x * i).is_finite is None
    assert (f * i).is_finite is False
    assert (x * f * i).is_finite is None
    assert (z * i).is_finite is False
    assert (nzf * i).is_finite is False
    assert (z * f).is_finite is True
    assert Mul(0, f, evaluate=False).is_finite is True
    assert Mul(0, i, evaluate=False).is_finite is False

    assert (x * f).is_infinite is None
    assert (x * i).is_infinite is None
    assert (f * i).is_infinite is None
    assert (x * f * i).is_infinite is None
    assert (z * i).is_infinite is S.NaN.is_infinite
    assert (nzf * i).is_infinite is True
    assert (z * f).is_infinite is False
    assert Mul(0, f, evaluate=False).is_infinite is False
    assert Mul(0, i, evaluate=False).is_infinite is S.NaN.is_infinite
Beispiel #2
0
 def _eval_subs(self, old, new):
     if old in self.variables:
         newexpr = self.expr.subs(old, new)
         i = self.variables.index(old)
         newvars = list(self.variables)
         newpt = list(self.point)
         if new.is_Symbol:
             newvars[i] = new
         else:
             syms = new.free_symbols
             if len(syms) == 1 or old in syms:
                 if old in syms:
                     var = self.variables[i]
                 else:
                     var = syms.pop()
                 # First, try to substitute self.point in the "new"
                 # expr to see if this is a fixed point.
                 # E.g.  O(y).subs(y, sin(x))
                 point = new.subs(var, self.point[i])
                 if point != self.point[i]:
                     from diofant.solvers import solve
                     d = Dummy()
                     res = solve(old - new.subs(var, d), d, dict=True)
                     point = d.subs(res[0]).limit(old, self.point[i])
                 newvars[i] = var
                 newpt[i] = point
             elif old not in syms:
                 del newvars[i], newpt[i]
                 if not syms and new == self.point[i]:
                     newvars.extend(syms)
                     newpt.extend([S.Zero]*len(syms))
             else:
                 return
         return Order(newexpr, *zip(newvars, newpt))
Beispiel #3
0
    def arbitrary_point(self, t=None):
        """ Returns an arbitrary point on the Plane; varying `t` from 0 to 2*pi
        will move the point in a circle of radius 1 about p1 of the Plane.

        Examples
        ========

        >>> from diofant.geometry.plane import Plane
        >>> from diofant.abc import t
        >>> p = Plane((0, 0, 0), (0, 0, 1), (0, 1, 0))
        >>> p.arbitrary_point(t)
        Point3D(0, cos(t), sin(t))
        >>> _.distance(p.p1).simplify()
        1

        Returns
        =======

        Point3D

        """
        from diofant import cos, sin
        t = t or Dummy('t')
        x, y, z = self.normal_vector
        a, b, c = self.p1.args
        if x == y == 0:
            return Point3D(a + cos(t), b + sin(t), c)
        elif x == z == 0:
            return Point3D(a + cos(t), b, c + sin(t))
        elif y == z == 0:
            return Point3D(a, b + cos(t), c + sin(t))
        m = Dummy()
        p = self.projection(
            Point3D(self.p1.x + cos(t), self.p1.y + sin(t), 0) * m)
        return p.xreplace({m: solve(p.distance(self.p1) - 1, m)[0]})
Beispiel #4
0
def test_gamma():
    assert Hyper_Function([2, 3], [-1]).gamma == 0
    assert Hyper_Function([-2, -3], [-1]).gamma == 2
    n = Dummy(integer=True)
    assert Hyper_Function([-1, n, 1], []).gamma == 1
    assert Hyper_Function([-1, -n, 1], []).gamma == 1
    p = Dummy(integer=True, positive=True)
    assert Hyper_Function([-1, p, 1], []).gamma == 1
    assert Hyper_Function([-1, -p, 1], []).gamma == 2
Beispiel #5
0
    def _eval_rewrite_as_Sum(self, arg):
        from diofant import Sum
        if arg.is_even:
            k = Dummy("k", integer=True)
            j = Dummy("j", integer=True)
            n = self.args[0] / 2
            Em = (S.ImaginaryUnit * Sum(
                Sum(
                    binomial(k, j) * ((-1)**j * (k - 2 * j)**(2 * n + 1)) /
                    (2**k * S.ImaginaryUnit**k * k), (j, 0, k)),
                (k, 1, 2 * n + 1)))

            return Em
Beispiel #6
0
def test_Add_is_pos_neg():
    # these cover lines not covered by the rest of tests in core
    n = Symbol('n', negative=True, infinite=True)
    nn = Symbol('n', nonnegative=True, infinite=True)
    np = Symbol('n', nonpositive=True, infinite=True)
    p = Symbol('p', positive=True, infinite=True)
    r = Dummy(extended_real=True, finite=False)
    x = Symbol('x')
    xf = Symbol('xb', finite=True, real=True)
    assert (n + p).is_positive is None
    assert (n + x).is_positive is None
    assert (p + x).is_positive is None
    assert (n + p).is_negative is None
    assert (n + x).is_negative is None
    assert (p + x).is_negative is None

    assert (n + xf).is_positive is False
    assert (p + xf).is_positive is True
    assert (n + xf).is_negative is True
    assert (p + xf).is_negative is False

    assert (x - S.Infinity).is_negative is None  # issue sympy/sympy#7798
    # issue sympy/sympy#8046, 16.2
    assert (p + nn).is_positive
    assert (n + np).is_negative
    assert (p + r).is_positive is None
Beispiel #7
0
def swinnerton_dyer_poly(n, x=None, **args):
    """Generates n-th Swinnerton-Dyer polynomial in `x`.  """
    from .numberfields import minimal_polynomial
    if n <= 0:
        raise ValueError(
            "can't generate Swinnerton-Dyer polynomial of order %s" % n)

    if x is not None:
        sympify(x)
    else:
        x = Dummy('x')

    if n > 3:
        p = 2
        a = [sqrt(2)]
        for i in range(2, n + 1):
            p = nextprime(p)
            a.append(sqrt(p))
        return minimal_polynomial(Add(*a), x, polys=args.get('polys', False))

    if n == 1:
        ex = x**2 - 2
    elif n == 2:
        ex = x**4 - 10 * x**2 + 1
    elif n == 3:
        ex = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576
    if not args.get('polys', False):
        return ex
    else:
        return PurePoly(ex, x)
Beispiel #8
0
    def contains(self, other):
        """
        Is the other GeometryEntity contained within this Segment?

        Examples
        ========

        >>> from diofant import Point, Segment
        >>> p1, p2 = Point(0, 1), Point(3, 4)
        >>> s = Segment(p1, p2)
        >>> s2 = Segment(p2, p1)
        >>> s.contains(s2)
        True
        """
        if isinstance(other, Segment):
            return other.p1 in self and other.p2 in self
        elif isinstance(other, Point):
            if Point.is_collinear(self.p1, self.p2, other):
                t = Dummy('t')
                x, y = self.arbitrary_point(t).args
                if self.p1.x != self.p2.x:
                    ti = solve(x - other.x, t)[0]
                else:
                    ti = solve(y - other.y, t)[0]
                if ti.is_number:
                    return 0 <= ti <= 1
                return

        return False
Beispiel #9
0
def deltaproduct(f, limit):
    """Handle products containing a KroneckerDelta.

    See Also
    ========

    deltasummation
    diofant.functions.special.tensor_functions.KroneckerDelta
    diofant.concrete.products.product
    """
    from diofant.concrete.products import product

    if ((limit[2] - limit[1]) < 0) is S.true:
        return S.One

    if not f.has(KroneckerDelta):
        return product(f, limit)

    if f.is_Add:
        # Identify the term in the Add that has a simple KroneckerDelta
        delta = None
        terms = []
        for arg in sorted(f.args, key=default_sort_key):
            if delta is None and _has_simple_delta(arg, limit[0]):
                delta = arg
            else:
                terms.append(arg)
        newexpr = f.func(*terms)
        k = Dummy("kprime", integer=True)
        if isinstance(limit[1], int) and isinstance(limit[2], int):
            result = deltaproduct(newexpr, limit) + sum(
                deltaproduct(newexpr, (limit[0], limit[1], ik - 1)) *
                delta.subs(limit[0], ik) *
                deltaproduct(newexpr, (limit[0], ik + 1, limit[2]))
                for ik in range(int(limit[1]), int(limit[2] + 1)))
        else:
            result = deltaproduct(newexpr, limit) + deltasummation(
                deltaproduct(newexpr, (limit[0], limit[1], k - 1)) *
                delta.subs(limit[0], k) *
                deltaproduct(newexpr, (limit[0], k + 1, limit[2])),
                (k, limit[1], limit[2]),
                no_piecewise=_has_simple_delta(newexpr, limit[0]))
        return _remove_multiple_delta(result)

    delta, _ = _extract_delta(f, limit[0])

    if not delta:
        g = _expand_delta(f, limit[0])
        if f != g:
            from diofant import factor
            try:
                return factor(deltaproduct(g, limit))
            except AssertionError:
                return deltaproduct(g, limit)
        return product(f, limit)

    from diofant import Eq
    c = Eq(limit[2], limit[1] - 1)
    return _remove_multiple_delta(f.subs(limit[0], limit[1])*KroneckerDelta(limit[2], limit[1])) + \
        S.One*_simplify_delta(KroneckerDelta(limit[2], limit[1] - 1))
Beispiel #10
0
    def _eval_expand_func(self, **hints):
        from diofant import Sum
        n = self.args[0]
        m = self.args[1] if len(self.args) == 2 else 1

        if m == S.One:
            if n.is_Add:
                off = n.args[0]
                nnew = n - off
                if off.is_Integer and off.is_positive:
                    result = [S.One / (nnew + i)
                              for i in range(off, 0, -1)] + [harmonic(nnew)]
                    return Add(*result)
                elif off.is_Integer and off.is_negative:
                    result = [-S.One / (nnew + i)
                              for i in range(0, off, -1)] + [harmonic(nnew)]
                    return Add(*result)

            if n.is_Rational:
                # Expansions for harmonic numbers at general rational arguments (u + p/q)
                # Split n as u + p/q with p < q
                p, q = n.as_numer_denom()
                u = p // q
                p = p - u * q
                if u.is_nonnegative and p.is_positive and q.is_positive and p < q:
                    k = Dummy("k")
                    t1 = q * Sum(1 / (q * k + p), (k, 0, u))
                    t2 = 2 * Sum(
                        cos((2 * pi * p * k) / q) * log(sin((pi * k) / q)),
                        (k, 1, floor((q - 1) / Integer(2))))
                    t3 = (pi / 2) * cot((pi * p) / q) + log(2 * q)
                    return t1 + t2 - t3

        return self
Beispiel #11
0
    def build_ideal(x, terms):
        """
        Build generators for our ideal. Terms is an iterable with elements of
        the form (fn, coeff), indicating that we have a generator fn(coeff*x).

        If any of the terms is trigonometric, sin(x) and cos(x) are guaranteed
        to appear in terms. Similarly for hyperbolic functions. For tan(n*x),
        sin(n*x) and cos(n*x) are guaranteed.
        """
        gens = []
        I = []
        y = Dummy('y')
        for fn, coeff in terms:
            for c, s, t, rel in ([cos, sin, tan,
                                  cos(x)**2 + sin(x)**2 - 1], [
                                      cosh, sinh, tanh,
                                      cosh(x)**2 - sinh(x)**2 - 1
                                  ]):
                if coeff == 1 and fn in [c, s]:
                    I.append(rel)
                elif fn == t:
                    I.append(t(coeff * x) * c(coeff * x) - s(coeff * x))
                elif fn in [c, s]:
                    cn = fn(coeff * y).expand(trig=True).subs(y, x)
                    I.append(fn(coeff * x) - cn)
        return list(set(I))
Beispiel #12
0
def posify(eq):
    """Return eq (with generic symbols made positive) and a
    dictionary containing the mapping between the old and new
    symbols.

    Any symbol that has positive=None will be replaced with a positive dummy
    symbol having the same name. This replacement will allow more symbolic
    processing of expressions, especially those involving powers and
    logarithms.

    A dictionary that can be sent to subs to restore eq to its original
    symbols is also returned.

    >>> from diofant import posify, Symbol, log, solve
    >>> from diofant.abc import x
    >>> posify(x + Symbol('p', positive=True) + Symbol('n', negative=True))
    (n + p + _x, {_x: x})

    >>> eq = 1/x
    >>> log(eq).expand()
    log(1/x)
    >>> log(posify(eq)[0]).expand()
    -log(_x)
    >>> p, rep = posify(eq)
    >>> log(p).expand().subs(rep)
    -log(x)

    It is possible to apply the same transformations to an iterable
    of expressions:

    >>> eq = x**2 - 4
    >>> solve(eq, x)
    [-2, 2]
    >>> eq_x, reps = posify([eq, x]); eq_x
    [_x**2 - 4, _x]
    >>> solve(*eq_x)
    [2]
    """
    eq = sympify(eq)
    if iterable(eq):
        f = type(eq)
        eq = list(eq)
        syms = set()
        for e in eq:
            syms = syms.union(e.atoms(Symbol))
        reps = {}
        for s in syms:
            reps.update({v: k for k, v in posify(s)[1].items()})
        for i, e in enumerate(eq):
            eq[i] = e.subs(reps)
        return f(eq), {r: s for s, r in reps.items()}

    reps = {
        s: Dummy(s.name, positive=True)
        for s in eq.free_symbols if s.is_positive is None
    }
    eq = eq.subs(reps)
    return eq, {r: s for s, r in reps.items()}
Beispiel #13
0
def reduce_inequalities(inequalities, symbols=[]):
    """
    Reduce a system of inequalities with rational coefficients.

    Examples
    ========

    >>> from diofant.solvers.inequalities import reduce_inequalities

    >>> x = Symbol('x', real=True)
    >>> y = Symbol('y', real=True)

    >>> reduce_inequalities(0 <= x + 3, [])
    -3 <= x
    >>> reduce_inequalities(0 <= x + y*2 - 1, [x])
    -2*y + 1 <= x
    """
    if not iterable(inequalities):
        inequalities = [inequalities]

    # prefilter
    keep = []
    for i in inequalities:
        if isinstance(i, Relational):
            i = i.func(i.lhs.as_expr() - i.rhs.as_expr(), 0)
        elif i not in (True, False):
            i = Eq(i, 0)
        if i == S.true:
            continue
        elif i == S.false:
            return S.false
        if i.lhs.is_number:
            raise NotImplementedError("Couldn't determine truth value of %s" %
                                      i)
        keep.append(i)
    inequalities = keep
    del keep

    gens = reduce(set.union, [i.free_symbols for i in inequalities], set())

    if not iterable(symbols):
        symbols = [symbols]
    symbols = set(symbols) or gens

    # make vanilla symbol real
    recast = {
        i: Dummy(i.name, extended_real=True)
        for i in gens if i.is_extended_real is None
    }
    inequalities = [i.xreplace(recast) for i in inequalities]
    symbols = {i.xreplace(recast) for i in symbols}

    # solve system
    rv = _reduce_inequalities(inequalities, symbols)

    # restore original symbols and return
    return rv.xreplace({v: k for k, v in recast.items()})
Beispiel #14
0
    def _eval_rewrite_as_Sum(self, n, k_sym=None, symbols=None):
        from diofant import Sum
        if (k_sym is not None) or (symbols is not None):
            return self

        # Dobinski's formula
        if not n.is_nonnegative:
            return self
        k = Dummy('k', integer=True, nonnegative=True)
        return 1 / E * Sum(k**n / factorial(k), (k, 0, S.Infinity))
Beispiel #15
0
    def perpendicular_segment(self, p):
        """Create a perpendicular line segment from `p` to this line.

        The enpoints of the segment are ``p`` and the closest point in
        the line containing self. (If self is not a line, the point might
        not be in self.)

        Parameters
        ==========

        p : Point3D

        Returns
        =======

        segment : Segment3D

        Notes
        =====

        Returns `p` itself if `p` is on this linear entity.

        See Also
        ========

        perpendicular_line

        Examples
        ========

        >>> from diofant import Point3D, Line3D
        >>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(1, 1, 1), Point3D(0, 2, 0)
        >>> l1 = Line3D(p1, p2)
        >>> s1 = l1.perpendicular_segment(p3)
        >>> l1.is_perpendicular(s1)
        True
        >>> p3 in s1
        True
        >>> l1.perpendicular_segment(Point3D(4, 0, 0))
        Segment3D(Point3D(4/3, 4/3, 4/3), Point3D(4, 0, 0))

        """
        p = Point3D(p)
        if p in self:
            raise NotImplementedError("Given point should not be on the line")
        t = Dummy()
        a = self.arbitrary_point(t)
        b = [i - j for i, j in zip(p.args, a.args)]
        c = sum(i * j for i, j in zip(b, self.direction_ratio))
        d = solve(c, t)
        e = a.subs(t, d[0])
        return Segment3D(p, e)
Beispiel #16
0
    def contains(self, o):
        """
        Return True if o is on this Line, or False otherwise.

        Examples
        ========

        >>> from diofant import Line,Point
        >>> p1, p2 = Point(0, 1), Point(3, 4)
        >>> l = Line(p1, p2)
        >>> l.contains(p1)
        True
        >>> l.contains((0, 1))
        True
        >>> l.contains((0, 0))
        False
        """
        if is_sequence(o):
            o = Point(o)
        if isinstance(o, Point):
            o = o.func(*[simplify(i) for i in o.args])
            x, y = Dummy(), Dummy()
            eq = self.equation(x, y)
            if not eq.has(y):
                return (solve(eq, x)[0] - o.x).equals(0)
            if not eq.has(x):
                return (solve(eq, y)[0] - o.y).equals(0)
            return (solve(eq.subs(x, o.x), y)[0] - o.y).equals(0)
        elif not isinstance(o, LinearEntity):
            return False
        elif isinstance(o, Line):
            return self.equal(o)
        elif not self.is_similar(o):
            return False
        else:
            return o.p1 in self and o.p2 in self
Beispiel #17
0
    def random_point(self, seed=None):
        """ Returns a random point on the Plane.

        Returns
        =======

        Point3D

        """
        import random
        if seed is not None:
            rng = random.Random(seed)
        else:
            rng = random
        t = Dummy('t')
        return self.arbitrary_point(t).subs(t, Rational(rng.random()))
Beispiel #18
0
def cyclotomic_poly(n, x=None, **args):
    """Generates cyclotomic polynomial of order `n` in `x`. """
    if n <= 0:
        raise ValueError("can't generate cyclotomic polynomial of order %s" %
                         n)

    poly = DMP(dup_zz_cyclotomic_poly(int(n), ZZ), ZZ)

    if x is not None:
        poly = Poly.new(poly, x)
    else:
        poly = PurePoly.new(poly, Dummy('x'))

    if not args.get('polys', False):
        return poly.as_expr()
    else:
        return poly
Beispiel #19
0
 def __contains__(self, o):
     from diofant.geometry.line3d import LinearEntity3D
     from diofant.geometry.line import LinearEntity
     x, y, z = map(Dummy, 'xyz')
     k = self.equation(x, y, z)
     if isinstance(o, Point):
         o = Point3D(o)
     if isinstance(o, Point3D):
         d = k.xreplace(dict(zip((x, y, z), o.args)))
         return d.equals(0)
     elif isinstance(o, (LinearEntity, LinearEntity3D)):
         t = Dummy()
         d = Point3D(o.arbitrary_point(t))
         e = k.subs([(x, d.x), (y, d.y), (z, d.z)])
         return e.equals(0)
     else:
         return False
Beispiel #20
0
    def perpendicular_line(self, p):
        """Create a new Line perpendicular to this linear entity which passes
        through the point `p`.

        Parameters
        ==========

        p : Point3D

        Returns
        =======

        line : Line3D

        See Also
        ========

        is_perpendicular, perpendicular_segment

        Examples
        ========

        >>> from diofant import Point3D, Line3D
        >>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(2, 3, 4), Point3D(-2, 2, 0)
        >>> l1 = Line3D(p1, p2)
        >>> l2 = l1.perpendicular_line(p3)
        >>> p3 in l2
        True
        >>> l1.is_perpendicular(l2)
        True

        """
        p = Point3D(p)
        if p in self:
            raise NotImplementedError("Given point should not be on the line")
        t = Dummy()
        a = self.arbitrary_point(t)
        b = [i - j for i, j in zip(p.args, a.args)]
        c = sum(i * j for i, j in zip(b, self.direction_ratio))
        d = solve(c, t)
        e = a.subs(t, d[0])
        return Line3D(p, e)
Beispiel #21
0
def mrv_leadterm(e, x):
    """
    Compute the leading term of the series.

    Returns
    =======

    tuple
        The leading term `c_0 w^{e_0}` of the series of `e` in terms
        of the most rapidly varying subexpression `w` in form of
        the pair ``(c0, e0)`` of Expr.

    Examples
    ========

    >>> from diofant import Symbol, exp

    >>> x = Symbol('x', real=True, positive=True)

    >>> mrv_leadterm(1/exp(-x + exp(-x)) - exp(x), x)
    (-1, 0)
    """
    if not e.has(x):
        return e, S.Zero

    e = e.replace(lambda f: f.is_Pow and f.base != S.Exp1 and f.exp.has(x),
                  lambda f: exp(log(f.base) * f.exp))
    e = e.replace(
        lambda f: f.is_Mul and sum(a.is_Pow for a in f.args) > 1,
        lambda f: Mul(
            exp(Add(*[a.exp for a in f.args
                      if a.is_Pow and a.base is S.Exp1])), *
            [a for a in f.args if not a.is_Pow or a.base is not S.Exp1]))

    # The positive dummy, w, is used here so log(w*2) etc. will expand.
    # TODO: For limits of complex functions, the algorithm would have to
    # be improved, or just find limits of Re and Im components separately.
    w = Dummy("w", real=True, positive=True)
    e, logw = rewrite(e, x, w)

    lt = e.compute_leading_term(w, logx=logw)
    return lt.as_coeff_exponent(w)
Beispiel #22
0
    def _eval_expand_func(self, **hints):
        arg = self.args[0]
        if arg.is_Rational:
            if abs(arg.p) > arg.q:
                x = Dummy('x')
                n = arg.p // arg.q
                p = arg.p - n * arg.q
                return gamma(x + n)._eval_expand_func().subs(
                    x, Rational(p, arg.q))

        if arg.is_Add:
            coeff, tail = arg.as_coeff_add()
            if coeff and coeff.q != 1:
                intpart = floor(coeff)
                tail = (coeff - intpart, ) + tail
                coeff = intpart
            tail = arg._new_rawargs(*tail, reeval=False)
            return gamma(tail) * RisingFactorial(tail, coeff)

        return self.func(*self.args)
Beispiel #23
0
    def _eval_expand_func(self, **hints):
        from diofant import Sum
        z = self.args[0]

        if z.is_Rational:
            p, q = z.as_numer_denom()
            # General rational arguments (u + p/q)
            # Split z as n + p/q with p < q
            n = p // q
            p = p - n * q
            if p.is_positive and q.is_positive and p < q:
                k = Dummy("k")
                if n.is_positive:
                    return loggamma(p / q) - n * log(q) + Sum(
                        log((k - 1) * q + p), (k, 1, n))
                elif n.is_negative:
                    return loggamma(
                        p / q) - n * log(q) + S.Pi * S.ImaginaryUnit * n - Sum(
                            log(k * q - p), (k, 1, -n))
                elif n.is_zero:
                    return loggamma(p / q)

        return self
Beispiel #24
0
    """
    from diofant.simplify.simplify import posify

    if force:
        eq, rep = posify(eq)
        return powdenest(eq, force=False).xreplace(rep)

    if polar:
        eq, rep = polarify(eq)
        return unpolarify(powdenest(unpolarify(eq, exponents_only=True)), rep)

    new = powsimp(sympify(eq))
    return new.xreplace(Transform(_denest_pow, filter=lambda m: m.is_Pow))


_y = Dummy('y')


def _denest_pow(eq):
    """
    Denest powers.

    This is a helper function for powdenest that performs the actual
    transformation.
    """
    from diofant.simplify.simplify import logcombine

    b, e = eq.as_base_exp()
    if b.is_Pow and e != 1:
        new = b._eval_power(e)
        if new is not None:
Beispiel #25
0
def besselsimp(expr):
    """
    Simplify bessel-type functions.

    This routine tries to simplify bessel-type functions. Currently it only
    works on the Bessel J and I functions, however. It works by looking at all
    such functions in turn, and eliminating factors of "I" and "-1" (actually
    their polar equivalents) in front of the argument. Then, functions of
    half-integer order are rewritten using trigonometric functions and
    functions of integer order (> 1) are rewritten using functions
    of low order.  Finally, if the expression was changed, compute
    factorization of the result with factor().

    >>> from diofant import besselj, besseli, besselsimp, polar_lift, I, Rational
    >>> from diofant.abc import z, nu
    >>> besselsimp(besselj(nu, z*polar_lift(-1)))
    E**(I*pi*nu)*besselj(nu, z)
    >>> besselsimp(besseli(nu, z*polar_lift(-I)))
    E**(-I*pi*nu/2)*besselj(nu, z)
    >>> besselsimp(besseli(Rational(-1, 2), z))
    sqrt(2)*cosh(z)/(sqrt(pi)*sqrt(z))
    >>> besselsimp(z*besseli(0, z) + z*(besseli(2, z))/2 + besseli(1, z))
    3*z*besseli(0, z)/2
    """

    # TODO
    # - better algorithm?
    # - simplify (cos(pi*b)*besselj(b,z) - besselj(-b,z))/sin(pi*b) ...
    # - use contiguity relations?

    def replacer(fro, to, factors):
        factors = set(factors)

        def repl(nu, z):
            if factors.intersection(Mul.make_args(z)):
                return to(nu, z)
            return fro(nu, z)

        return repl

    def torewrite(fro, to):
        def tofunc(nu, z):
            return fro(nu, z).rewrite(to)

        return tofunc

    def tominus(fro):
        def tofunc(nu, z):
            return exp(I * pi * nu) * fro(nu, exp_polar(-I * pi) * z)

        return tofunc

    orig_expr = expr

    ifactors = [I, exp_polar(I * pi / 2), exp_polar(-I * pi / 2)]
    expr = expr.replace(
        besselj, replacer(besselj, torewrite(besselj, besseli), ifactors))
    expr = expr.replace(
        besseli, replacer(besseli, torewrite(besseli, besselj), ifactors))

    minusfactors = [-1, exp_polar(I * pi)]
    expr = expr.replace(besselj,
                        replacer(besselj, tominus(besselj), minusfactors))
    expr = expr.replace(besseli,
                        replacer(besseli, tominus(besseli), minusfactors))

    z0 = Dummy('z')

    def expander(fro):
        def repl(nu, z):
            if (nu % 1) == Rational(1, 2):
                return exptrigsimp(
                    trigsimp(
                        unpolarify(
                            fro(nu, z0).rewrite(besselj).rewrite(jn).expand(
                                func=True)).subs(z0, z)))
            elif nu.is_Integer and nu > 1:
                return fro(nu, z).expand(func=True)
            return fro(nu, z)

        return repl

    expr = expr.replace(besselj, expander(besselj))
    expr = expr.replace(bessely, expander(bessely))
    expr = expr.replace(besseli, expander(besseli))
    expr = expr.replace(besselk, expander(besselk))

    if expr != orig_expr:
        expr = expr.factor()

    return expr
Beispiel #26
0
    def _eval_interval(self, sym, a, b):
        """Evaluates the function along the sym in a given interval ab"""
        # FIXME: Currently complex intervals are not supported.  A possible
        # replacement algorithm, discussed in issue 5227, can be found in the
        # following papers;
        #     http://portal.acm.org/citation.cfm?id=281649
        #     http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.70.4127&rep=rep1&type=pdf
        from diofant.functions.elementary.complexes import Abs

        if sym.is_real is None:
            d = Dummy('d', real=True)
            return self.subs(sym, d)._eval_interval(d, a, b)

        if self.has(Abs):
            return piecewise_fold(self.rewrite(Abs, Piecewise))._eval_interval(
                sym, a, b)

        if a is None or b is None:
            # In this case, it is just simple substitution
            return piecewise_fold(
                super(Piecewise, self)._eval_interval(sym, a, b))

        mul = 1
        if a == b:
            return S.Zero
        elif (a > b) is S.true:
            a, b, mul = b, a, -1
        elif (a <= b) is not S.true:
            newargs = []
            for e, c in self.args:
                intervals = self._sort_expr_cond(sym, S.NegativeInfinity,
                                                 S.Infinity, c)
                values = []
                for lower, upper, expr in intervals:
                    if (a < lower) is S.true:
                        mid = lower
                        rep = b
                        val = e._eval_interval(sym, mid, b)
                        val += self._eval_interval(sym, a, mid)
                    elif (a > upper) is S.true:
                        mid = upper
                        rep = b
                        val = e._eval_interval(sym, mid, b)
                        val += self._eval_interval(sym, a, mid)
                    elif (a >= lower) is S.true and (a <= upper) is S.true:
                        rep = b
                        val = e._eval_interval(sym, a, b)
                    elif (b < lower) is S.true:
                        mid = lower
                        rep = a
                        val = e._eval_interval(sym, a, mid)
                        val += self._eval_interval(sym, mid, b)
                    elif (b > upper) is S.true:
                        mid = upper
                        rep = a
                        val = e._eval_interval(sym, a, mid)
                        val += self._eval_interval(sym, mid, b)
                    elif ((b >= lower) is S.true) and ((b <= upper) is S.true):
                        rep = a
                        val = e._eval_interval(sym, a, b)
                    else:
                        raise NotImplementedError(
                            """The evaluation of a Piecewise interval when both the lower
                            and the upper limit are symbolic is not yet implemented."""
                        )
                    values.append(val)
                if len(set(values)) == 1:
                    try:
                        c = c.subs(sym, rep)
                    except AttributeError:
                        pass
                    e = values[0]
                    newargs.append((e, c))
                else:
                    for i in range(len(values)):
                        newargs.append(
                            (values[i], (c == S.true and i == len(values) - 1)
                             or And(rep >= intervals[i][0],
                                    rep <= intervals[i][1])))
            return self.func(*newargs)

        # Determine what intervals the expr,cond pairs affect.
        int_expr = self._sort_expr_cond(sym, a, b)

        # Finally run through the intervals and sum the evaluation.
        ret_fun = 0
        for int_a, int_b, expr in int_expr:
            if isinstance(expr, Piecewise):
                # If we still have a Piecewise by now, _sort_expr_cond would
                # already have determined that its conditions are independent
                # of the integration variable, thus we just use substitution.
                ret_fun += piecewise_fold(
                    super(Piecewise,
                          expr)._eval_interval(sym, Max(a, int_a),
                                               Min(b, int_b)))
            else:
                ret_fun += expr._eval_interval(sym, Max(a, int_a),
                                               Min(b, int_b))
        return mul * ret_fun
Beispiel #27
0
 def _eval_rewrite_as_Product(self, n):
     from diofant import Product
     if n.is_nonnegative and n.is_integer:
         i = Dummy('i', integer=True)
         return Product(i, (i, 1, n))
Beispiel #28
0
    def intersection(self, o):
        """The intersection with another geometrical entity.

        Parameters
        ==========

        o : Point or LinearEntity3D

        Returns
        =======

        intersection : list of geometrical entities

        See Also
        ========

        diofant.geometry.point.Point3D

        Examples
        ========

        >>> from diofant import Point3D, Line3D, Segment3D
        >>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(1, 1, 1), Point3D(7, 7, 7)
        >>> l1 = Line3D(p1, p2)
        >>> l1.intersection(p3)
        [Point3D(7, 7, 7)]

        >>> l1 = Line3D(Point3D(4,19,12), Point3D(5,25,17))
        >>> l2 = Line3D(Point3D(-3, -15, -19), direction_ratio=[2,8,8])
        >>> l1.intersection(l2)
        [Point3D(1, 1, -3)]

        >>> p6, p7 = Point3D(0, 5, 2), Point3D(2, 6, 3)
        >>> s1 = Segment3D(p6, p7)
        >>> l1.intersection(s1)
        []

        """
        if isinstance(o, Point3D):
            if o in self:
                return [o]
            else:
                return []

        elif isinstance(o, LinearEntity3D):
            if self == o:
                return [self]
            elif self.is_parallel(o):
                if isinstance(self, Line3D):
                    if o.p1 in self:
                        return [o]
                    return []
                elif isinstance(self, Ray3D):
                    if isinstance(o, Ray3D):
                        # case 1, rays in the same direction
                        if self.xdirection == o.xdirection and \
                                self.ydirection == o.ydirection and \
                                self.zdirection == o.zdirection:
                            return [self] if (self.source in o) else [o]
                        # case 2, rays in the opposite directions
                        else:
                            if o.source in self:
                                if self.source == o.source:
                                    return [self.source]
                                return [Segment3D(o.source, self.source)]
                            return []
                    elif isinstance(o, Segment3D):
                        if o.p1 in self:
                            if o.p2 in self:
                                return [o]
                            return [Segment3D(o.p1, self.source)]
                        elif o.p2 in self:
                            return [Segment3D(o.p2, self.source)]
                        return []
                elif isinstance(self, Segment3D):
                    if isinstance(o, Segment3D):
                        # A reminder that the points of Segments are ordered
                        # in such a way that the following works. See
                        # Segment3D.__new__ for details on the ordering.
                        if self.p1 not in o:
                            if self.p2 not in o:
                                # Neither of the endpoints are in o so either
                                # o is contained in this segment or it isn't
                                if o in self:
                                    return [o]
                                return []
                            else:
                                # p1 not in o but p2 is. Either there is a
                                # segment as an intersection, or they only
                                # intersect at an endpoint
                                if self.p2 == o.p1:
                                    return [o.p1]
                                return [Segment3D(o.p1, self.p2)]
                        elif self.p2 not in o:
                            # p2 not in o but p1 is. Either there is a
                            # segment as an intersection, or they only
                            # intersect at an endpoint
                            if self.p1 == o.p2:
                                return [o.p2]
                            return [Segment3D(o.p2, self.p1)]

                        # Both points of self in o so the whole segment
                        # is in o
                        return [self]

                else:  # unrecognized LinearEntity
                    raise NotImplementedError

            else:
                # If the lines are not parallel then solve their arbitrary points
                # to obtain the point of intersection
                t = t1, t2 = Dummy(), Dummy()
                a = self.arbitrary_point(t1)
                b = o.arbitrary_point(t2)
                dx = a.x - b.x
                c = solve([dx, a.y - b.y], t)
                d = solve([dx, a.z - b.z], t)
                if len(c) == 1 and len(d) == 1:
                    return []
                e = a.subs(t1, c[t1])
                if e in self and e in o:
                    return [e]
                else:
                    return []

        return o.intersection(self)
Beispiel #29
0
def test_symbols():
    assert mcode(x) == "x"
    d = Dummy("d")
    assert mcode(d) == "d%s" % d.dummy_index
Beispiel #30
0
from diofant import pi, I
from diofant.core.singleton import S
from diofant.core import Dummy, sympify
from diofant.core.function import Function, ArgumentIndexError
from diofant.functions import assoc_legendre
from diofant.functions.elementary.trigonometric import sin, cos, cot
from diofant.functions.combinatorial.factorials import factorial
from diofant.functions.elementary.complexes import Abs
from diofant.functions.elementary.exponential import exp
from diofant.functions.elementary.miscellaneous import sqrt

_x = Dummy("dummy_for_spherical_harmonics")


class Ynm(Function):
    r"""
    Spherical harmonics defined as

    .. math::
        Y_n^m(\theta, \varphi) := \sqrt{\frac{(2n+1)(n-m)!}{4\pi(n+m)!}}
                                  \exp(i m \varphi)
                                  \mathrm{P}_n^m\left(\cos(\theta)\right)

    Ynm() gives the spherical harmonic function of order `n` and `m`
    in `\theta` and `\varphi`, `Y_n^m(\theta, \varphi)`. The four
    parameters are as follows: `n \geq 0` an integer and `m` an integer
    such that `-n \leq m \leq n` holds. The two angles are real-valued
    with `\theta \in [0, \pi]` and `\varphi \in [0, 2\pi]`.

    Examples
    ========