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)]
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
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())
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)
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)
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 / [])
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])'
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)
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])
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
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
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
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)
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])
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])