示例#1
0
def test_polymatrix_getitem():
    M = PolyMatrix([[1, 2], [3, 4]], x)
    assert M[:, :] == M
    assert M[0, :] == PolyMatrix([[1, 2]], x)
    assert M[:, 0] == PolyMatrix([1, 3], x)
    assert M[0, 0] == Poly(1, x, domain=QQ)
    assert M[0] == Poly(1, x, domain=QQ)
    assert M[:2] == [Poly(1, x, domain=QQ), Poly(2, x, domain=QQ)]
示例#2
0
def test_polymatrix_from_Matrix():
    assert PolyMatrix.from_Matrix(Matrix([1, 2]), x) == PolyMatrix([1, 2], x, ring=QQ[x])
    assert PolyMatrix.from_Matrix(Matrix([1]), ring=QQ[x]) == PolyMatrix([1], x)
    pmx = PolyMatrix([1, 2], x)
    pmy = PolyMatrix([1, 2], y)
    assert pmx != pmy
    assert pmx.set_gens(y) == pmy
示例#3
0
def test_polymatrix_rref():
    M = PolyMatrix([[1, 2], [3, 4]], x)
    assert M.rref() == (PolyMatrix.eye(2, x), (0, 1))
    raises(ValueError, lambda: PolyMatrix([1, 2], ring=ZZ[x]).rref())
    raises(ValueError, lambda: PolyMatrix([1, x], ring=QQ[x]).rref())
示例#4
0
def test_polymatrix_ones_zeros():
    assert PolyMatrix.zeros(1, 2, x) == PolyMatrix([[0, 0]], x)
    assert PolyMatrix.eye(2, x) == PolyMatrix([[1, 0], [0, 1]], x)
示例#5
0
def test_polymatrix_manipulations():
    M1 = PolyMatrix([[1, 2], [3, 4]], x)
    assert M1.transpose() == PolyMatrix([[1, 3], [2, 4]], x)
    M2 = PolyMatrix([[5, 6], [7, 8]], x)
    assert M1.row_join(M2) == PolyMatrix([[1, 2, 5, 6], [3, 4, 7, 8]], x)
    assert M1.col_join(M2) == PolyMatrix([[1, 2], [3, 4], [5, 6], [7, 8]], x)
    assert M1.applyfunc(lambda e: 2 * e) == PolyMatrix([[2, 4], [6, 8]], x)
示例#6
0
def test_polymatrix_arithmetic():
    M = PolyMatrix([[1, 2], [3, 4]], x)
    assert M + M == PolyMatrix([[2, 4], [6, 8]], x)
    assert M - M == PolyMatrix([[0, 0], [0, 0]], x)
    assert -M == PolyMatrix([[-1, -2], [-3, -4]], x)
    raises(TypeError, lambda: M + 1)
    raises(TypeError, lambda: M - 1)
    raises(TypeError, lambda: 1 + M)
    raises(TypeError, lambda: 1 - M)

    assert M * M == PolyMatrix([[7, 10], [15, 22]], x)
    assert 2 * M == PolyMatrix([[2, 4], [6, 8]], x)
    assert M * 2 == PolyMatrix([[2, 4], [6, 8]], x)
    assert S(2) * M == PolyMatrix([[2, 4], [6, 8]], x)
    assert M * S(2) == PolyMatrix([[2, 4], [6, 8]], x)
    raises(TypeError, lambda: [] * M)
    raises(TypeError, lambda: M * [])
    M2 = PolyMatrix([[1, 2]], ring=ZZ[x])
    assert S.Half * M2 == PolyMatrix([[S.Half, 1]], ring=QQ[x])
    assert M2 * S.Half == PolyMatrix([[S.Half, 1]], ring=QQ[x])

    assert M / 2 == PolyMatrix([[S(1) / 2, 1], [S(3) / 2, 2]], x)
    assert M / Poly(2, x) == PolyMatrix([[S(1) / 2, 1], [S(3) / 2, 2]], x)
    raises(TypeError, lambda: M / [])
示例#7
0
def test_polymatrix_repr():
    assert repr(PolyMatrix([[1, 2]], x)) == 'PolyMatrix([[1, 2]], ring=QQ[x])'
    assert repr(PolyMatrix(0, 2, [], x)) == 'PolyMatrix(0, 2, [], ring=QQ[x])'
示例#8
0
文件: prde.py 项目: yuyumaz/sympy
def prde_no_cancel_b_small(b, Q, n, DE):
    """
    Parametric Poly Risch Differential Equation - No cancellation: deg(b) small enough.

    Given a derivation D on k[t], n in ZZ, and b, q1, ..., qm in k[t] with
    deg(b) < deg(D) - 1 and either D == d/dt or deg(D) >= 2, returns
    h1, ..., hr in k[t] and a matrix A with coefficients in Const(k) such that
    if c1, ..., cm in Const(k) and q in k[t] satisfy deg(q) <= n and
    Dq + b*q == Sum(ci*qi, (i, 1, m)) then q = Sum(dj*hj, (j, 1, r)) where
    d1, ..., dr in Const(k) and A*Matrix([[c1, ..., cm, d1, ..., dr]]).T == 0.
    """
    m = len(Q)
    H = [Poly(0, DE.t)]*m

    for N in range(n, 0, -1):  # [n, ..., 1]
        for i in range(m):
            si = Q[i].nth(N + DE.d.degree(DE.t) - 1)/(N*DE.d.LC())
            sitn = Poly(si*DE.t**N, DE.t)
            H[i] = H[i] + sitn
            Q[i] = Q[i] - derivation(sitn, DE) - b*sitn

    if b.degree(DE.t) > 0:
        for i in range(m):
            si = Poly(Q[i].nth(b.degree(DE.t))/b.LC(), DE.t)
            H[i] = H[i] + si
            Q[i] = Q[i] - derivation(si, DE) - b*si
        if all(qi.is_zero for qi in Q):
            dc = -1
            M = Matrix()
        else:
            dc = max([qi.degree(DE.t) for qi in Q])
            M = Matrix(dc + 1, m, lambda i, j: Q[j].nth(i))
        A, u = constant_system(M, zeros(dc + 1, 1), DE)
        c = eye(m)
        A = A.row_join(zeros(A.rows, m)).col_join(c.row_join(-c))
        return (H, A)

    # else: b is in k, deg(qi) < deg(Dt)

    t = DE.t
    if DE.case != 'base':
        with DecrementLevel(DE):
            t0 = DE.t  # k = k0(t0)
            ba, bd = frac_in(b, t0, field=True)
            Q0 = [frac_in(qi.TC(), t0, field=True) for qi in Q]
            f, B = param_rischDE(ba, bd, Q0, DE)

            # f = [f1, ..., fr] in k^r and B is a matrix with
            # m + r columns and entries in Const(k) = Const(k0)
            # such that Dy0 + b*y0 = Sum(ci*qi, (i, 1, m)) has
            # a solution y0 in k with c1, ..., cm in Const(k)
            # if and only y0 = Sum(dj*fj, (j, 1, r)) where
            # d1, ..., dr ar in Const(k) and
            # B*Matrix([c1, ..., cm, d1, ..., dr]) == 0.

        # Transform fractions (fa, fd) in f into constant
        # polynomials fa/fd in k[t].
        # (Is there a better way?)
        f = [Poly(fa.as_expr()/fd.as_expr(), t, field=True)
             for fa, fd in f]
    else:
        # Base case. Dy == 0 for all y in k and b == 0.
        # Dy + b*y = Sum(ci*qi) is solvable if and only if
        # Sum(ci*qi) == 0 in which case the solutions are
        # y = d1*f1 for f1 = 1 and any d1 in Const(k) = k.

        f = [Poly(1, t, field=True)]  # r = 1
        B = Matrix([[qi.TC() for qi in Q] + [S(0)]])
        # The condition for solvability is
        # B*Matrix([c1, ..., cm, d1]) == 0
        # There are no constraints on d1.

    # Coefficients of t^j (j > 0) in Sum(ci*qi) must be zero.
    d = max([qi.degree(DE.t) for qi in Q])
    if d > 0:
        M = Matrix(d, m, lambda i, j: Q[j].nth(i + 1))
        A, _ = constant_system(M, zeros(d, 1), DE)
    else:
        # No constraints on the hj.
        A = Matrix(0, m, [])

    # Solutions of the original equation are
    #    y = Sum(dj*fj, (j, 1, r) + Sum(ei*hi, (i, 1, m)),
    # where  ei == ci  (i = 1, ..., m),  when
    # A*Matrix([c1, ..., cm]) == 0 and
    # B*Matrix([c1, ..., cm, d1, ..., dr]) == 0

    # Build combined constraint matrix with m + r + m columns.

    r = len(f)
    I = eye(m)
    A = A.row_join(zeros(A.rows, r + m))
    B = B.row_join(zeros(B.rows, m))
    C = I.row_join(zeros(m, r)).row_join(-I)

    return f + H, A.col_join(B).col_join(C)
示例#9
0
def _test_polymatrix():
    pm1 = PolyMatrix([[Poly(x**2, x), Poly(-x, x)],
                      [Poly(x**3, x), Poly(-1 + x, x)]])
    v1 = PolyMatrix([[1, 0], [-1, 0]], ring='ZZ[x]')
    m1 = PolyMatrix([[1, 0], [-1, 0]], ring='ZZ[x]')
    A = PolyMatrix([[Poly(x**2 + x, x), Poly(0, x)], \
                    [Poly(x**3 - x + 1, x), Poly(0, x)]])
    B = PolyMatrix([[Poly(x**2, x), Poly(-x, x)], [Poly(-x**2, x),
                                                   Poly(x, x)]])
    assert A.ring == ZZ[x]
    assert isinstance(pm1 * v1, PolyMatrix)
    assert pm1 * v1 == A
    assert pm1 * m1 == A
    assert v1 * pm1 == B

    pm2 = PolyMatrix([[Poly(x**2, x, domain='QQ'), Poly(0, x, domain='QQ'), Poly(-x**2, x, domain='QQ'), \
                    Poly(x**3, x, domain='QQ'), Poly(0, x, domain='QQ'), Poly(-x**3, x, domain='QQ')]])
    assert pm2.ring == QQ[x]
    v2 = PolyMatrix([1, 0, 0, 0, 0, 0], ring='ZZ[x]')
    m2 = PolyMatrix([1, 0, 0, 0, 0, 0], ring='ZZ[x]')
    C = PolyMatrix([[Poly(x**2, x, domain='QQ')]])
    assert pm2 * v2 == C
    assert pm2 * m2 == C

    pm3 = PolyMatrix([[Poly(x**2, x), S.One]], ring='ZZ[x]')
    v3 = S.Half * pm3
    assert v3 == PolyMatrix([[Poly(S.Half * x**2, x, domain='QQ'), S.Half]],
                            ring='QQ[x]')
    assert pm3 * S.Half == v3
    assert v3.ring == QQ[x]

    pm4 = PolyMatrix(
        [[Poly(x**2, x, domain='ZZ'),
          Poly(-x**2, x, domain='ZZ')]])
    v4 = PolyMatrix([1, -1], ring='ZZ[x]')
    assert pm4 * v4 == PolyMatrix([[Poly(2 * x**2, x, domain='ZZ')]])

    assert len(PolyMatrix(ring=ZZ[x])) == 0
    assert PolyMatrix([1, 0, 0, 1], x) / (-1) == PolyMatrix([-1, 0, 0, -1], x)
def test_polymatrix():
    pm1 = PolyMatrix([[Poly(x**2, x), Poly(-x, x)],
                      [Poly(x**3, x), Poly(-1 + x, x)]])
    v1 = PolyMatrix([[1, 0], [-1, 0]], ring='ZZ[x]')
    m1 = Matrix([[1, 0], [-1, 0]], ring='ZZ[x]')
    A = PolyMatrix([[Poly(x**2 + x, x), Poly(0, x)], \
                    [Poly(x**3 - x + 1, x), Poly(0, x)]])
    B = PolyMatrix([[Poly(x**2, x), Poly(-x, x)], [Poly(-x**2, x),
                                                   Poly(x, x)]])
    assert A.ring == ZZ[x]
    assert isinstance(pm1 * v1, PolyMatrix)
    assert pm1 * v1 == A
    assert pm1 * m1 == A
    assert v1 * pm1 == B

    pm2 = PolyMatrix([[Poly(x**2, x, domain='QQ'), Poly(0, x, domain='QQ'), Poly(-x**2, x, domain='QQ'), \
                    Poly(x**3, x, domain='QQ'), Poly(0, x, domain='QQ'), Poly(-x**3, x, domain='QQ')]])
    assert pm2.ring == QQ[x]
    v2 = PolyMatrix([1, 0, 0, 0, 0, 0], ring='ZZ[x]')
    m2 = Matrix([1, 0, 0, 0, 0, 0], ring='ZZ[x]')
    C = PolyMatrix([[Poly(x**2, x, domain='QQ')]])
    assert pm2 * v2 == C
    assert pm2 * m2 == C

    pm3 = PolyMatrix([[Poly(x**2, x), S(1)]], ring='ZZ[x]')
    v3 = (S(1) / 2) * pm3
    assert v3 == PolyMatrix([[Poly(S(1) / 2 * x**2, x, domain='QQ'),
                              S(1) / 2]],
                            ring='EX')
    assert pm3 * (S(1) / 2) == v3
    assert v3.ring == EX

    pm4 = PolyMatrix(
        [[Poly(x**2, x, domain='ZZ'),
          Poly(-x**2, x, domain='ZZ')]])
    v4 = Matrix([1, -1], ring='ZZ[x]')
    assert pm4 * v4 == PolyMatrix([[Poly(2 * x**2, x, domain='ZZ')]])

    assert len(PolyMatrix()) == 0
    assert PolyMatrix([1, 0, 0, 1]) / (-1) == PolyMatrix([-1, 0, 0, -1])
示例#11
0
文件: prde.py 项目: bjodah/sympy
def param_rischDE(fa, fd, G, DE):
    """
    Solve a Parametric Risch Differential Equation: Dy + f*y == Sum(ci*Gi, (i, 1, m)).

    Given a derivation D in k(t), f in k(t), and G
    = [G1, ..., Gm] in k(t)^m, return h = [h1, ..., hr] in k(t)^r and
    a matrix A with m + r columns and entries in Const(k) such that
    Dy + f*y = Sum(ci*Gi, (i, 1, m)) has a solution y
    in k(t) with c1, ..., cm in Const(k) if and only if y = Sum(dj*hj,
    (j, 1, r)) where d1, ..., dr are in Const(k) and (c1, ..., cm,
    d1, ..., dr) is a solution of Ax == 0.

    Elements of k(t) are tuples (a, d) with a and d in k[t].
    """
    m = len(G)
    q, (fa, fd) = weak_normalizer(fa, fd, DE)
    # Solutions of the weakly normalized equation Dz + f*z = q*Sum(ci*Gi)
    # correspond to solutions y = z/q of the original equation.
    gamma = q
    G = [(q*ga).cancel(gd, include=True) for ga, gd in G]

    a, (ba, bd), G, hn = prde_normal_denom(fa, fd, G, DE)
    # Solutions q in k<t> of  a*Dq + b*q = Sum(ci*Gi) correspond
    # to solutions z = q/hn of the weakly normalized equation.
    gamma *= hn

    A, B, G, hs = prde_special_denom(a, ba, bd, G, DE)
    # Solutions p in k[t] of  A*Dp + B*p = Sum(ci*Gi) correspond
    # to solutions q = p/hs of the previous equation.
    gamma *= hs

    g = A.gcd(B)
    a, b, g = A.quo(g), B.quo(g), [gia.cancel(gid*g, include=True) for
        gia, gid in G]

    # a*Dp + b*p = Sum(ci*gi)  may have a polynomial solution
    # only if the sum is in k[t].

    q, M = prde_linear_constraints(a, b, g, DE)

    # q = [q1, ..., qm] where qi in k[t] is the polynomial component
    # of the partial fraction expansion of gi.
    # M is a matrix with m columns and entries in k.
    # Sum(fi*gi, (i, 1, m)), where f1, ..., fm are elements of k,
    # is a polynomial if and only if M*Matrix([f1, ..., fm]) == 0,
    # in which case the sum is equal to Sum(fi*qi).

    M, _ = constant_system(M, zeros(M.rows, 1), DE)
    # M is a matrix with m columns and entries in Const(k).
    # Sum(ci*gi) is in k[t] for c1, ..., cm in Const(k)
    # if and only if M*Matrix([c1, ..., cm]) == 0,
    # in which case the sum is Sum(ci*qi).

    ## Reduce number of constants at this point

    V = M.nullspace()
    # V = [v1, ..., vu] where each vj is a column matrix with
    # entries aj1, ..., ajm in Const(k).
    # Sum(aji*gi) is in k[t] and equal to Sum(aji*qi) (j = 1, ..., u).
    # Sum(ci*gi) is in k[t] if and only is ci = Sum(dj*aji)
    # (i = 1, ..., m) for some d1, ..., du in Const(k).
    # In that case,
    #     Sum(ci*gi) = Sum(ci*qi) = Sum(dj*Sum(aji*qi)) = Sum(dj*rj)
    # where rj = Sum(aji*qi) (j = 1, ..., u) in k[t].

    if not V:  # No non-trivial solution
        return [], eye(m)

    Mq = Matrix([q])  # A single row.
    r = [(Mq*vj)[0] for vj in V]  # [r1, ..., ru]

    # Solutions of a*Dp + b*p = Sum(dj*rj) correspond to solutions
    # y = p/gamma of the initial equation with ci = Sum(dj*aji).

    try:
        # We try n=5. At least for prde_spde, it will always
        # terminate no matter what n is.
        n = bound_degree(a, b, r, DE, parametric=True)
    except NotImplementedError:
        # A temporary bound is set. Eventually, it will be removed.
        # the currently added test case takes large time
        # even with n=5, and much longer with large n's.
        n = 5

    h, B = param_poly_rischDE(a, b, r, n, DE)

    # h = [h1, ..., hv] in k[t]^v and and B is a matrix with u + v
    # columns and entries in Const(k) such that
    # a*Dp + b*p = Sum(dj*rj) has a solution p of degree <= n
    # in k[t] if and only if p = Sum(ek*hk) where e1, ..., ev are in
    # Const(k) and B*Matrix([d1, ..., du, e1, ..., ev]) == 0.
    # The solutions of the original equation for ci = Sum(dj*aji)
    # (i = 1, ..., m) are then y = Sum(ek*hk, (k, 1, v))/gamma.

    ## Build combined relation matrix with m + u + v columns.

    A = -eye(m)
    for vj in V:
        A = A.row_join(vj)
    A = A.row_join(zeros(m, len(h)))
    A = A.col_join(zeros(B.rows, m).row_join(B))

    ## Eliminate d1, ..., du.

    W = A.nullspace()

    # W = [w1, ..., wt] where each wl is a column matrix with
    # entries blk (k = 1, ..., m + u + v) in Const(k).
    # The vectors (bl1, ..., blm) generate the space of those
    # constant families (c1, ..., cm) for which a solution of
    # the equation Dy + f*y == Sum(ci*Gi) exists. They generate
    # the space and form a basis except possibly when Dy + f*y == 0
    # is solvable in k(t}. The corresponding solutions are
    # y = Sum(blk'*hk, (k, 1, v))/gamma, where k' = k + m + u.

    v = len(h)
    M = Matrix([wl[:m] + wl[-v:] for wl in W])  # excise dj's.
    N = M.nullspace()
    # N = [n1, ..., ns] where the ni in Const(k)^(m + v) are column
    # vectors generating the space of linear relations between
    # c1, ..., cm, e1, ..., ev.

    C = Matrix([ni[:] for ni in N])  # rows n1, ..., ns.

    return [hk.cancel(gamma, include=True) for hk in h], C
示例#12
0
文件: prde.py 项目: bjodah/sympy
def prde_no_cancel_b_small(b, Q, n, DE):
    """
    Parametric Poly Risch Differential Equation - No cancellation: deg(b) small enough.

    Given a derivation D on k[t], n in ZZ, and b, q1, ..., qm in k[t] with
    deg(b) < deg(D) - 1 and either D == d/dt or deg(D) >= 2, returns
    h1, ..., hr in k[t] and a matrix A with coefficients in Const(k) such that
    if c1, ..., cm in Const(k) and q in k[t] satisfy deg(q) <= n and
    Dq + b*q == Sum(ci*qi, (i, 1, m)) then q = Sum(dj*hj, (j, 1, r)) where
    d1, ..., dr in Const(k) and A*Matrix([[c1, ..., cm, d1, ..., dr]]).T == 0.
    """
    m = len(Q)
    H = [Poly(0, DE.t)]*m

    for N in range(n, 0, -1):  # [n, ..., 1]
        for i in range(m):
            si = Q[i].nth(N + DE.d.degree(DE.t) - 1)/(N*DE.d.LC())
            sitn = Poly(si*DE.t**N, DE.t)
            H[i] = H[i] + sitn
            Q[i] = Q[i] - derivation(sitn, DE) - b*sitn

    if b.degree(DE.t) > 0:
        for i in range(m):
            si = Poly(Q[i].nth(b.degree(DE.t))/b.LC(), DE.t)
            H[i] = H[i] + si
            Q[i] = Q[i] - derivation(si, DE) - b*si
        if all(qi.is_zero for qi in Q):
            dc = -1
            M = Matrix()
        else:
            dc = max([qi.degree(DE.t) for qi in Q])
            M = Matrix(dc + 1, m, lambda i, j: Q[j].nth(i))
        A, u = constant_system(M, zeros(dc + 1, 1), DE)
        c = eye(m)
        A = A.row_join(zeros(A.rows, m)).col_join(c.row_join(-c))
        return (H, A)

    # else: b is in k, deg(qi) < deg(Dt)

    t = DE.t
    if DE.case != 'base':
        with DecrementLevel(DE):
            t0 = DE.t  # k = k0(t0)
            ba, bd = frac_in(b, t0, field=True)
            Q0 = [frac_in(qi.TC(), t0, field=True) for qi in Q]
            f, B = param_rischDE(ba, bd, Q0, DE)

            # f = [f1, ..., fr] in k^r and B is a matrix with
            # m + r columns and entries in Const(k) = Const(k0)
            # such that Dy0 + b*y0 = Sum(ci*qi, (i, 1, m)) has
            # a solution y0 in k with c1, ..., cm in Const(k)
            # if and only y0 = Sum(dj*fj, (j, 1, r)) where
            # d1, ..., dr ar in Const(k) and
            # B*Matrix([c1, ..., cm, d1, ..., dr]) == 0.

        # Transform fractions (fa, fd) in f into constant
        # polynomials fa/fd in k[t].
        # (Is there a better way?)
        f = [Poly(fa.as_expr()/fd.as_expr(), t, field=True)
             for fa, fd in f]
    else:
        # Base case. Dy == 0 for all y in k and b == 0.
        # Dy + b*y = Sum(ci*qi) is solvable if and only if
        # Sum(ci*qi) == 0 in which case the solutions are
        # y = d1*f1 for f1 = 1 and any d1 in Const(k) = k.

        f = [Poly(1, t, field=True)]  # r = 1
        B = Matrix([[qi.TC() for qi in Q] + [S(0)]])
        # The condition for solvability is
        # B*Matrix([c1, ..., cm, d1]) == 0
        # There are no constraints on d1.

    # Coefficients of t^j (j > 0) in Sum(ci*qi) must be zero.
    d = max([qi.degree(DE.t) for qi in Q])
    if d > 0:
        M = Matrix(d, m, lambda i, j: Q[j].nth(i + 1))
        A, _ = constant_system(M, zeros(d, 1), DE)
    else:
        # No constraints on the hj.
        A = Matrix(0, m, [])

    # Solutions of the original equation are
    #    y = Sum(dj*fj, (j, 1, r) + Sum(ei*hi, (i, 1, m)),
    # where  ei == ci  (i = 1, ..., m),  when
    # A*Matrix([c1, ..., cm]) == 0 and
    # B*Matrix([c1, ..., cm, d1, ..., dr]) == 0

    # Build combined constraint matrix with m + r + m columns.

    r = len(f)
    I = eye(m)
    A = A.row_join(zeros(A.rows, r + m))
    B = B.row_join(zeros(B.rows, m))
    C = I.row_join(zeros(m, r)).row_join(-I)

    return f + H, A.col_join(B).col_join(C)
示例#13
0
文件: prde.py 项目: yuyumaz/sympy
def param_rischDE(fa, fd, G, DE):
    """
    Solve a Parametric Risch Differential Equation: Dy + f*y == Sum(ci*Gi, (i, 1, m)).

    Given a derivation D in k(t), f in k(t), and G
    = [G1, ..., Gm] in k(t)^m, return h = [h1, ..., hr] in k(t)^r and
    a matrix A with m + r columns and entries in Const(k) such that
    Dy + f*y = Sum(ci*Gi, (i, 1, m)) has a solution y
    in k(t) with c1, ..., cm in Const(k) if and only if y = Sum(dj*hj,
    (j, 1, r)) where d1, ..., dr are in Const(k) and (c1, ..., cm,
    d1, ..., dr) is a solution of Ax == 0.

    Elements of k(t) are tuples (a, d) with a and d in k[t].
    """
    m = len(G)
    q, (fa, fd) = weak_normalizer(fa, fd, DE)
    # Solutions of the weakly normalized equation Dz + f*z = q*Sum(ci*Gi)
    # correspond to solutions y = z/q of the original equation.
    gamma = q
    G = [(q*ga).cancel(gd, include=True) for ga, gd in G]

    a, (ba, bd), G, hn = prde_normal_denom(fa, fd, G, DE)
    # Solutions q in k<t> of  a*Dq + b*q = Sum(ci*Gi) correspond
    # to solutions z = q/hn of the weakly normalized equation.
    gamma *= hn

    A, B, G, hs = prde_special_denom(a, ba, bd, G, DE)
    # Solutions p in k[t] of  A*Dp + B*p = Sum(ci*Gi) correspond
    # to solutions q = p/hs of the previous equation.
    gamma *= hs

    g = A.gcd(B)
    a, b, g = A.quo(g), B.quo(g), [gia.cancel(gid*g, include=True) for
        gia, gid in G]

    # a*Dp + b*p = Sum(ci*gi)  may have a polynomial solution
    # only if the sum is in k[t].

    q, M = prde_linear_constraints(a, b, g, DE)

    # q = [q1, ..., qm] where qi in k[t] is the polynomial component
    # of the partial fraction expansion of gi.
    # M is a matrix with m columns and entries in k.
    # Sum(fi*gi, (i, 1, m)), where f1, ..., fm are elements of k,
    # is a polynomial if and only if M*Matrix([f1, ..., fm]) == 0,
    # in which case the sum is equal to Sum(fi*qi).

    M, _ = constant_system(M, zeros(M.rows, 1), DE)
    # M is a matrix with m columns and entries in Const(k).
    # Sum(ci*gi) is in k[t] for c1, ..., cm in Const(k)
    # if and only if M*Matrix([c1, ..., cm]) == 0,
    # in which case the sum is Sum(ci*qi).

    ## Reduce number of constants at this point

    V = M.nullspace()
    # V = [v1, ..., vu] where each vj is a column matrix with
    # entries aj1, ..., ajm in Const(k).
    # Sum(aji*gi) is in k[t] and equal to Sum(aji*qi) (j = 1, ..., u).
    # Sum(ci*gi) is in k[t] if and only is ci = Sum(dj*aji)
    # (i = 1, ..., m) for some d1, ..., du in Const(k).
    # In that case,
    #     Sum(ci*gi) = Sum(ci*qi) = Sum(dj*Sum(aji*qi)) = Sum(dj*rj)
    # where rj = Sum(aji*qi) (j = 1, ..., u) in k[t].

    if not V:  # No non-trivial solution
        return [], eye(m)

    Mq = Matrix([q])  # A single row.
    r = [(Mq*vj)[0] for vj in V]  # [r1, ..., ru]

    # Solutions of a*Dp + b*p = Sum(dj*rj) correspond to solutions
    # y = p/gamma of the initial equation with ci = Sum(dj*aji).

    try:
        # Similar to rischDE(), we try oo, even though it might lead to
        # non-termination when there is no solution.  At least for prde_spde,
        # it will always terminate no matter what n is.
        n = bound_degree(a, b, r, DE, parametric=True)
    except NotImplementedError:
        debug("param_rischDE: Proceeding with n = oo; may cause "
              "non-termination.")
        n = oo

    h, B = param_poly_rischDE(a, b, r, n, DE)

    # h = [h1, ..., hv] in k[t]^v and and B is a matrix with u + v
    # columns and entries in Const(k) such that
    # a*Dp + b*p = Sum(dj*rj) has a solution p of degree <= n
    # in k[t] if and only if p = Sum(ek*hk) where e1, ..., ev are in
    # Const(k) and B*Matrix([d1, ..., du, e1, ..., ev]) == 0.
    # The solutions of the original equation for ci = Sum(dj*aji)
    # (i = 1, ..., m) are then y = Sum(ek*hk, (k, 1, v))/gamma.

    ## Build combined relation matrix with m + u + v columns.

    A = -eye(m)
    for vj in V:
        A = A.row_join(vj)
    A = A.row_join(zeros(m, len(h)))
    A = A.col_join(zeros(B.rows, m).row_join(B))

    ## Eliminate d1, ..., du.

    W = A.nullspace()

    # W = [w1, ..., wt] where each wl is a column matrix with
    # entries blk (k = 1, ..., m + u + v) in Const(k).
    # The vectors (bl1, ..., blm) generate the space of those
    # constant families (c1, ..., cm) for which a solution of
    # the equation Dy + f*y == Sum(ci*Gi) exists. They generate
    # the space and form a basis except possibly when Dy + f*y == 0
    # is solvable in k(t}. The corresponding solutions are
    # y = Sum(blk'*hk, (k, 1, v))/gamma, where k' = k + m + u.

    v = len(h)
    M = Matrix([wl[:m] + wl[-v:] for wl in W])  # excise dj's.
    N = M.nullspace()
    # N = [n1, ..., ns] where the ni in Const(k)^(m + v) are column
    # vectors generating the space of linear relations between
    # c1, ..., cm, e1, ..., ev.

    C = Matrix([ni[:] for ni in N])  # rows n1, ..., ns.

    return [hk.cancel(gamma, include=True) for hk in h], C
示例#14
0
def test_polymatrix_nullspace():
    M = PolyMatrix([[1, 2], [3, 6]], x)
    assert M.nullspace() == [PolyMatrix([-2, 1], x)]
    raises(ValueError, lambda: PolyMatrix([1, 2], ring=ZZ[x]).nullspace())
    raises(ValueError, lambda: PolyMatrix([1, x], ring=QQ[x]).nullspace())
    assert M.rank() == 1
示例#15
0
def test_polymatrix_eq():
    assert (PolyMatrix([x]) == PolyMatrix([x])) is True
    assert (PolyMatrix([y]) == PolyMatrix([x])) is False
    assert (PolyMatrix([x]) != PolyMatrix([x])) is False
    assert (PolyMatrix([y]) != PolyMatrix([x])) is True

    assert PolyMatrix([[x, y]]) != PolyMatrix([x, y]) == PolyMatrix([[x], [y]])

    assert PolyMatrix([x], ring=QQ[x]) != PolyMatrix([x], ring=ZZ[x])

    assert PolyMatrix([x]) != Matrix([x])
    assert PolyMatrix([x]).to_Matrix() == Matrix([x])

    assert PolyMatrix([1], x) == PolyMatrix([1], x)
    assert PolyMatrix([1], x) != PolyMatrix([1], y)
示例#16
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])
示例#17
0
def test_polymatrix():
    pm1 = PolyMatrix([[Poly(x**2, x), Poly(-x, x)],
                      [Poly(x**3, x), Poly(-1 + x, x)]])
    v1 = PolyMatrix([[1, 0], [-1, 0]], ring="ZZ[x]")
    m1 = Matrix([[1, 0], [-1, 0]], ring="ZZ[x]")
    A = PolyMatrix([[Poly(x**2 + x, x), Poly(0, x)],
                    [Poly(x**3 - x + 1, x), Poly(0, x)]])
    B = PolyMatrix([[Poly(x**2, x), Poly(-x, x)],
                    [Poly(-(x**2), x), Poly(x, x)]])
    assert A.ring == ZZ[x]
    assert isinstance(pm1 * v1, PolyMatrix)
    assert pm1 * v1 == A
    assert pm1 * m1 == A
    assert v1 * pm1 == B

    pm2 = PolyMatrix([[
        Poly(x**2, x, domain="QQ"),
        Poly(0, x, domain="QQ"),
        Poly(-(x**2), x, domain="QQ"),
        Poly(x**3, x, domain="QQ"),
        Poly(0, x, domain="QQ"),
        Poly(-(x**3), x, domain="QQ"),
    ]])
    assert pm2.ring == QQ[x]
    v2 = PolyMatrix([1, 0, 0, 0, 0, 0], ring="ZZ[x]")
    m2 = Matrix([1, 0, 0, 0, 0, 0], ring="ZZ[x]")
    C = PolyMatrix([[Poly(x**2, x, domain="QQ")]])
    assert pm2 * v2 == C
    assert pm2 * m2 == C

    pm3 = PolyMatrix([[Poly(x**2, x), S.One]], ring="ZZ[x]")
    v3 = S.Half * pm3
    assert v3 == PolyMatrix([[Poly(S.Half * x**2, x, domain="QQ"), S.Half]],
                            ring="EX")
    assert pm3 * S.Half == v3
    assert v3.ring == EX

    pm4 = PolyMatrix(
        [[Poly(x**2, x, domain="ZZ"),
          Poly(-(x**2), x, domain="ZZ")]])
    v4 = Matrix([1, -1], ring="ZZ[x]")
    assert pm4 * v4 == PolyMatrix([[Poly(2 * x**2, x, domain="ZZ")]])

    assert len(PolyMatrix()) == 0
    assert PolyMatrix([1, 0, 0, 1]) / (-1) == PolyMatrix([-1, 0, 0, -1])