示例#1
0
def test_simplify():
    x, y = R2_r.coord_functions()
    dx, dy = R2_r.base_oneforms()
    ex, ey = R2_r.base_vectors()
    assert simplify(x) == x
    assert simplify(x * y) == x * y
    assert simplify(dx * dy) == dx * dy
    assert simplify(ex * ey) == ex * ey
    assert ((1 - x) * dx) / (1 - x)**2 == dx / (1 - x)
示例#2
0
def test_simplify():
    x, y = R2_r.coord_functions()
    dx, dy = R2_r.base_oneforms()
    ex, ey = R2_r.base_vectors()
    assert simplify(x) == x
    assert simplify(x*y) == x*y
    assert simplify(dx*dy) == dx*dy
    assert simplify(ex*ey) == ex*ey
    assert ((1-x)*dx)/(1-x)**2 == dx/(1-x)
示例#3
0
 def _eval_rewrite_as_cos(self, n, m, theta, phi):
     # This method can be expensive due to extensive use of simplification!
     from diofant.simplify import simplify, trigsimp
     # TODO: Make sure n \in N
     # TODO: Assert |m| <= n ortherwise we should return 0
     term = simplify(self.expand(func=True))
     # We can do this because of the range of theta
     term = term.xreplace({Abs(sin(theta)): sin(theta)})
     return simplify(trigsimp(term))
示例#4
0
    def midpoint(self, p):
        """The midpoint between self and point p.

        Parameters
        ==========

        p : Point

        Returns
        =======

        midpoint : Point

        See Also
        ========

        diofant.geometry.line.Segment.midpoint

        Examples
        ========

        >>> from diofant.geometry import Point
        >>> p1, p2 = Point(1, 1), Point(13, 5)
        >>> p1.midpoint(p2)
        Point2D(7, 3)

        """
        return Point([simplify((a + b)*S.Half) for a, b in zip(self.args, p.args)])
示例#5
0
    def __new__(cls, *args, **kwargs):
        evaluate = kwargs.get('evaluate', global_evaluate[0])

        if iterable(args[0]):
            if isinstance(args[0], Point) and not evaluate:
                return args[0]
            args = args[0]

        # unpack the arguments into a friendly Tuple
        # if we were already a Point, we're doing an excess
        # iteration, but we'll worry about efficiency later
        coords = Tuple(*args)
        if any(a.is_number and im(a) for a in coords):
            raise ValueError('Imaginary coordinates not permitted.')

        # Turn any Floats into rationals and simplify
        # any expressions before we instantiate
        if evaluate:
            coords = coords.xreplace(dict(
                [(f, simplify(nsimplify(f, rational=True)))
                for f in coords.atoms(Float)]))
        if len(coords) == 2:
            return Point2D(coords, **kwargs)
        if len(coords) == 3:
            return Point3D(coords, **kwargs)

        return GeometryEntity.__new__(cls, *coords)
示例#6
0
def test_schwarzschild():
    m = Manifold('Schwarzschild', 4)
    p = Patch('origin', m)
    cs = CoordSystem('spherical', p, ['t', 'r', 'theta', 'phi'])
    t, r, theta, phi = cs.coord_functions()
    dt, dr, dtheta, dphi = cs.base_oneforms()
    f, g = symbols('f g', cls=Function)
    metric = (exp(2*f(r))*TP(dt, dt) - exp(2*g(r))*TP(dr, dr) -
              r**2*TP(dtheta, dtheta) - r**2*sin(theta)**2*TP(dphi, dphi))
    ricci = metric_to_Ricci_components(metric)
    assert all(ricci[i, j] == 0 for i in range(4) for j in range(4) if i != j)
    R = Symbol('R')
    eq1 = simplify((ricci[0, 0]/exp(2*f(r) - 2*g(r)) +
                    ricci[1, 1])*r/2).subs({r: R}).doit()
    assert eq1 == f(R).diff(R) + g(R).diff(R)
    eq2 = simplify(ricci[1, 1].replace(g, lambda x: -f(x)).replace(r, R).doit())
    assert eq2 == -2*f(R).diff(R)**2 - f(R).diff(R, 2) - 2*f(R).diff(R)/R
示例#7
0
def test_schwarzschild():
    m = Manifold('Schwarzschild', 4)
    p = Patch('origin', m)
    cs = CoordSystem('spherical', p, ['t', 'r', 'theta', 'phi'])
    t, r, theta, phi = cs.coord_functions()
    dt, dr, dtheta, dphi = cs.base_oneforms()
    f, g = symbols('f g', cls=Function)
    metric = (exp(2*f(r))*TP(dt, dt) - exp(2*g(r))*TP(dr, dr) -
              r**2*TP(dtheta, dtheta) - r**2*sin(theta)**2*TP(dphi, dphi))
    ricci = metric_to_Ricci_components(metric)
    assert all(ricci[i, j] == 0 for i in range(4) for j in range(4) if i != j)
    R = Symbol('R')
    eq1 = simplify((ricci[0, 0]/exp(2*f(r) - 2*g(r)) +
                    ricci[1, 1])*r/2).subs(r, R).doit()
    assert eq1 == f(R).diff(R) + g(R).diff(R)
    eq2 = simplify(ricci[1, 1].replace(g, lambda x: -f(x)).replace(r, R).doit())
    assert eq2 == -2*f(R).diff(R)**2 - f(R).diff(R, 2) - 2*f(R).diff(R)/R
示例#8
0
    def __contains__(self, o):
        if isinstance(o, Point):
            x = Dummy('x', extended_real=True)
            y = Dummy('y', extended_real=True)

            res = self.equation(x, y).subs({x: o.x, y: o.y})
            return trigsimp(simplify(res)) is S.Zero
        elif isinstance(o, Ellipse):
            return self == o
        return False
示例#9
0
def _eval_sum_hyper(f, i, a):
    """ Returns (res, cond). Sums from a to oo. """
    from diofant.functions import hyper
    from diofant.simplify import hyperexpand, hypersimp, fraction, simplify
    from diofant.polys.polytools import Poly, factor

    if a != 0:
        return _eval_sum_hyper(f.subs(i, i + a), i, 0)

    if f.subs(i, 0) == 0:
        if simplify(f.subs(i, Dummy('i', integer=True, positive=True))) == 0:
            return Integer(0), True
        return _eval_sum_hyper(f.subs(i, i + 1), i, 0)

    hs = hypersimp(f, i)
    if hs is None:
        return

    numer, denom = fraction(factor(hs))
    top, topl = numer.as_coeff_mul(i)
    bot, botl = denom.as_coeff_mul(i)
    ab = [top, bot]
    factors = [topl, botl]
    params = [[], []]
    for k in range(2):
        for fac in factors[k]:
            mul = 1
            if fac.is_Pow:
                mul = fac.exp
                fac = fac.base
                if not mul.is_Integer:
                    return
            p = Poly(fac, i)
            if p.degree() != 1:
                return
            m, n = p.all_coeffs()
            ab[k] *= m**mul
            params[k] += [n / m] * mul

    # Add "1" to numerator parameters, to account for implicit n! in
    # hypergeometric series.
    ap = params[0] + [1]
    bq = params[1]
    x = ab[0] / ab[1]
    h = hyper(ap, bq, x)

    e = h
    try:
        e = hyperexpand(h)
    except PolynomialError:
        pass
    if e is S.NaN and h.convergence_statement:
        e = h

    return f.subs(i, 0) * e, h.convergence_statement
示例#10
0
def roots_linear(f):
    """Returns a list of roots of a linear polynomial."""
    r = -f.nth(0)/f.nth(1)
    dom = f.get_domain()

    if not dom.is_Numerical:
        if dom.is_Composite:
            r = factor(r)
        else:
            r = simplify(r)

    return [r]
示例#11
0
def test_vector_simplify():
    A, s, k, m = symbols('A, s, k, m')

    test1 = (1 / a + 1 / b) * i
    assert (test1 & i) != (a + b) / (a * b)
    test1 = simplify(test1)
    assert (test1 & i) == (a + b) / (a * b)
    assert test1.simplify() == simplify(test1)

    test2 = (A**2 * s**4 / (4 * pi * k * m**3)) * i
    test2 = simplify(test2)
    assert (test2 & i) == (A**2 * s**4 / (4 * pi * k * m**3))

    test3 = ((4 + 4 * a - 2 * (2 + 2 * a)) / (2 + 2 * a)) * i
    test3 = simplify(test3)
    assert (test3 & i) == 0

    test4 = ((-4 * a * b**2 - 2 * b**3 - 2 * a**2 * b) / (a + b)**2) * i
    test4 = simplify(test4)
    assert (test4 & i) == -2 * b

    v = (sin(a)+cos(a))**2*i - j
    assert trigsimp(v) == (2*sin(a + pi/4)**2)*i + (-1)*j
    assert trigsimp(v) == v.trigsimp()

    assert simplify(Vector.zero) == Vector.zero
示例#12
0
def test_vector_simplify():
    A, s, k, m = symbols('A, s, k, m')

    test1 = (1 / a + 1 / b) * i
    assert (test1 & i) != (a + b) / (a * b)
    test1 = simplify(test1)
    assert (test1 & i) == (a + b) / (a * b)
    assert test1.simplify() == simplify(test1)

    test2 = (A**2 * s**4 / (4 * pi * k * m**3)) * i
    test2 = simplify(test2)
    assert (test2 & i) == (A**2 * s**4 / (4 * pi * k * m**3))

    test3 = ((4 + 4 * a - 2 * (2 + 2 * a)) / (2 + 2 * a)) * i
    test3 = simplify(test3)
    assert (test3 & i) == 0

    test4 = ((-4 * a * b**2 - 2 * b**3 - 2 * a**2 * b) / (a + b)**2) * i
    test4 = simplify(test4)
    assert (test4 & i) == -2 * b

    v = (sin(a)+cos(a))**2*i - j
    assert trigsimp(v) == (2*sin(a + pi/4)**2)*i + (-1)*j
    assert trigsimp(v) == v.trigsimp()

    assert simplify(Vector.zero) == Vector.zero
示例#13
0
    def __add__(self, other):
        """Add other to self by incrementing self's coordinates by those of other.

        See Also
        ========

        diofant.geometry.entity.GeometryEntity.translate
        """

        if iterable(other) and len(other) == len(self):
            return Point([simplify(a + b) for a, b in zip(self, other)])
        else:
            raise ValueError(
                "Points must have the same number of dimensions")
示例#14
0
    def area(self):
        """The area of the ellipse.

        Returns
        =======

        area : number

        Examples
        ========

        >>> from diofant import Point, Ellipse
        >>> p1 = Point(0, 0)
        >>> e1 = Ellipse(p1, 3, 1)
        >>> e1.area
        3*pi

        """
        return simplify(S.Pi * self.hradius * self.vradius)
示例#15
0
 def __new__(cls, *args, **kwargs):
     eval = kwargs.get('evaluate', global_evaluate[0])
     if isinstance(args[0], (Point, Point3D)):
         if not eval:
             return args[0]
         args = args[0].args
     else:
         if iterable(args[0]):
             args = args[0]
         if len(args) not in (2, 3):
             raise TypeError(
                 "Enter a 2 or 3 dimensional point")
     coords = Tuple(*args)
     if len(coords) == 2:
         coords += (S.Zero,)
     if eval:
         coords = coords.xreplace(dict(
             [(f, simplify(nsimplify(f, rational=True)))
             for f in coords.atoms(Float)]))
     return GeometryEntity.__new__(cls, *coords)
示例#16
0
def test_functional_diffgeom_ch4():
    x0, y0, theta0 = symbols('x0, y0, theta0', extended_real=True)
    x, y, r, theta = symbols('x, y, r, theta', extended_real=True)
    r0 = symbols('r0', positive=True)
    f = Function('f')
    b1 = Function('b1')
    b2 = Function('b2')
    p_r = R2_r.point([x0, y0])
    p_p = R2_p.point([r0, theta0])

    f_field = b1(R2.x, R2.y) * R2.dx + b2(R2.x, R2.y) * R2.dy
    assert f_field.rcall(R2.e_x).rcall(p_r) == b1(x0, y0)
    assert f_field.rcall(R2.e_y).rcall(p_r) == b2(x0, y0)

    s_field_r = f(R2.x, R2.y)
    df = Differential(s_field_r)
    assert df(R2.e_x).rcall(p_r).doit() == Derivative(f(x0, y0), x0)
    assert df(R2.e_y).rcall(p_r).doit() == Derivative(f(x0, y0), y0)

    s_field_p = f(R2.r, R2.theta)
    df = Differential(s_field_p)
    assert trigsimp(df(R2.e_x).rcall(p_p).doit()) == (
        cos(theta0) * Derivative(f(r0, theta0), r0) -
        sin(theta0) * Derivative(f(r0, theta0), theta0) / r0)
    assert trigsimp(df(R2.e_y).rcall(p_p).doit()) == (
        sin(theta0) * Derivative(f(r0, theta0), r0) +
        cos(theta0) * Derivative(f(r0, theta0), theta0) / r0)

    assert R2.dx(R2.e_x).rcall(p_r) == 1
    assert R2.dx(R2.e_x) == 1
    assert R2.dx(R2.e_y).rcall(p_r) == 0
    assert R2.dx(R2.e_y) == 0

    circ = -R2.y * R2.e_x + R2.x * R2.e_y
    assert R2.dx(circ).rcall(p_r).doit() == -y0
    assert R2.dy(circ).rcall(p_r) == x0
    assert R2.dr(circ).rcall(p_r) == 0
    assert simplify(R2.dtheta(circ).rcall(p_r)) == 1

    assert (circ - R2.e_theta).rcall(s_field_r).rcall(p_r) == 0
def test_functional_diffgeom_ch4():
    x0, y0, theta0 = symbols('x0, y0, theta0', extended_real=True)
    x, y, r, theta = symbols('x, y, r, theta', extended_real=True)
    r0 = symbols('r0', positive=True)
    f = Function('f')
    b1 = Function('b1')
    b2 = Function('b2')
    p_r = R2_r.point([x0, y0])
    p_p = R2_p.point([r0, theta0])

    f_field = b1(R2.x, R2.y)*R2.dx + b2(R2.x, R2.y)*R2.dy
    assert f_field.rcall(R2.e_x).rcall(p_r) == b1(x0, y0)
    assert f_field.rcall(R2.e_y).rcall(p_r) == b2(x0, y0)

    s_field_r = f(R2.x, R2.y)
    df = Differential(s_field_r)
    assert df(R2.e_x).rcall(p_r).doit() == Derivative(f(x0, y0), x0)
    assert df(R2.e_y).rcall(p_r).doit() == Derivative(f(x0, y0), y0)

    s_field_p = f(R2.r, R2.theta)
    df = Differential(s_field_p)
    assert trigsimp(df(R2.e_x).rcall(p_p).doit()) == (
        cos(theta0)*Derivative(f(r0, theta0), r0) -
        sin(theta0)*Derivative(f(r0, theta0), theta0)/r0)
    assert trigsimp(df(R2.e_y).rcall(p_p).doit()) == (
        sin(theta0)*Derivative(f(r0, theta0), r0) +
        cos(theta0)*Derivative(f(r0, theta0), theta0)/r0)

    assert R2.dx(R2.e_x).rcall(p_r) == 1
    assert R2.dx(R2.e_x) == 1
    assert R2.dx(R2.e_y).rcall(p_r) == 0
    assert R2.dx(R2.e_y) == 0

    circ = -R2.y*R2.e_x + R2.x*R2.e_y
    assert R2.dx(circ).rcall(p_r).doit() == -y0
    assert R2.dy(circ).rcall(p_r) == x0
    assert R2.dr(circ).rcall(p_r) == 0
    assert simplify(R2.dtheta(circ).rcall(p_r)) == 1

    assert (circ - R2.e_theta).rcall(s_field_r).rcall(p_r) == 0
示例#18
0
 def __new__(cls, *args, **kwargs):
     eval = kwargs.get('evaluate', global_evaluate[0])
     check = True
     if isinstance(args[0], Point2D):
         if not eval:
             return args[0]
         args = args[0].args
         check = False
     else:
         if iterable(args[0]):
             args = args[0]
         if len(args) != 2:
             raise ValueError(
                 "Only two dimensional points currently supported")
     coords = Tuple(*args)
     if check:
         if any(a.is_number and im(a) for a in coords):
             raise ValueError('Imaginary args not permitted.')
     if eval:
         coords = coords.xreplace(dict(
             [(f, simplify(nsimplify(f, rational=True)))
             for f in coords.atoms(Float)]))
     return GeometryEntity.__new__(cls, *coords)
示例#19
0
    def _do_line_intersection(self, o):
        """
        Find the intersection of a LinearEntity and the ellipse.

        All LinearEntities are treated as a line and filtered at
        the end to see that they lie in o.

        """

        hr_sq = self.hradius**2
        vr_sq = self.vradius**2
        lp = o.points

        ldir = lp[1] - lp[0]
        diff = lp[0] - self.center
        mdir = Point(ldir.x / hr_sq, ldir.y / vr_sq)
        mdiff = Point(diff.x / hr_sq, diff.y / vr_sq)

        a = ldir.dot(mdir)
        b = ldir.dot(mdiff)
        c = diff.dot(mdiff) - 1
        det = simplify(b * b - a * c)

        result = []
        if det == 0:
            t = -b / a
            result.append(lp[0] + (lp[1] - lp[0]) * t)
        # Definite and potential symbolic intersections are allowed.
        elif (det > 0) is not S.false:
            root = sqrt(det)
            t_a = (-b - root) / a
            t_b = (-b + root) / a
            result.append(lp[0] + (lp[1] - lp[0]) * t_a)
            result.append(lp[0] + (lp[1] - lp[0]) * t_b)

        return [r for r in result if r in o]
示例#20
0
def test_del_operator():

    # Tests for curl
    assert (delop
            ^ Vector.zero == (Derivative(0, C.y) - Derivative(0, C.z)) * C.i +
            (-Derivative(0, C.x) + Derivative(0, C.z)) * C.j +
            (Derivative(0, C.x) - Derivative(0, C.y)) * C.k)
    assert ((delop ^ Vector.zero).doit() == Vector.zero == curl(
        Vector.zero, C))
    assert delop.cross(Vector.zero) == delop ^ Vector.zero
    assert (delop ^ i).doit() == Vector.zero
    assert delop.cross(2 * y**2 * j, doit=True) == Vector.zero
    assert delop.cross(2 * y**2 * j) == delop ^ 2 * y**2 * j
    v = x * y * z * (i + j + k)
    assert ((delop ^ v).doit() == (-x * y + x * z) * i + (x * y - y * z) * j +
            (-x * z + y * z) * k == curl(v, C))
    assert delop ^ v == delop.cross(v)
    assert (delop.cross(
        2 * x**2 *
        j) == (Derivative(0, C.y) - Derivative(2 * C.x**2, C.z)) * C.i +
            (-Derivative(0, C.x) + Derivative(0, C.z)) * C.j +
            (-Derivative(0, C.y) + Derivative(2 * C.x**2, C.x)) * C.k)
    assert (delop.cross(2 * x**2 * j, doit=True) == 4 * x * k == curl(
        2 * x**2 * j, C))

    # Tests for divergence
    assert delop & Vector.zero == Integer(0) == divergence(Vector.zero, C)
    assert (delop & Vector.zero).doit() == Integer(0)
    assert delop.dot(Vector.zero) == delop & Vector.zero
    assert (delop & i).doit() == Integer(0)
    assert (delop & x**2 * i).doit() == 2 * x == divergence(x**2 * i, C)
    assert (delop.dot(v, doit=True) == x * y + y * z + z * x == divergence(
        v, C))
    assert delop & v == delop.dot(v)
    assert delop.dot(1/(x*y*z) * (i + j + k), doit=True) == \
           - 1 / (x*y*z**2) - 1 / (x*y**2*z) - 1 / (x**2*y*z)
    v = x * i + y * j + z * k
    assert (delop & v == Derivative(C.x, C.x) + Derivative(C.y, C.y) +
            Derivative(C.z, C.z))
    assert delop.dot(v, doit=True) == 3 == divergence(v, C)
    assert delop & v == delop.dot(v)
    assert simplify((delop & v).doit()) == 3

    # Tests for gradient
    assert (delop.gradient(0, doit=True) == Vector.zero == gradient(0, C))
    assert delop.gradient(0) == delop(0)
    assert (delop(Integer(0))).doit() == Vector.zero
    assert (delop(x) == (Derivative(C.x, C.x)) * C.i +
            (Derivative(C.x, C.y)) * C.j + (Derivative(C.x, C.z)) * C.k)
    assert (delop(x)).doit() == i == gradient(x, C)
    assert (delop(x * y * z) == (Derivative(C.x * C.y * C.z, C.x)) * C.i +
            (Derivative(C.x * C.y * C.z, C.y)) * C.j +
            (Derivative(C.x * C.y * C.z, C.z)) * C.k)
    assert (delop.gradient(x * y * z, doit=True) ==
            y * z * i + z * x * j + x * y * k == gradient(x * y * z, C))
    assert delop(x * y * z) == delop.gradient(x * y * z)
    assert (delop(2 * x**2)).doit() == 4 * x * i
    assert ((delop(a * sin(y) / x)).doit() == -a * sin(y) / x**2 * i +
            a * cos(y) / x * j)

    # Tests for directional derivative
    assert (Vector.zero & delop)(a) == Integer(0)
    assert ((Vector.zero & delop)(a)).doit() == Integer(0)
    assert ((v & delop)(Vector.zero)).doit() == Vector.zero
    assert ((v & delop)(Integer(0))).doit() == Integer(0)
    assert ((i & delop)(x)).doit() == 1
    assert ((j & delop)(y)).doit() == 1
    assert ((k & delop)(z)).doit() == 1
    assert ((i & delop)(x * y * z)).doit() == y * z
    assert ((v & delop)(x)).doit() == x
    assert ((v & delop)(x * y * z)).doit() == 3 * x * y * z
    assert (v & delop)(x + y + z) == C.x + C.y + C.z
    assert ((v & delop)(x + y + z)).doit() == x + y + z
    assert ((v & delop)(v)).doit() == v
    assert ((i & delop)(v)).doit() == i
    assert ((j & delop)(v)).doit() == j
    assert ((k & delop)(v)).doit() == k
    assert ((v & delop)(Vector.zero)).doit() == Vector.zero
示例#21
0
def test_product_rules():
    """
    Tests the six product rules defined with respect to the Del
    operator

    References
    ==========

    .. [1] http://en.wikipedia.org/wiki/Del

    """

    # Define the scalar and vector functions
    f = 2 * x * y * z
    g = x * y + y * z + z * x
    u = x**2 * i + 4 * j - y**2 * z * k
    v = 4 * i + x * y * z * k

    # First product rule
    lhs = delop(f * g, doit=True)
    rhs = (f * delop(g) + g * delop(f)).doit()
    assert simplify(lhs) == simplify(rhs)

    # Second product rule
    lhs = delop(u & v).doit()
    rhs = ((u ^ (delop ^ v)) + (v ^ (delop ^ u)) + ((u & delop)(v)) +
           ((v & delop)(u))).doit()
    assert simplify(lhs) == simplify(rhs)

    # Third product rule
    lhs = (delop & (f * v)).doit()
    rhs = ((f * (delop & v)) + (v & (delop(f)))).doit()
    assert simplify(lhs) == simplify(rhs)

    # Fourth product rule
    lhs = (delop & (u ^ v)).doit()
    rhs = ((v & (delop ^ u)) - (u & (delop ^ v))).doit()
    assert simplify(lhs) == simplify(rhs)

    # Fifth product rule
    lhs = (delop ^ (f * v)).doit()
    rhs = (((delop(f)) ^ v) + (f * (delop ^ v))).doit()
    assert simplify(lhs) == simplify(rhs)

    # Sixth product rule
    lhs = (delop ^ (u ^ v)).doit()
    rhs = ((u * (delop & v) - v * (delop & u) + (v & delop)(u) -
            (u & delop)(v))).doit()
    assert simplify(lhs) == simplify(rhs)
示例#22
0
    def tangent_lines(self, p):
        """Tangent lines between `p` and the ellipse.

        If `p` is on the ellipse, returns the tangent line through point `p`.
        Otherwise, returns the tangent line(s) from `p` to the ellipse, or
        None if no tangent line is possible (e.g., `p` inside ellipse).

        Parameters
        ==========

        p : Point

        Returns
        =======

        tangent_lines : list with 1 or 2 Lines

        Raises
        ======

        NotImplementedError
            Can only find tangent lines for a point, `p`, on the ellipse.

        See Also
        ========

        diofant.geometry.point.Point, diofant.geometry.line.Line

        Examples
        ========

        >>> from diofant import Point, Ellipse
        >>> e1 = Ellipse(Point(0, 0), 3, 2)
        >>> e1.tangent_lines(Point(3, 0))
        [Line(Point2D(3, 0), Point2D(3, -12))]
        """
        p = Point(p)
        if self.encloses_point(p):
            return []

        if p in self:
            delta = self.center - p
            rise = (self.vradius**2) * delta.x
            run = -(self.hradius**2) * delta.y
            p2 = Point(simplify(p.x + run), simplify(p.y + rise))
            return [Line(p, p2)]
        else:
            if len(self.foci) == 2:
                f1, f2 = self.foci
                maj = self.hradius
                test = (2 * maj - Point.distance(f1, p) -
                        Point.distance(f2, p))
            else:
                test = self.radius - Point.distance(self.center, p)
            if test.is_number and test.is_positive:
                return []
            # else p is outside the ellipse or we can't tell. In case of the
            # latter, the solutions returned will only be valid if
            # the point is not inside the ellipse; if it is, nan will result.
            x, y = Dummy('x'), Dummy('y')
            eq = self.equation(x, y)
            dydx = idiff(eq, y, x)
            slope = Line(p, Point(x, y)).slope
            tangent_points = solve([slope - dydx, eq], [x, y])

            # handle horizontal and vertical tangent lines
            if len(tangent_points) == 1:
                assert tangent_points[0][0] == p.x or tangent_points[0][
                    1] == p.y
                return [Line(p, p + Point(1, 0)), Line(p, p + Point(0, 1))]

            # others
            return [Line(p, tangent_points[0]), Line(p, tangent_points[1])]
示例#23
0
def test_product_rules():
    """
    Tests the six product rules defined with respect to the Del
    operator

    References
    ==========

    * https//en.wikipedia.org/wiki/Del

    """

    # Define the scalar and vector functions
    f = 2*x*y*z
    g = x*y + y*z + z*x
    u = x**2*i + 4*j - y**2*z*k
    v = 4*i + x*y*z*k

    # First product rule
    lhs = delop(f * g, doit=True)
    rhs = (f * delop(g) + g * delop(f)).doit()
    assert simplify(lhs) == simplify(rhs)

    # Second product rule
    lhs = delop(u & v).doit()
    rhs = ((u ^ (delop ^ v)) + (v ^ (delop ^ u)) +
           ((u & delop)(v)) + ((v & delop)(u))).doit()
    assert simplify(lhs) == simplify(rhs)

    # Third product rule
    lhs = (delop & (f*v)).doit()
    rhs = ((f * (delop & v)) + (v & (delop(f)))).doit()
    assert simplify(lhs) == simplify(rhs)

    # Fourth product rule
    lhs = (delop & (u ^ v)).doit()
    rhs = ((v & (delop ^ u)) - (u & (delop ^ v))).doit()
    assert simplify(lhs) == simplify(rhs)

    # Fifth product rule
    lhs = (delop ^ (f * v)).doit()
    rhs = (((delop(f)) ^ v) + (f * (delop ^ v))).doit()
    assert simplify(lhs) == simplify(rhs)

    # Sixth product rule
    lhs = (delop ^ (u ^ v)).doit()
    rhs = ((u * (delop & v) - v * (delop & u) +
            (v & delop)(u) - (u & delop)(v))).doit()
    assert simplify(lhs) == simplify(rhs)
示例#24
0
    def intersection(self, o):
        """The intersection of this circle with another geometrical entity.

        Parameters
        ==========

        o : GeometryEntity

        Returns
        =======

        intersection : list of GeometryEntities

        Examples
        ========

        >>> from diofant import Point, Circle, Line, Ray
        >>> p1, p2, p3 = Point(0, 0), Point(5, 5), Point(6, 0)
        >>> p4 = Point(5, 0)
        >>> c1 = Circle(p1, 5)
        >>> c1.intersection(p2)
        []
        >>> c1.intersection(p4)
        [Point2D(5, 0)]
        >>> c1.intersection(Ray(p1, p2))
        [Point2D(5*sqrt(2)/2, 5*sqrt(2)/2)]
        >>> c1.intersection(Line(p2, p3))
        []

        """
        if isinstance(o, Circle):
            if o.center == self.center:
                if o.radius == self.radius:
                    return o
                return []
            dx, dy = (o.center - self.center).args
            d = sqrt(simplify(dy**2 + dx**2))
            R = o.radius + self.radius
            if d > R or d < abs(self.radius - o.radius):
                return []

            a = simplify((self.radius**2 - o.radius**2 + d**2) / (2 * d))

            x2 = self.center.x + (dx * a / d)
            y2 = self.center.y + (dy * a / d)

            h = sqrt(simplify(self.radius**2 - a**2))
            rx = -dy * (h / d)
            ry = dx * (h / d)

            xi_1 = simplify(x2 + rx)
            xi_2 = simplify(x2 - rx)
            yi_1 = simplify(y2 + ry)
            yi_2 = simplify(y2 - ry)

            ret = [Point(xi_1, yi_1)]
            if xi_1 != xi_2 or yi_1 != yi_2:
                ret.append(Point(xi_2, yi_2))
            return ret

        return Ellipse.intersection(self, o)
示例#25
0
def rsolve_ratio(coeffs, f, n, **hints):
    """
    Given linear recurrence operator `\operatorname{L}` of order `k`
    with polynomial coefficients and inhomogeneous equation
    `\operatorname{L} y = f`, where `f` is a polynomial, we seek
    for all rational solutions over field `K` of characteristic zero.

    This procedure accepts only polynomials, however if you are
    interested in solving recurrence with rational coefficients
    then use ``rsolve`` which will pre-process the given equation
    and run this procedure with polynomial arguments.

    The algorithm performs two basic steps:

        (1) Compute polynomial `v(n)` which can be used as universal
            denominator of any rational solution of equation
            `\operatorname{L} y = f`.

        (2) Construct new linear difference equation by substitution
            `y(n) = u(n)/v(n)` and solve it for `u(n)` finding all its
            polynomial solutions. Return ``None`` if none were found.

    Algorithm implemented here is a revised version of the original
    Abramov's algorithm, developed in 1989. The new approach is much
    simpler to implement and has better overall efficiency. This
    method can be easily adapted to q-difference equations case.

    Besides finding rational solutions alone, this functions is
    an important part of Hyper algorithm were it is used to find
    particular solution of inhomogeneous part of a recurrence.

    Examples
    ========

    >>> from diofant.abc import x
    >>> from diofant.solvers.recurr import rsolve_ratio
    >>> rsolve_ratio([-2*x**3 + x**2 + 2*x - 1, 2*x**3 + x**2 - 6*x,
    ... - 2*x**3 - 11*x**2 - 18*x - 9, 2*x**3 + 13*x**2 + 22*x + 8], 0, x)
    C2*(2*x - 3)/(2*(x**2 - 1))

    References
    ==========

    .. [1] S. A. Abramov, Rational solutions of linear difference
           and q-difference equations with polynomial coefficients,
           in: T. Levelt, ed., Proc. ISSAC '95, ACM Press, New York,
           1995, 285-289

    See Also
    ========

    rsolve_hyper
    """
    f = sympify(f)

    if not f.is_polynomial(n):
        return

    coeffs = list(map(sympify, coeffs))

    r = len(coeffs) - 1

    A, B = coeffs[r], coeffs[0]
    A = A.subs(n, n - r).expand()

    h = Dummy('h')

    res = resultant(A, B.subs(n, n + h), n)

    if not res.is_polynomial(h):
        p, q = res.as_numer_denom()
        res = quo(p, q, h)

    nni_roots = list(
        roots(res, h, filter='Z', predicate=lambda r: r >= 0).keys())

    if not nni_roots:
        return rsolve_poly(coeffs, f, n, **hints)
    else:
        C, numers = S.One, [S.Zero] * (r + 1)

        for i in range(int(max(nni_roots)), -1, -1):
            d = gcd(A, B.subs(n, n + i), n)

            A = quo(A, d, n)
            B = quo(B, d.subs(n, n - i), n)

            C *= Mul(*[d.subs(n, n - j) for j in range(0, i + 1)])

        denoms = [C.subs(n, n + i) for i in range(0, r + 1)]

        for i in range(0, r + 1):
            g = gcd(coeffs[i], denoms[i], n)

            numers[i] = quo(coeffs[i], g, n)
            denoms[i] = quo(denoms[i], g, n)

        for i in range(0, r + 1):
            numers[i] *= Mul(*(denoms[:i] + denoms[i + 1:]))

        result = rsolve_poly(numers, f * Mul(*denoms), n, **hints)

        if result is not None:
            if hints.get('symbols', False):
                return simplify(result[0] / C), result[1]
            else:
                return simplify(result / C)
        else:
            return
示例#26
0
def test_matmul_simplify():
    A = MatrixSymbol('A', 1, 1)
    assert simplify(MatMul(A, ImmutableMatrix([[sin(x)**2 + cos(x)**2]]))) == \
        MatMul(A, ImmutableMatrix([[1]]))
示例#27
0
def rsolve(f, y, init=None):
    """
    Solve univariate recurrence with rational coefficients.

    Given `k`-th order linear recurrence `\operatorname{L} y = f`,
    or equivalently:

    .. math:: a_{k}(n) y(n+k) + a_{k-1}(n) y(n+k-1) +
              \ldots + a_{0}(n) y(n) = f(n)

    where `a_{i}(n)`, for `i=0, \ldots, k`, are polynomials or rational
    functions in `n`, and `f` is a hypergeometric function or a sum
    of a fixed number of pairwise dissimilar hypergeometric terms in
    `n`, finds all solutions or returns ``None``, if none were found.

    Initial conditions can be given as a dictionary in two forms:

        (1) ``{   n_0  : v_0,   n_1  : v_1, ...,   n_m  : v_m }``
        (2) ``{ y(n_0) : v_0, y(n_1) : v_1, ..., y(n_m) : v_m }``

    or as a list ``L`` of values:

        ``L = [ v_0, v_1, ..., v_m ]``

    where ``L[i] = v_i``, for `i=0, \ldots, m`, maps to `y(n_i)`.

    Examples
    ========

    Lets consider the following recurrence:

    .. math:: (n - 1) y(n + 2) - (n^2 + 3 n - 2) y(n + 1) +
              2 n (n + 1) y(n) = 0

    >>> from diofant import Function, rsolve
    >>> from diofant.abc import n
    >>> y = Function('y')

    >>> f = (n - 1)*y(n + 2) - (n**2 + 3*n - 2)*y(n + 1) + 2*n*(n + 1)*y(n)

    >>> rsolve(f, y(n))
    2**n*C0 + C1*factorial(n)

    >>> rsolve(f, y(n), { y(0):0, y(1):3 })
    3*2**n - 3*factorial(n)

    See Also
    ========

    rsolve_poly, rsolve_ratio, rsolve_hyper

    """
    if isinstance(f, Equality):
        f = f.lhs - f.rhs
    f = f.expand()

    n = y.args[0]

    h_part = defaultdict(lambda: S.Zero)
    i_part = S.Zero

    for h, c in f.collect(y.func(Wild('n')), evaluate=False).items():
        if h.func == y.func:
            k = Wild('k', exclude=(n, ))
            r = h.args[0].match(n + k)
            if r:
                c = simplify(c)
                if not c.is_rational_function(n):
                    raise ValueError(
                        "Rational function of '%s' expected, got '%s'" %
                        (n, c))
                h_part[int(r[k])] = c
            else:
                raise ValueError("'%s(%s + Integer)' expected, got '%s'" %
                                 (y.func, n, h))
        else:
            i_term = h * c
            if i_term.find(y.func(Wild('k'))):
                raise ValueError(
                    "Linear recurrence for '%s' expected, got '%s'" %
                    (y.func, f))
            i_part -= i_term

    if not i_part.is_rational_function(n):
        raise ValueError(
            "Inhomogeneous part should be a rational function of '%s', got '%s'"
            % (n, i_part))

    k_min, k_max = min(h_part.keys()), max(h_part.keys())

    if k_min < 0:
        return rsolve(f.subs(n, n + abs(k_min)), y, init)

    i_numer, i_denom = i_part.as_numer_denom()

    common = lcm_list([x.as_numer_denom()[1]
                       for x in h_part.values()] + [i_denom])

    if common is not S.One:
        for k, coeff in h_part.items():
            numer, denom = coeff.as_numer_denom()
            h_part[k] = numer * quo(common, denom, n)

        i_part = i_numer * quo(common, i_denom, n)

    coeffs = [h_part[i] for i in range(k_max + 1)]

    result = rsolve_hyper(coeffs, i_part, n, symbols=True)

    if result is None:
        return

    solution, symbols = result

    if init == {} or init == []:
        init = None

    if symbols and init is not None:
        if type(init) is list:
            init = {i: init[i] for i in range(len(init))}

        equations = []

        for k, v in init.items():
            try:
                i = int(k)
            except TypeError:
                if k.is_Function and k.func == y.func:
                    i = int(k.args[0])
                else:
                    raise ValueError(
                        "Integer or term '%s(Integer)' expected, got '%s'" %
                        (y.func, k))
            try:
                eq = solution.limit(n, i) - v
            except NotImplementedError:
                eq = solution.subs(n, i) - v
            equations.append(eq)

        result = solve(equations, *symbols)

        if not result:
            return
        else:
            solution = solution.subs(result)

    return solution
示例#28
0
def test_del_operator():
    pytest.raises(TypeError, lambda: Del(Integer(1)))

    # Tests for curl
    assert (delop ^ Vector.zero ==
            (Derivative(0, C.y) - Derivative(0, C.z))*C.i +
            (-Derivative(0, C.x) + Derivative(0, C.z))*C.j +
            (Derivative(0, C.x) - Derivative(0, C.y))*C.k)
    assert ((delop ^ Vector.zero).doit() == Vector.zero ==
            curl(Vector.zero, C))
    assert delop.cross(Vector.zero) == delop ^ Vector.zero
    assert (delop ^ i).doit() == Vector.zero
    assert delop.cross(2*y**2*j, doit=True) == Vector.zero
    assert delop.cross(2*y**2*j) == delop ^ 2*y**2*j
    v = x*y*z * (i + j + k)
    assert ((delop ^ v).doit() ==
            (-x*y + x*z)*i + (x*y - y*z)*j + (-x*z + y*z)*k ==
            curl(v, C))
    assert delop ^ v == delop.cross(v)
    assert (delop.cross(2*x**2*j) ==
            (Derivative(0, C.y) - Derivative(2*C.x**2, C.z))*C.i +
            (-Derivative(0, C.x) + Derivative(0, C.z))*C.j +
            (-Derivative(0, C.y) + Derivative(2*C.x**2, C.x))*C.k)
    assert (delop.cross(2*x**2*j, doit=True) == 4*x*k ==
            curl(2*x**2*j, C))

    # Tests for divergence
    assert delop & Vector.zero == Integer(0) == divergence(Vector.zero, C)
    assert (delop & Vector.zero).doit() == Integer(0)
    assert delop.dot(Vector.zero) == delop & Vector.zero
    assert (delop & i).doit() == Integer(0)
    assert (delop & x**2*i).doit() == 2*x == divergence(x**2*i, C)
    assert (delop.dot(v, doit=True) == x*y + y*z + z*x ==
            divergence(v, C))
    assert delop & v == delop.dot(v)
    assert delop.dot(1/(x*y*z) * (i + j + k), doit=True) == \
        - 1 / (x*y*z**2) - 1 / (x*y**2*z) - 1 / (x**2*y*z)
    v = x*i + y*j + z*k
    assert (delop & v == Derivative(C.x, C.x) +
            Derivative(C.y, C.y) + Derivative(C.z, C.z))
    assert delop.dot(v, doit=True) == 3 == divergence(v, C)
    assert delop & v == delop.dot(v)
    assert simplify((delop & v).doit()) == 3

    # Tests for gradient
    assert (delop.gradient(0, doit=True) == Vector.zero ==
            gradient(0, C))
    assert delop.gradient(0) == delop(0)
    assert (delop(Integer(0))).doit() == Vector.zero
    assert (delop(x) == (Derivative(C.x, C.x))*C.i +
            (Derivative(C.x, C.y))*C.j + (Derivative(C.x, C.z))*C.k)
    assert (delop(x)).doit() == i == gradient(x, C)
    assert (delop(x*y*z) ==
            (Derivative(C.x*C.y*C.z, C.x))*C.i +
            (Derivative(C.x*C.y*C.z, C.y))*C.j +
            (Derivative(C.x*C.y*C.z, C.z))*C.k)
    assert (delop.gradient(x*y*z, doit=True) ==
            y*z*i + z*x*j + x*y*k ==
            gradient(x*y*z, C))
    assert delop(x*y*z) == delop.gradient(x*y*z)
    assert (delop(2*x**2)).doit() == 4*x*i
    assert ((delop(a*sin(y) / x)).doit() ==
            -a*sin(y)/x**2 * i + a*cos(y)/x * j)

    # Tests for directional derivative
    assert (Vector.zero & delop)(a) == Integer(0)
    assert ((Vector.zero & delop)(a)).doit() == Integer(0)
    assert ((v & delop)(Vector.zero)).doit() == Vector.zero
    assert ((v & delop)(Integer(0))).doit() == Integer(0)
    assert ((i & delop)(x)).doit() == 1
    assert ((j & delop)(y)).doit() == 1
    assert ((k & delop)(z)).doit() == 1
    assert ((i & delop)(x*y*z)).doit() == y*z
    assert ((v & delop)(x)).doit() == x
    assert ((v & delop)(x*y*z)).doit() == 3*x*y*z
    assert (v & delop)(x + y + z) == C.x + C.y + C.z
    assert ((v & delop)(x + y + z)).doit() == x + y + z
    assert ((v & delop)(v)).doit() == v
    assert ((i & delop)(v)).doit() == i
    assert ((j & delop)(v)).doit() == j
    assert ((k & delop)(v)).doit() == k
    assert ((v & delop)(Vector.zero)).doit() == Vector.zero
示例#29
0
 def _simplify(expr):
     if dom.is_Composite:
         return factor(expr)
     else:
         return simplify(expr)
示例#30
0
 def __div__(self, divisor):
     """Divide point's coordinates by a factor."""
     divisor = sympify(divisor)
     return Point([simplify(x/divisor) for x in self.args])
示例#31
0
 def __mul__(self, factor):
     """Multiply point's coordinates by a factor."""
     factor = sympify(factor)
     return Point([simplify(x*factor) for x in self.args])
示例#32
0
def test_matmul_simplify():
    A = MatrixSymbol('A', 1, 1)
    assert simplify(MatMul(A, ImmutableMatrix([[sin(x)**2 + cos(x)**2]]))) == \
        MatMul(A, ImmutableMatrix([[1]]))
示例#33
0
def test_diofantissue_469():
    A = MatrixSymbol("A", n, n)
    B = MatrixSymbol("B", n, n)
    expr = Eq(A, B)
    assert simplify(expr) == expr
示例#34
0
 def _eval_simplify(self, **kwargs):
     if self.is_Atom:
         return self
     else:
         return self.__class__(*[simplify(x, **kwargs) for x in self.args])
示例#35
0
def test_diofantissue_469():
    A = MatrixSymbol("A", n, n)
    B = MatrixSymbol("B", n, n)
    expr = Eq(A, B)
    assert simplify(expr) == expr
示例#36
0
def rsolve_hyper(coeffs, f, n, **hints):
    """
    Given linear recurrence operator `\operatorname{L}` of order `k`
    with polynomial coefficients and inhomogeneous equation
    `\operatorname{L} y = f` we seek for all hypergeometric solutions
    over field `K` of characteristic zero.

    The inhomogeneous part can be either hypergeometric or a sum
    of a fixed number of pairwise dissimilar hypergeometric terms.

    The algorithm performs three basic steps:

        (1) Group together similar hypergeometric terms in the
            inhomogeneous part of `\operatorname{L} y = f`, and find
            particular solution using Abramov's algorithm.

        (2) Compute generating set of `\operatorname{L}` and find basis
            in it, so that all solutions are linearly independent.

        (3) Form final solution with the number of arbitrary
            constants equal to dimension of basis of `\operatorname{L}`.

    Term `a(n)` is hypergeometric if it is annihilated by first order
    linear difference equations with polynomial coefficients or, in
    simpler words, if consecutive term ratio is a rational function.

    The output of this procedure is a linear combination of fixed
    number of hypergeometric terms. However the underlying method
    can generate larger class of solutions - D'Alembertian terms.

    Note also that this method not only computes the kernel of the
    inhomogeneous equation, but also reduces in to a basis so that
    solutions generated by this procedure are linearly independent

    Examples
    ========

    >>> from diofant.solvers import rsolve_hyper
    >>> from diofant.abc import x

    >>> rsolve_hyper([-1, -1, 1], 0, x)
    C0*(1/2 + sqrt(5)/2)**x + C1*(-sqrt(5)/2 + 1/2)**x

    >>> rsolve_hyper([-1, 1], 1 + x, x)
    C0 + x*(x + 1)/2

    References
    ==========

    .. [1] M. Petkovšek, Hypergeometric solutions of linear recurrences
           with polynomial coefficients, J. Symbolic Computation,
           14 (1992), 243-264.

    .. [2] M. Petkovšek, H. S. Wilf, D. Zeilberger, A = B, 1996.
    """
    coeffs = list(map(sympify, coeffs))

    f = sympify(f)

    r, kernel, symbols = len(coeffs) - 1, [], set()

    if not f.is_zero:
        if f.is_Add:
            similar = {}

            for g in f.expand().args:
                if not g.is_hypergeometric(n):
                    return

                for h in similar.keys():
                    if hypersimilar(g, h, n):
                        similar[h] += g
                        break
                else:
                    similar[g] = S.Zero

            inhomogeneous = []

            for g, h in similar.items():
                inhomogeneous.append(g + h)
        elif f.is_hypergeometric(n):
            inhomogeneous = [f]
        else:
            return

        for i, g in enumerate(inhomogeneous):
            coeff, polys = S.One, coeffs[:]
            denoms = [S.One] * (r + 1)

            s = hypersimp(g, n)

            for j in range(1, r + 1):
                coeff *= s.subs(n, n + j - 1)

                p, q = coeff.as_numer_denom()

                polys[j] *= p
                denoms[j] = q

            for j in range(0, r + 1):
                polys[j] *= Mul(*(denoms[:j] + denoms[j + 1:]))

            R = rsolve_ratio(polys, Mul(*denoms), n, symbols=True)
            if R is not None:
                R, syms = R
                if syms:
                    R = R.subs(zip(syms, [0] * len(syms)))

            if R:
                inhomogeneous[i] *= R
            else:
                return

            result = Add(*inhomogeneous)
            result = simplify(result)
    else:
        result = S.Zero

    Z = Dummy('Z')

    p, q = coeffs[0], coeffs[r].subs(n, n - r + 1)

    p_factors = [z for z in roots(p, n).keys()]
    q_factors = [z for z in roots(q, n).keys()]

    factors = [(S.One, S.One)]

    for p in p_factors:
        for q in q_factors:
            if p.is_integer and q.is_integer and p <= q:
                continue
            else:
                factors += [(n - p, n - q)]

    p = [(n - p, S.One) for p in p_factors]
    q = [(S.One, n - q) for q in q_factors]

    factors = p + factors + q

    for A, B in factors:
        polys, degrees = [], []
        D = A * B.subs(n, n + r - 1)

        for i in range(0, r + 1):
            a = Mul(*[A.subs(n, n + j) for j in range(0, i)])
            b = Mul(*[B.subs(n, n + j) for j in range(i, r)])

            poly = quo(coeffs[i] * a * b, D, n)
            polys.append(poly.as_poly(n))

            if not poly.is_zero:
                degrees.append(polys[i].degree())

        d, poly = max(degrees), S.Zero

        for i in range(0, r + 1):
            coeff = polys[i].nth(d)

            if coeff is not S.Zero:
                poly += coeff * Z**i

        for z in roots(poly, Z).keys():
            if z.is_zero:
                continue

            (C, s) = rsolve_poly([polys[i] * z**i for i in range(r + 1)],
                                 0,
                                 n,
                                 symbols=True)

            if C is not None and C is not S.Zero:
                symbols |= set(s)

                ratio = z * A * C.subs(n, n + 1) / B / C
                ratio = simplify(ratio)

                skip = max([-1] + [
                    v for v in roots(Mul(*ratio.as_numer_denom()), n).keys()
                    if v.is_Integer
                ]) + 1
                K = product(ratio, (n, skip, n - 1))

                if K.has(factorial, FallingFactorial, RisingFactorial):
                    K = simplify(K)

                if casoratian(kernel + [K], n, zero=False) != 0:
                    kernel.append(K)

    kernel.sort(key=default_sort_key)
    sk = list(zip(numbered_symbols('C'), kernel))

    for C, ker in sk:
        result += C * ker

    if hints.get('symbols', False):
        symbols |= {s for s, k in sk}
        return result, list(symbols)
    else:
        return result