Esempio n. 1
0
def test_to_Sequence():
    x = symbols('x')
    R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
    n = symbols('n', integer=True)
    _, Sn = RecurrenceOperators(ZZ.old_poly_ring(n), 'Sn')
    p = HolonomicFunction(x**2 * Dx**4 + x + Dx, x).to_sequence()
    q = [(HolonomicSequence(1 + (n + 2) * Sn**2 +
                            (n**4 + 6 * n**3 + 11 * n**2 + 6 * n) * Sn**3), 0,
          1)]
    assert p == q
    p = HolonomicFunction(x**2 * Dx**4 + x**3 + Dx**2, x).to_sequence()
    q = [
        (HolonomicSequence(1 + (n**4 + 14 * n**3 + 72 * n**2 + 163 * n + 140) *
                           Sn**5), 0, 0)
    ]
    assert p == q
    p = HolonomicFunction(x**3 * Dx**4 + 1 + Dx**2, x).to_sequence()
    q = [(HolonomicSequence(1 + (n**4 - 2 * n**3 - n**2 + 2 * n) * Sn +
                            (n**2 + 3 * n + 2) * Sn**2), 0, 0)]
    assert p == q
    p = HolonomicFunction(3 * x**3 * Dx**4 + 2 * x * Dx + x * Dx**3,
                          x).to_sequence()
    q = [(HolonomicSequence(2 * n +
                            (3 * n**4 - 6 * n**3 - 3 * n**2 + 6 * n) * Sn +
                            (n**3 + 3 * n**2 + 2 * n) * Sn**2), 0, 1)]
    assert p == q
Esempio n. 2
0
def hermite_normal_form(A, *, D=None, check_rank=False):
    r"""
    Compute the Hermite Normal Form of a Matrix *A* of integers.

    Examples
    ========

    >>> from sympy import Matrix
    >>> from sympy.matrices.normalforms import hermite_normal_form
    >>> m = Matrix([[12, 6, 4], [3, 9, 6], [2, 16, 14]])
    >>> print(hermite_normal_form(m))
    Matrix([[10, 0, 2], [0, 15, 3], [0, 0, 2]])

    Parameters
    ==========

    A : $m \times n$ ``Matrix`` of integers.

    D : int, optional
        Let $W$ be the HNF of *A*. If known in advance, a positive integer *D*
        being any multiple of $\det(W)$ may be provided. In this case, if *A*
        also has rank $m$, then we may use an alternative algorithm that works
        mod *D* in order to prevent coefficient explosion.

    check_rank : boolean, optional (default=False)
        The basic assumption is that, if you pass a value for *D*, then
        you already believe that *A* has rank $m$, so we do not waste time
        checking it for you. If you do want this to be checked (and the
        ordinary, non-modulo *D* algorithm to be used if the check fails), then
        set *check_rank* to ``True``.

    Returns
    =======

    ``Matrix``
        The HNF of matrix *A*.

    Raises
    ======

    DMDomainError
        If the domain of the matrix is not :ref:`ZZ`.

    DMShapeError
        If the mod *D* algorithm is used but the matrix has more rows than
        columns.

    References
    ==========

    .. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.*
       (See Algorithms 2.4.5 and 2.4.8.)

    """
    # Accept any of Python int, SymPy Integer, and ZZ itself:
    if D is not None and not ZZ.of_type(D):
        D = ZZ(int(D))
    return _hnf(A._rep, D=D, check_rank=check_rank).to_Matrix()
Esempio n. 3
0
def test_QuotientRing():
    I = QQ.old_poly_ring(x).ideal(x**2 + 1)
    R = QQ.old_poly_ring(x) / I

    assert R == QQ.old_poly_ring(x) / [x**2 + 1]
    assert R == QQ.old_poly_ring(x) / QQ.old_poly_ring(x).ideal(x**2 + 1)
    assert R != QQ.old_poly_ring(x)

    assert R.convert(1) / x == -x + I
    assert -1 + I == x**2 + I
    assert R.convert(ZZ(1), ZZ) == 1 + I
    assert R.convert(R.convert(x), R) == R.convert(x)

    X = R.convert(x)
    Y = QQ.old_poly_ring(x).convert(x)
    assert -1 + I == X**2 + I
    assert -1 + I == Y**2 + I
    assert R.to_sympy(X) == x

    raises(ValueError,
           lambda: QQ.old_poly_ring(x) / QQ.old_poly_ring(x, y).ideal(x))

    R = QQ.old_poly_ring(x, order="ilex")
    I = R.ideal(x)
    assert R.convert(1) + I == (R / I).convert(1)
Esempio n. 4
0
 def denom(self, a):
     """Get the denominator of ``a``."""
     ZZ = self.dom.get_ring()
     QQ = self.dom
     ZZ_I = self.get_ring()
     denom_ZZ = ZZ.lcm(QQ.denom(a.x), QQ.denom(a.y))
     return ZZ_I(denom_ZZ, ZZ.zero)
Esempio n. 5
0
def test_to_expr():
    x = symbols('x')
    R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
    p = HolonomicFunction(Dx - 1, x, 0, [1]).to_expr()
    q = exp(x)
    assert p == q
    p = HolonomicFunction(Dx**2 + 1, x, 0, [1, 0]).to_expr()
    q = cos(x)
    assert p == q
    p = HolonomicFunction(Dx**2 - 1, x, 0, [1, 0]).to_expr()
    q = cosh(x)
    assert p == q
    p = HolonomicFunction(2 + (4*x - 1)*Dx + \
        (x**2 - x)*Dx**2, x, 0, [1, 2]).to_expr().expand()
    q = 1 / (x**2 - 2 * x + 1)
    assert p == q
    p = expr_to_holonomic(sin(x)**2 / x).integrate((x, 0, x)).to_expr()
    q = (sin(x)**2 / x).integrate((x, 0, x))
    assert p == q
    C_0, C_1, C_2, C_3 = symbols('C_0, C_1, C_2, C_3')
    p = expr_to_holonomic(log(1 + x**2)).to_expr()
    q = C_2 * log(x**2 + 1)
    assert p == q
    p = expr_to_holonomic(log(1 + x**2)).diff().to_expr()
    q = C_0 * x / (x**2 + 1)
    assert p == q
    p = expr_to_holonomic(erf(x) + x).to_expr()
    q = 3 * C_3 * x - 3 * sqrt(pi) * C_3 * erf(x) / 2 + x + 2 * x / sqrt(pi)
    assert p == q
    p = expr_to_holonomic(sqrt(x), x0=1).to_expr()
    assert p == sqrt(x)
    assert expr_to_holonomic(sqrt(x)).to_expr() == sqrt(x)
    p = expr_to_holonomic(sqrt(1 + x**2)).to_expr()
    assert p == sqrt(1 + x**2)
    p = expr_to_holonomic((2 * x**2 + 1)**Rational(2, 3)).to_expr()
    assert p == (2 * x**2 + 1)**Rational(2, 3)
    p = expr_to_holonomic(sqrt(-x**2 + 2 * x)).to_expr()
    assert p == sqrt(x) * sqrt(-x + 2)
    p = expr_to_holonomic((-2 * x**3 + 7 * x)**Rational(2, 3)).to_expr()
    q = x**Rational(2, 3) * (-2 * x**2 + 7)**Rational(2, 3)
    assert p == q
    p = from_hyper(hyper((-2, -3), (S.Half, ), x))
    s = hyperexpand(hyper((-2, -3), (S.Half, ), x))
    D_0 = Symbol('D_0')
    C_0 = Symbol('C_0')
    assert (p.to_expr().subs({C_0: 1, D_0: 0}) - s).simplify() == 0
    p.y0 = {0: [1], S.Half: [0]}
    assert p.to_expr() == s
    assert expr_to_holonomic(x**5).to_expr() == x**5
    assert expr_to_holonomic(2*x**3-3*x**2).to_expr().expand() == \
        2*x**3-3*x**2
    a = symbols("a")
    p = (expr_to_holonomic(1.4 * x) * expr_to_holonomic(a * x, x)).to_expr()
    q = 1.4 * a * x**2
    assert p == q
    p = (expr_to_holonomic(1.4 * x) + expr_to_holonomic(a * x, x)).to_expr()
    q = x * (a + 1.4)
    assert p == q
    p = (expr_to_holonomic(1.4 * x) + expr_to_holonomic(x)).to_expr()
    assert p == 2.4 * x
Esempio n. 6
0
def test_HolonomicFunction_addition():
    x = symbols('x')
    R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
    p = HolonomicFunction(Dx**2 * x, x)
    q = HolonomicFunction((2) * Dx + (x) * Dx**2, x)
    assert p == q
    p = HolonomicFunction(x * Dx + 1, x)
    q = HolonomicFunction(Dx + 1, x)
    r = HolonomicFunction((x - 2) + (x**2 - 2) * Dx + (x**2 - x) * Dx**2, x)
    assert p + q == r
    p = HolonomicFunction(x * Dx + Dx**2 * (x**2 + 2), x)
    q = HolonomicFunction(Dx - 3, x)
    r = HolonomicFunction((-54 * x**2 - 126 * x - 150) + (-135 * x**3 - 252 * x**2 - 270 * x + 140) * Dx +\
                 (-27 * x**4 - 24 * x**2 + 14 * x - 150) * Dx**2 + \
                 (9 * x**4 + 15 * x**3 + 38 * x**2 + 30 * x +40) * Dx**3, x)
    assert p + q == r
    p = HolonomicFunction(Dx**5 - 1, x)
    q = HolonomicFunction(x**3 + Dx, x)
    r = HolonomicFunction((-x**18 + 45*x**14 - 525*x**10 + 1575*x**6 - x**3 - 630*x**2) + \
        (-x**15 + 30*x**11 - 195*x**7 + 210*x**3 - 1)*Dx + (x**18 - 45*x**14 + 525*x**10 - \
        1575*x**6 + x**3 + 630*x**2)*Dx**5 + (x**15 - 30*x**11 + 195*x**7 - 210*x**3 + \
        1)*Dx**6, x)
    assert p + q == r

    p = x**2 + 3 * x + 8
    q = x**3 - 7 * x + 5
    p = p * Dx - p.diff()
    q = q * Dx - q.diff()
    r = HolonomicFunction(p, x) + HolonomicFunction(q, x)
    s = HolonomicFunction((6*x**2 + 18*x + 14) + (-4*x**3 - 18*x**2 - 62*x + 10)*Dx +\
        (x**4 + 6*x**3 + 31*x**2 - 10*x - 71)*Dx**2, x)
    assert r == s
Esempio n. 7
0
def test_pickling_polys_polyclasses():
    from sympy.polys.polyclasses import DMP, DMF, ANP

    for c in (DMP, DMP([[ZZ(1)], [ZZ(2)], [ZZ(3)]], ZZ)):
        check(c)
    for c in (DMF, DMF(([ZZ(1), ZZ(2)], [ZZ(1), ZZ(3)]), ZZ)):
        check(c)
    for c in (ANP, ANP([QQ(1), QQ(2)], [QQ(1), QQ(2), QQ(3)], QQ)):
        check(c)
Esempio n. 8
0
def test_integrate():
    x = symbols('x')
    R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
    p = expr_to_holonomic(sin(x)**2 / x, x0=1).integrate((x, 2, 3))
    q = '0.166270406994788'
    assert sstr(p) == q
    p = expr_to_holonomic(sin(x)).integrate((x, 0, x)).to_expr()
    q = 1 - cos(x)
    assert p == q
    p = expr_to_holonomic(sin(x)).integrate((x, 0, 3))
    q = 1 - cos(3)
    assert p == q
    p = expr_to_holonomic(sin(x) / x, x0=1).integrate((x, 1, 2))
    q = '0.659329913368450'
    assert sstr(p) == q
    p = expr_to_holonomic(sin(x)**2 / x, x0=1).integrate((x, 1, 0))
    q = '-0.423690480850035'
    assert sstr(p) == q
    p = expr_to_holonomic(sin(x) / x)
    assert p.integrate(x).to_expr() == Si(x)
    assert p.integrate((x, 0, 2)) == Si(2)
    p = expr_to_holonomic(sin(x)**2 / x)
    q = p.to_expr()
    assert p.integrate(x).to_expr() == q.integrate((x, 0, x))
    assert p.integrate((x, 0, 1)) == q.integrate((x, 0, 1))
    assert expr_to_holonomic(1 / x, x0=1).integrate(x).to_expr() == log(x)
    p = expr_to_holonomic((x + 1)**3 * exp(-x), x0=-1).integrate(x).to_expr()
    q = (-x**3 - 6 * x**2 - 15 * x + 6 * exp(x + 1) - 16) * exp(-x)
    assert p == q
    p = expr_to_holonomic(cos(x)**2 / x**2, y0={
        -2: [1, 0, -1]
    }).integrate(x).to_expr()
    q = -Si(2 * x) - cos(x)**2 / x
    assert p == q
    p = expr_to_holonomic(sqrt(x**2 + x)).integrate(x).to_expr()
    q = (x**Rational(3, 2) * (2 * x**2 + 3 * x + 1) -
         x * sqrt(x + 1) * asinh(sqrt(x))) / (4 * x * sqrt(x + 1))
    assert p == q
    p = expr_to_holonomic(sqrt(x**2 + 1)).integrate(x).to_expr()
    q = (sqrt(x**2 + 1)).integrate(x)
    assert (p - q).simplify() == 0
    p = expr_to_holonomic(1 / x**2, y0={-2: [1, 0, 0]})
    r = expr_to_holonomic(1 / x**2, lenics=3)
    assert p == r
    q = expr_to_holonomic(cos(x)**2)
    assert (r * q).integrate(x).to_expr() == -Si(2 * x) - cos(x)**2 / x
Esempio n. 9
0
def is_int(c):
    r"""
    Test whether an argument is of an acceptable type to be used as an integer.

    Explanation
    ===========

    Returns ``True`` on any argument of type ``int`` or :ref:`ZZ`.

    See Also
    ========

    is_rat

    """
    # If gmpy2 is installed then ``ZZ.of_type()`` accepts only
    # ``mpz``, not ``int``, so we need another clause to ensure ``int`` is
    # accepted.
    return isinstance(c, int) or ZZ.of_type(c)
Esempio n. 10
0
def test_series():
    x = symbols('x')
    R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
    p = HolonomicFunction(Dx**2 + 2 * x * Dx, x, 0, [0, 1]).series(n=10)
    q = x - x**3 / 3 + x**5 / 10 - x**7 / 42 + x**9 / 216 + O(x**10)
    assert p == q
    p = HolonomicFunction(Dx - 1, x).composition(x**2, 0, [1])  # e^(x**2)
    q = HolonomicFunction(Dx**2 + 1, x, 0, [1, 0])  # cos(x)
    r = (p * q).series(n=10)  # expansion of cos(x) * exp(x**2)
    s = 1 + x**2 / 2 + x**4 / 24 - 31 * x**6 / 720 - 179 * x**8 / 8064 + O(x**
                                                                           10)
    assert r == s
    t = HolonomicFunction((1 + x) * Dx**2 + Dx, x, 0, [0, 1])  # log(1 + x)
    r = (p * t + q).series(n=10)
    s = 1 + x - x**2 + 4*x**3/3 - 17*x**4/24 + 31*x**5/30 - 481*x**6/720 +\
     71*x**7/105 - 20159*x**8/40320 + 379*x**9/840 + O(x**10)
    assert r == s
    p = HolonomicFunction((6+6*x-3*x**2) - (10*x-3*x**2-3*x**3)*Dx + \
        (4-6*x**3+2*x**4)*Dx**2, x, 0, [0, 1]).series(n=7)
    q = x + x**3 / 6 - 3 * x**4 / 16 + x**5 / 20 - 23 * x**6 / 960 + O(x**7)
    assert p == q
    p = HolonomicFunction((6+6*x-3*x**2) - (10*x-3*x**2-3*x**3)*Dx + \
        (4-6*x**3+2*x**4)*Dx**2, x, 0, [1, 0]).series(n=7)
    q = 1 - 3 * x**2 / 4 - x**3 / 4 - 5 * x**4 / 32 - 3 * x**5 / 40 - 17 * x**6 / 384 + O(
        x**7)
    assert p == q
    p = expr_to_holonomic(erf(x) + x).series(n=10)
    C_3 = symbols('C_3')
    q = (erf(x) + x).series(n=10)
    assert p.subs(C_3, -2 / (3 * sqrt(pi))) == q
    assert expr_to_holonomic(
        sqrt(x**3 + x)).series(n=10) == sqrt(x**3 + x).series(n=10)
    assert expr_to_holonomic((2 * x - 3 * x**2)**Rational(
        1, 3)).series() == ((2 * x - 3 * x**2)**Rational(1, 3)).series()
    assert expr_to_holonomic(sqrt(x**2 - x)).series() == (sqrt(x**2 -
                                                               x)).series()
    assert expr_to_holonomic(cos(x)**2 / x**2, y0={
        -2: [1, 0, -1]
    }).series(n=10) == (cos(x)**2 / x**2).series(n=10)
    assert expr_to_holonomic(cos(x)**2 / x**2, x0=1).series(
        n=10).together() == (cos(x)**2 / x**2).series(n=10, x0=1).together()
    assert expr_to_holonomic(cos(x-1)**2/(x-1)**2, x0=1, y0={-2: [1, 0, -1]}).series(n=10) \
        == (cos(x-1)**2/(x-1)**2).series(x0=1, n=10)
Esempio n. 11
0
def test_diff():
    x, y = symbols('x, y')
    R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
    p = HolonomicFunction(x * Dx**2 + 1, x, 0, [0, 1])
    assert p.diff().to_expr() == p.to_expr().diff().simplify()
    p = HolonomicFunction(Dx**2 - 1, x, 0, [1, 0])
    assert p.diff(x, 2).to_expr() == p.to_expr()
    p = expr_to_holonomic(Si(x))
    assert p.diff().to_expr() == sin(x) / x
    assert p.diff(y) == 0
    C_0, C_1, C_2, C_3 = symbols('C_0, C_1, C_2, C_3')
    q = Si(x)
    assert p.diff(x).to_expr() == q.diff()
    assert p.diff(x, 2).to_expr().subs(C_0, Rational(-1,
                                                     3)).cancel() == q.diff(
                                                         x, 2).cancel()
    assert p.diff(x, 3).series().subs({
        C_3: Rational(-1, 3),
        C_0: 0
    }) == q.diff(x, 3).series()
Esempio n. 12
0
def test_polymatrix_constructor():
    M1 = PolyMatrix([[x, y]], ring=QQ[x,y])
    assert M1.ring == QQ[x,y]
    assert M1.domain == QQ
    assert M1.gens == (x, y)
    assert M1.shape == (1, 2)
    assert M1.rows == 1
    assert M1.cols == 2
    assert len(M1) == 2
    assert list(M1) == [Poly(x, (x, y), domain=QQ), Poly(y, (x, y), domain=QQ)]

    M2 = PolyMatrix([[x, y]], ring=QQ[x][y])
    assert M2.ring == QQ[x][y]
    assert M2.domain == QQ[x]
    assert M2.gens == (y,)
    assert M2.shape == (1, 2)
    assert M2.rows == 1
    assert M2.cols == 2
    assert len(M2) == 2
    assert list(M2) == [Poly(x, (y,), domain=QQ[x]), Poly(y, (y,), domain=QQ[x])]

    assert PolyMatrix([[x, y]], y) == PolyMatrix([[x, y]], ring=ZZ.frac_field(x)[y])
    assert PolyMatrix([[x, y]], ring='ZZ[x,y]') == PolyMatrix([[x, y]], ring=ZZ[x,y])

    assert PolyMatrix([[x, y]], (x, y)) == PolyMatrix([[x, y]], ring=QQ[x,y])
    assert PolyMatrix([[x, y]], x, y) == PolyMatrix([[x, y]], ring=QQ[x,y])
    assert PolyMatrix([x, y]) == PolyMatrix([[x], [y]], ring=QQ[x,y])
    assert PolyMatrix(1, 2, [x, y]) == PolyMatrix([[x, y]], ring=QQ[x,y])
    assert PolyMatrix(1, 2, lambda i,j: [x,y][j]) == PolyMatrix([[x, y]], ring=QQ[x,y])
    assert PolyMatrix(0, 2, [], x, y).shape == (0, 2)
    assert PolyMatrix(2, 0, [], x, y).shape == (2, 0)
    assert PolyMatrix([[], []], x, y).shape == (2, 0)
    assert PolyMatrix(ring=QQ[x,y]) == PolyMatrix(0, 0, [], ring=QQ[x,y]) == PolyMatrix([], ring=QQ[x,y])
    raises(TypeError, lambda: PolyMatrix())
    raises(TypeError, lambda: PolyMatrix(1))

    assert PolyMatrix([Poly(x), Poly(y)]) == PolyMatrix([[x], [y]], ring=ZZ[x,y])

    # XXX: Maybe a bug in parallel_poly_from_expr (x lost from gens and domain):
    assert PolyMatrix([Poly(y, x), 1]) == PolyMatrix([[y], [1]], ring=QQ[y])
Esempio n. 13
0
def is_rat(c):
    r"""
    Test whether an argument is of an acceptable type to be used as a rational
    number.

    Explanation
    ===========

    Returns ``True`` on any argument of type ``int``, :ref:`ZZ`, or :ref:`QQ`.

    See Also
    ========

    is_int

    """
    # ``c in QQ`` is too accepting (e.g. ``3.14 in QQ`` is ``True``),
    # ``QQ.of_type(c)`` is too demanding (e.g. ``QQ.of_type(3)`` is ``False``).
    #
    # Meanwhile, if gmpy2 is installed then ``ZZ.of_type()`` accepts only
    # ``mpz``, not ``int``, so we need another clause to ensure ``int`` is
    # accepted.
    return isinstance(c, int) or ZZ.of_type(c) or QQ.of_type(c)
Esempio n. 14
0
def test_HolonomicFunction_multiplication():
    x = symbols('x')
    R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
    p = HolonomicFunction(Dx + x + x * Dx**2, x)
    q = HolonomicFunction(x * Dx + Dx * x + Dx**2, x)
    r = HolonomicFunction((8*x**6 + 4*x**4 + 6*x**2 + 3) + (24*x**5 - 4*x**3 + 24*x)*Dx + \
        (8*x**6 + 20*x**4 + 12*x**2 + 2)*Dx**2 + (8*x**5 + 4*x**3 + 4*x)*Dx**3 + \
        (2*x**4 + x**2)*Dx**4, x)
    assert p * q == r
    p = HolonomicFunction(Dx**2 + 1, x)
    q = HolonomicFunction(Dx - 1, x)
    r = HolonomicFunction((2) + (-2) * Dx + (1) * Dx**2, x)
    assert p * q == r
    p = HolonomicFunction(Dx**2 + 1 + x + Dx, x)
    q = HolonomicFunction((Dx * x - 1)**2, x)
    r = HolonomicFunction((4*x**7 + 11*x**6 + 16*x**5 + 4*x**4 - 6*x**3 - 7*x**2 - 8*x - 2) + \
        (8*x**6 + 26*x**5 + 24*x**4 - 3*x**3 - 11*x**2 - 6*x - 2)*Dx + \
        (8*x**6 + 18*x**5 + 15*x**4 - 3*x**3 - 6*x**2 - 6*x - 2)*Dx**2 + (8*x**5 + \
            10*x**4 + 6*x**3 - 2*x**2 - 4*x)*Dx**3 + (4*x**5 + 3*x**4 - x**2)*Dx**4, x)
    assert p * q == r
    p = HolonomicFunction(x * Dx**2 - 1, x)
    q = HolonomicFunction(Dx * x - x, x)
    r = HolonomicFunction((x - 3) + (-2 * x + 2) * Dx + (x) * Dx**2, x)
    assert p * q == r
Esempio n. 15
0
def test_HolonomicFunction_composition():
    x = symbols('x')
    R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
    p = HolonomicFunction(Dx - 1, x).composition(x**2 + x)
    r = HolonomicFunction((-2 * x - 1) + Dx, x)
    assert p == r
    p = HolonomicFunction(Dx**2 + 1, x).composition(x**5 + x**2 + 1)
    r = HolonomicFunction((125*x**12 + 150*x**9 + 60*x**6 + 8*x**3) + (-20*x**3 - 2)*Dx + \
        (5*x**4 + 2*x)*Dx**2, x)
    assert p == r
    p = HolonomicFunction(Dx**2 * x + x, x).composition(2 * x**3 + x**2 + 1)
    r = HolonomicFunction((216*x**9 + 324*x**8 + 180*x**7 + 152*x**6 + 112*x**5 + \
        36*x**4 + 4*x**3) + (24*x**4 + 16*x**3 + 3*x**2 - 6*x - 1)*Dx + (6*x**5 + 5*x**4 + \
        x**3 + 3*x**2 + x)*Dx**2, x)
    assert p == r
    p = HolonomicFunction(Dx**2 + 1, x).composition(1 - x**2)
    r = HolonomicFunction((4 * x**3) - Dx + x * Dx**2, x)
    assert p == r
    p = HolonomicFunction(Dx**2 + 1, x).composition(x - 2 / (x**2 + 1))
    r = HolonomicFunction((x**12 + 6*x**10 + 12*x**9 + 15*x**8 + 48*x**7 + 68*x**6 + \
        72*x**5 + 111*x**4 + 112*x**3 + 54*x**2 + 12*x + 1) + (12*x**8 + 32*x**6 + \
        24*x**4 - 4)*Dx + (x**12 + 6*x**10 + 4*x**9 + 15*x**8 + 16*x**7 + 20*x**6 + 24*x**5+ \
        15*x**4 + 16*x**3 + 6*x**2 + 4*x + 1)*Dx**2, x)
    assert p == r
Esempio n. 16
0
class GaussianIntegerRing(GaussianDomain, Ring):
    r"""Ring of Gaussian integers ``ZZ_I``

    The :ref:`ZZ_I` domain represents the `Gaussian integers`_ `\mathbb{Z}[i]`
    as a :py:class:`~.Domain` in the domain system (see
    :ref:`polys-domainsintro`).

    By default a :py:class:`~.Poly` created from an expression with
    coefficients that are combinations of integers and ``I`` (`\sqrt{-1}`)
    will have the domain :ref:`ZZ_I`.

    >>> from sympy import Poly, Symbol, I
    >>> x = Symbol('x')
    >>> p = Poly(x**2 + I)
    >>> p
    Poly(x**2 + I, x, domain='ZZ_I')
    >>> p.domain
    ZZ_I

    The :ref:`ZZ_I` domain can be used to factorise polynomials that are
    reducible over the Gaussian integers.

    >>> from sympy import factor
    >>> factor(x**2 + 1)
    x**2 + 1
    >>> factor(x**2 + 1, domain='ZZ_I')
    (x - I)*(x + I)

    The corresponding `field of fractions`_ is the domain of the Gaussian
    rationals :ref:`QQ_I`. Conversely :ref:`ZZ_I` is the `ring of integers`_
    of :ref:`QQ_I`.

    >>> from sympy import ZZ_I, QQ_I
    >>> ZZ_I.get_field()
    QQ_I
    >>> QQ_I.get_ring()
    ZZ_I

    When using the domain directly :ref:`ZZ_I` can be used as a constructor.

    >>> ZZ_I(3, 4)
    (3 + 4*I)
    >>> ZZ_I(5)
    (5 + 0*I)

    The domain elements of :ref:`ZZ_I` are instances of
    :py:class:`~.GaussianInteger` which support the rings operations
    ``+,-,*,**``.

    >>> z1 = ZZ_I(5, 1)
    >>> z2 = ZZ_I(2, 3)
    >>> z1
    (5 + 1*I)
    >>> z2
    (2 + 3*I)
    >>> z1 + z2
    (7 + 4*I)
    >>> z1 * z2
    (7 + 17*I)
    >>> z1 ** 2
    (24 + 10*I)

    Both floor (``//``) and modulo (``%``) division work with
    :py:class:`~.GaussianInteger` (see the :py:meth:`~.Domain.div` method).

    >>> z3, z4 = ZZ_I(5), ZZ_I(1, 3)
    >>> z3 // z4  # floor division
    (1 + -1*I)
    >>> z3 % z4   # modulo division (remainder)
    (1 + -2*I)
    >>> (z3//z4)*z4 + z3%z4 == z3
    True

    True division (``/``) in :ref:`ZZ_I` gives an element of :ref:`QQ_I`. The
    :py:meth:`~.Domain.exquo` method can be used to divide in :ref:`ZZ_I` when
    exact division is possible.

    >>> z1 / z2
    (1 + -1*I)
    >>> ZZ_I.exquo(z1, z2)
    (1 + -1*I)
    >>> z3 / z4
    (1/2 + -3/2*I)
    >>> ZZ_I.exquo(z3, z4)
    Traceback (most recent call last):
        ...
    ExactQuotientFailed: (1 + 3*I) does not divide (5 + 0*I) in ZZ_I

    The :py:meth:`~.Domain.gcd` method can be used to compute the `gcd`_ of any
    two elements.

    >>> ZZ_I.gcd(ZZ_I(10), ZZ_I(2))
    (2 + 0*I)
    >>> ZZ_I.gcd(ZZ_I(5), ZZ_I(2, 1))
    (2 + 1*I)

    .. _Gaussian integers: https://en.wikipedia.org/wiki/Gaussian_integer
    .. _gcd: https://en.wikipedia.org/wiki/Greatest_common_divisor

    """
    dom = ZZ
    dtype = GaussianInteger
    zero = dtype(ZZ(0), ZZ(0))
    one = dtype(ZZ(1), ZZ(0))
    imag_unit = dtype(ZZ(0), ZZ(1))
    units = (one, imag_unit, -one, -imag_unit)  # powers of i

    rep = 'ZZ_I'

    is_GaussianRing = True
    is_ZZ_I = True

    def __init__(self):  # override Domain.__init__
        """For constructing ZZ_I."""

    def get_ring(self):
        """Returns a ring associated with ``self``. """
        return self

    def get_field(self):
        """Returns a field associated with ``self``. """
        return QQ_I

    def normalize(self, d, *args):
        """Return first quadrant element associated with ``d``.

        Also multiply the other arguments by the same power of i.
        """
        unit = self.canonical_unit(d)
        d *= unit
        args = tuple(a * unit for a in args)
        return (d, ) + args if args else d

    def gcd(self, a, b):
        """Greatest common divisor of a and b over ZZ_I."""
        while b:
            a, b = b, a % b
        return self.normalize(a)

    def lcm(self, a, b):
        """Least common multiple of a and b over ZZ_I."""
        return (a * b) // self.gcd(a, b)

    def from_GaussianIntegerRing(K1, a, K0):
        """Convert a ZZ_I element to ZZ_I."""
        return a

    def from_GaussianRationalField(K1, a, K0):
        """Convert a QQ_I element to ZZ_I."""
        return K1.new(ZZ.convert(a.x), ZZ.convert(a.y))
Esempio n. 17
0
def test_trace():
    a = [[ZZ(3), ZZ(7), ZZ(4)], [ZZ(2), ZZ(4), ZZ(5)], [ZZ(6), ZZ(2), ZZ(3)]]
    b = eye(2, ZZ)

    assert trace(a, ZZ) == ZZ(10)
    assert trace(b, ZZ) == ZZ(2)
Esempio n. 18
0
def test_mulmatscaler():
    a = eye(3, ZZ)
    b = [[ZZ(3), ZZ(7), ZZ(4)], [ZZ(2), ZZ(4), ZZ(5)], [ZZ(6), ZZ(2), ZZ(3)]]

    assert mulmatscaler(a, ZZ(4), ZZ) == [[ZZ(4), ZZ(0), ZZ(0)],
                                          [ZZ(0), ZZ(4), ZZ(0)],
                                          [ZZ(0), ZZ(0), ZZ(4)]]
    assert mulmatscaler(b, ZZ(1), ZZ) == [[ZZ(3), ZZ(7), ZZ(4)],
                                          [ZZ(2), ZZ(4), ZZ(5)],
                                          [ZZ(6), ZZ(2), ZZ(3)]]
Esempio n. 19
0
 def from_GaussianRationalField(K1, a, K0):
     """Convert a QQ_I element to ZZ_I."""
     return K1.new(ZZ.convert(a.x), ZZ.convert(a.y))
Esempio n. 20
0
def test_mulmatmat():
    a = [[ZZ(3), ZZ(4)], [ZZ(5), ZZ(6)]]
    b = [[ZZ(1), ZZ(2)], [ZZ(7), ZZ(8)]]
    c = eye(2, ZZ)
    d = [[ZZ(6)], [ZZ(7)]]

    assert mulmatmat(a, b, ZZ) == [[ZZ(31), ZZ(38)], [ZZ(47), ZZ(58)]]
    assert mulmatmat(a, c, ZZ) == [[ZZ(3), ZZ(4)], [ZZ(5), ZZ(6)]]
    assert mulmatmat(b, d, ZZ) == [[ZZ(20)], [ZZ(98)]]
Esempio n. 21
0
def test_sub():
    a = [[ZZ(3), ZZ(7), ZZ(4)], [ZZ(2), ZZ(4), ZZ(5)], [ZZ(6), ZZ(2), ZZ(3)]]
    b = [[ZZ(5), ZZ(4), ZZ(9)], [ZZ(3), ZZ(7), ZZ(1)],
         [ZZ(12), ZZ(13), ZZ(14)]]
    c = [[ZZ(12)], [ZZ(17)], [ZZ(21)]]
    d = [[ZZ(3)], [ZZ(4)], [ZZ(5)]]
    e = [[ZZ(12), ZZ(78)], [ZZ(56), ZZ(79)]]
    f = [[ZZ.zero, ZZ.zero], [ZZ.zero, ZZ.zero]]

    assert sub(a, b, ZZ) == [[ZZ(-2), ZZ(3), ZZ(-5)], [ZZ(-1),
                                                       ZZ(-3),
                                                       ZZ(4)],
                             [ZZ(-6), ZZ(-11), ZZ(-11)]]
    assert sub(c, d, ZZ) == [[ZZ(9)], [ZZ(13)], [ZZ(16)]]
    assert sub(e, f, ZZ) == e
Esempio n. 22
0
def test_add():
    a = [[ZZ(3), ZZ(7), ZZ(4)], [ZZ(2), ZZ(4), ZZ(5)], [ZZ(6), ZZ(2), ZZ(3)]]
    b = [[ZZ(5), ZZ(4), ZZ(9)], [ZZ(3), ZZ(7), ZZ(1)],
         [ZZ(12), ZZ(13), ZZ(14)]]
    c = [[ZZ(12)], [ZZ(17)], [ZZ(21)]]
    d = [[ZZ(3)], [ZZ(4)], [ZZ(5)]]
    e = [[ZZ(12), ZZ(78)], [ZZ(56), ZZ(79)]]
    f = [[ZZ.zero, ZZ.zero], [ZZ.zero, ZZ.zero]]

    assert add(a, b, ZZ) == [[ZZ(8), ZZ(11), ZZ(13)], [ZZ(5),
                                                       ZZ(11),
                                                       ZZ(6)],
                             [ZZ(18), ZZ(15), ZZ(17)]]
    assert add(c, d, ZZ) == [[ZZ(15)], [ZZ(21)], [ZZ(26)]]
    assert add(e, f, ZZ) == e
Esempio n. 23
0
def round_two(T, radicals=None):
    r"""
    Zassenhaus's "Round 2" algorithm.

    Explanation
    ===========

    Carry out Zassenhaus's "Round 2" algorithm on a monic irreducible
    polynomial *T* over :ref:`ZZ`. This computes an integral basis and the
    discriminant for the field $K = \mathbb{Q}[x]/(T(x))$.

    Ordinarily this function need not be called directly, as one can instead
    access the :py:meth:`~.AlgebraicField.maximal_order`,
    :py:meth:`~.AlgebraicField.integral_basis`, and
    :py:meth:`~.AlgebraicField.discriminant` methods of an
    :py:class:`~.AlgebraicField`.

    Examples
    ========

    Working through an AlgebraicField:

    >>> from sympy import Poly, QQ
    >>> from sympy.abc import x
    >>> T = Poly(x ** 3 + x ** 2 - 2 * x + 8)
    >>> K = QQ.alg_field_from_poly(T, "theta")
    >>> print(K.maximal_order())
    Submodule[[2, 0, 0], [0, 2, 0], [0, 1, 1]]/2
    >>> print(K.discriminant())
    -503
    >>> print(K.integral_basis(fmt='sympy'))
    [1, theta, theta/2 + theta**2/2]

    Calling directly:

    >>> from sympy import Poly
    >>> from sympy.abc import x
    >>> from sympy.polys.numberfields.basis import round_two
    >>> T = Poly(x ** 3 + x ** 2 - 2 * x + 8)
    >>> print(round_two(T))
    (Submodule[[2, 0, 0], [0, 2, 0], [0, 1, 1]]/2, -503)

    The nilradicals mod $p$ that are sometimes computed during the Round Two
    algorithm may be useful in further calculations. Pass a dictionary under
    `radicals` to receive these:

    >>> T = Poly(x**3 + 3*x**2 + 5)
    >>> rad = {}
    >>> ZK, dK = round_two(T, radicals=rad)
    >>> print(rad)
    {3: Submodule[[-1, 1, 0], [-1, 0, 1]]}

    Parameters
    ==========

    T : :py:class:`~.Poly`
        The irreducible monic polynomial over :ref:`ZZ` defining the number
        field.

    radicals : dict, optional
        This is a way for any $p$-radicals (if computed) to be returned by
        reference. If desired, pass an empty dictionary. If the algorithm
        reaches the point where it computes the nilradical mod $p$ of the ring
        of integers $Z_K$, then an $\mathbb{F}_p$-basis for this ideal will be
        stored in this dictionary under the key ``p``. This can be useful for
        other algorithms, such as prime decomposition.

    Returns
    =======

    Pair ``(ZK, dK)``, where:

        ``ZK`` is a :py:class:`~sympy.polys.numberfields.modules.Submodule`
        representing the maximal order.

        ``dK`` is the discriminant of the field $K = \mathbb{Q}[x]/(T(x))$.

    See Also
    ========

    .AlgebraicField.maximal_order
    .AlgebraicField.integral_basis
    .AlgebraicField.discriminant

    References
    ==========

    .. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.*

    """
    if T.domain == QQ:
        try:
            T = Poly(T, domain=ZZ)
        except CoercionFailed:
            pass  # Let the error be raised by the next clause.
    if (not T.is_univariate or not T.is_irreducible or not T.is_monic
            or not T.domain == ZZ):
        raise ValueError(
            'Round 2 requires a monic irreducible univariate polynomial over ZZ.'
        )
    n = T.degree()
    D = T.discriminant()
    D_modulus = ZZ.from_sympy(abs(D))
    # D must be 0 or 1 mod 4 (see Cohen Sec 4.4), which ensures we can write
    # it in the form D = D_0 * F**2, where D_0 is 1 or a fundamental discriminant.
    _, F = extract_fundamental_discriminant(D)
    Ztheta = PowerBasis(T)
    H = Ztheta.whole_submodule()
    nilrad = None
    while F:
        # Next prime:
        p, e = F.popitem()
        U_bar, m = _apply_Dedekind_criterion(T, p)
        if m == 0:
            continue
        # For a given prime p, the first enlargement of the order spanned by
        # the current basis can be done in a simple way:
        U = Ztheta.element_from_poly(Poly(U_bar, domain=ZZ))
        # TODO:
        #  Theory says only first m columns of the U//p*H term below are needed.
        #  Could be slightly more efficient to use only those. Maybe `Submodule`
        #  class should support a slice operator?
        H = H.add(U // p * H, hnf_modulus=D_modulus)
        if e <= m:
            continue
        # A second, and possibly more, enlargements for p will be needed.
        # These enlargements require a more involved procedure.
        q = p
        while q < n:
            q *= p
        H1, nilrad = _second_enlargement(H, p, q)
        while H1 != H:
            H = H1
            H1, nilrad = _second_enlargement(H, p, q)
    # Note: We do not store all nilradicals mod p, only the very last. This is
    # because, unless computed against the entire integral basis, it might not
    # be accurate. (In other words, if H was not already equal to ZK when we
    # passed it to `_second_enlargement`, then we can't trust the nilradical
    # so computed.) Example: if T(x) = x ** 3 + 15 * x ** 2 - 9 * x + 13, then
    # F is divisible by 2, 3, and 7, and the nilradical mod 2 as computed above
    # will not be accurate for the full, maximal order ZK.
    if nilrad is not None and isinstance(radicals, dict):
        radicals[p] = nilrad
    ZK = H
    # Pre-set expensive boolean properties which we already know to be true:
    ZK._starts_with_unity = True
    ZK._is_sq_maxrank_HNF = True
    dK = (D * ZK.matrix.det()**2) // ZK.denom**(2 * n)
    return ZK, dK
Esempio n. 24
0
def test_transpose():
    a = [[ZZ(3), ZZ(7), ZZ(4)], [ZZ(2), ZZ(4), ZZ(5)], [ZZ(6), ZZ(2), ZZ(3)]]
    b = eye(4, ZZ)

    assert transpose(a, ZZ) == ([[ZZ(3), ZZ(2), ZZ(6)], [ZZ(7), ZZ(4), ZZ(2)], [ZZ(4), ZZ(5), ZZ(3)]])
    assert transpose(b, ZZ) == b