Пример #1
0
    def test_symplectic(self):
        # the symmetric transformation matrix should be symplectic
        Pa = self.atrott
        Pb = self.btrott
        R = involution_matrix(Pa, Pb)
        S = integer_kernel_basis(R)
        N1 = N1_matrix(Pa, Pb, S)
        H,Q = symmetric_block_diagonalize(N1)
        Gamma = symmetric_transformation_matrix(Pa, Pb, S, H, Q, tol=1e-4)
        g,g = Pa.dimensions()
        J = zero_matrix(ZZ,2*g,2*g)
        Ig = identity_matrix(ZZ, g, g)
        J[:g,g:] = Ig
        J[g:,:g] = -Ig
        self.assertEqual(Gamma.T*J*Gamma,J)

        Pa = self.aklein
        Pb = self.bklein
        R = involution_matrix(Pa, Pb, tol=1e-3)
        S = integer_kernel_basis(R)
        N1 = N1_matrix(Pa, Pb, S)
        H,Q = symmetric_block_diagonalize(N1)
        Gamma = symmetric_transformation_matrix(Pa, Pb, S, H, Q, tol=1e-3)
        g,g = Pa.dimensions()
        J = zero_matrix(ZZ,2*g,2*g)
        Ig = identity_matrix(ZZ, g, g)
        J[:g,g:] = Ig
        J[g:,:g] = -Ig
        self.assertEqual(Gamma.T*J*Gamma,J)

        Pa = self.afermat
        Pb = self.bfermat
        R = involution_matrix(Pa, Pb, tol=1e-3)
        S = integer_kernel_basis(R)
        N1 = N1_matrix(Pa, Pb, S)
        H,Q = symmetric_block_diagonalize(N1)
        Gamma = symmetric_transformation_matrix(Pa, Pb, S, H, Q, tol=1e-3)
        g,g = Pa.dimensions()
        J = zero_matrix(ZZ,2*g,2*g)
        Ig = identity_matrix(ZZ, g, g)
        J[:g,g:] = Ig
        J[g:,:g] = -Ig
        self.assertEqual(Gamma.T*J*Gamma,J)

        Pa = self.a6
        Pb = self.b6
        R = involution_matrix(Pa, Pb)
        S = integer_kernel_basis(R)
        N1 = N1_matrix(Pa, Pb, S)
        H,Q = symmetric_block_diagonalize(N1)
        Gamma = symmetric_transformation_matrix(Pa, Pb, S, H, Q, tol=1e-4)
        g,g = Pa.dimensions()
        J = zero_matrix(ZZ,2*g,2*g)
        Ig = identity_matrix(ZZ, g, g)
        J[:g,g:] = Ig
        J[g:,:g] = -Ig
        self.assertEqual(Gamma.T*J*Gamma,J)
Пример #2
0
def _jordan_decomposition_odd_p(S, p):
    '''
    Input:
      S: half integral matrix
      p: prime
    Output:
      a list l = [p^n1 * u1, p^n2 * u2, ... p^nk * uk]
      such that n1 <= n2 <= ... nk and
      diag(l) is Z_p equivalent to S.
    '''
    p = Integer(p)
    acc = []
    n = len(S.columns())
    while True:
        if n == 1:
            return acc + [S[0, 0]]
        i0, j0 = find_min_ord_elet(S, p)
        if i0 != j0:
            u = identity_matrix(QQ, n)
            u[(j0, i0)] = 1
            S = bracket_action(S, u)
            j0 = i0

        S = _jordan_dcomp_diag(i0, n, S)
        acc.append(S[(0, 0)])
        S = S.submatrix(row=1, col=1)
        n -= 1
Пример #3
0
 def ideal(self, z):
     Imod = self.ideal_mod_p(z)
     A = Imod.basis_matrix().lift()
     from sage.all import identity_matrix
     p = self.p
     B = A.stack(p*identity_matrix(ZZ,8))
     V = B.row_module()
     return V
Пример #4
0
def dual_instance1(A, scale=1):
    """
    Generate dual attack basis for LWE normal form.

    :param A: LWE matrix A

    """
    q = A.base_ring().order()
    n = A.ncols()
    B = A.matrix_from_rows(range(0, n)).inverse().change_ring(ZZ)
    L = identity_matrix(ZZ, n).augment(B)
    L = L.stack(matrix(ZZ, n, n).augment(q*identity_matrix(ZZ, n)))

    for i in range(0, 2*n):
        for j in range(n, 2*n):
            L[i, j] = scale*L[i, j]

    return L
Пример #5
0
    def topologically_evaluate_regular(self, datum):
        if not datum.is_regular():
            raise ValueError('need a regular datum')

        euler_cap = {}
        torus_factor_dim = {}

        N = Set(range(len(datum.polynomials)))

        _, d, _ = split_off_torus([datum.initials[i].num for i in N])
        min_dim = datum.ambient_dim - d

        # NOTE: triangulation/"topologisation" of RationalSet instances only
        # considers cones of maximal dimension.
        if datum.RS.dim() <= min_dim - 2:
            return
            yield

        if datum.RS.dim() >= min_dim:
            raise RuntimeError('this should be impossible')

        for I in Subsets(N):
            F = [datum.initials[i].num for i in I]
            V = SubvarietyOfTorus(F, torus_dim=datum.ambient_dim)
            U,W = V.split_off_torus()
            torus_factor_dim[I] = W.torus_dim

            assert torus_factor_dim[I] >= min_dim

            if W.torus_dim > min_dim:
                continue
            euler_cap[I] = U.khovanskii_characteristic() if U.is_nondegenerate() else U.euler_characteristic()

        for I in Subsets(N):
            chi = sum((-1)**len(J) * euler_cap[I + J] for J in Subsets(N - I)
                      if torus_factor_dim[I + J] == min_dim)
            if not chi:
                continue

            I = list(I)
            id = identity_matrix(ZZ, len(I))
            def vectorise(first, k, vec):
                w = id[I.index(k)] if k in I else vector(ZZ,len(I))
                return vector(ZZ, [first] + list(vec) + list(w))

            polytopes = []
            for (i, j) in self.pairs:
                vertices = [vectorise(0, k, datum.ideals[i].initials[m].exponents()[0]) for m, k in enumerate(datum._ideal2poly[i])] +\
                           [vectorise(1, k, datum.ideals[j].initials[m].exponents()[0]) for m, k in enumerate(datum._ideal2poly[j])]
                polytopes.append(Polyhedron(vertices=vertices, ambient_dim=1+datum.ambient_dim + len(I)))
            extended_RS = (RationalSet(StrictlyPositiveOrthant(1)) * datum.RS *
                           RationalSet(StrictlyPositiveOrthant(len(I))))

            for surf in topologically_evaluate_monomial_integral(extended_RS, polytopes,
                                                                 self.integrand, dims=[min_dim+len(I)]):
                yield SURF(scalar=chi*surf.scalar, rays=surf.rays)
Пример #6
0
def _jordan_dcomp_diag(i0, n, S):
    u = perm_mat(0, i0, n)
    S = bracket_action(S, u)

    # (0, 0) elment is the min order.
    u = identity_matrix(QQ, n)
    a = S[(0, 0)]
    for j in range(1, n):
        u[(0, j)] = -S[(0, j)] / a
    return bracket_action(S, u)
Пример #7
0
def _jordan_decomposition_2(S):
    '''
    Input:
      S: half integral matrix
    Output:
      list of tuples (a, b)
      Here a is an integer which is an exponent.
      b is equal to an element of [1, 3, 5, 7] or 'h' or 'y'.
    '''
    n = len(S.columns())
    acc = []
    while True:
        i0, j0 = find_min_ord_elet(S, 2)
        if (n == 1) or (n == 2 and i0 != j0):
            mat_lst = acc + [S]
            break

        if i0 == j0:
            S = _jordan_dcomp_diag(i0, n, S)
            acc.append(S.submatrix(nrows=1, ncols=1))
            S = S.submatrix(row=1, col=1)
            n -= 1
        else:
            # (0, 1) element has the minimal order.
            S = bracket_action(S, perm_mat2(i0, j0, n))
            u = identity_matrix(QQ, n)
            for j in range(2, n):
                s00, s01, s11 = S[(0, 0)], S[(0, 1)], S[(1, 1)]
                d = s00 * s11 - s01 ** 2
                s0j = S[(0, j)]
                s1j = S[(1, j)]
                a0 = (-s11 * s0j + s01 * s1j) / d
                a1 = (s01 * s0j - s00 * s1j) / d
                u[(0, j)] = a0
                u[(1, j)] = a1
            S = bracket_action(S, u)
            acc.append(S.submatrix(nrows=2, ncols=2))
            S = S.submatrix(row=2, col=2)
            n -= 2
    res = []
    for m in mat_lst:
        if m.ncols() == 1:
            a = m[0, 0]
            e = valuation(a, two)
            u = (a / two ** e) % 8
            res.append((e, u))
        else:
            e = valuation(m[0, 1], two) + 1
            m = m / two ** (e - 1)
            if m.det() % 8 == 3:
                h_or_y = 'y'
            else:
                h_or_y = 'h'
            res.append((e, h_or_y))
    return res
Пример #8
0
def involution_matrix(Pa, Pb, tol=1e-4):
    r"""Returns the transformation matrix `R` corresponding to the anti-holomorphic
    involution on the periods of the Riemann surface.

    Given an aritrary `2g x g` period matrix `[Pa, Pb]^T` of a genus `g`
    Riemann surface `X` the action of the anti-holomorphic involution on `X` of
    these periods is given by left-multiplication by a `2g x 2g` matrix `R`.
    That is, .. math::

        [\tau P_a^T, \tau P_b^T]^T = R [P_a^T, P_b^T]^T

    Parameters
    ----------
    Pa : complex matrix
    Pb : complex matrix
        The a- and b-periods, respectively, of a genus `g` Riemann surface.
    tol : double
        (Default: 1e-4) Tolerance used to veryify integrality of transformation
        matrix. Dependent on precision of period matrices.

    Returns
    -------
    R : complex matrix
        The anti-holomorphic involution matrix.

    Todo
    ----
    For numerical stability, replace matrix inversion with linear system
    solves.
    """
    g, g = Pa.dimensions()
    R_RDF = Matrix(RDF, 2 * g, 2 * g)

    Ig = identity_matrix(RDF, g)
    M = Im(Pb.T) * Re(Pa) - Im(Pa.T) * Re(Pb)
    Minv = M.inverse()

    R_RDF[:g, :g] = (2 * Re(Pb) * Minv * Im(Pa.T) + Ig).T
    R_RDF[:g, g:] = -2 * Re(Pa) * Minv * Im(Pa.T)
    R_RDF[g:, :g] = 2 * Re(Pb) * Minv * Im(Pb.T)
    R_RDF[g:, g:] = -(2 * Re(Pb) * Minv * Im(Pa.T) + Ig)
    R = R_RDF.round().change_ring(ZZ)

    # sanity check: make sure that R_RDF is close to integral. we perform this
    # test here since the matrix returned should be over ZZ
    error = (R_RDF.round() - R_RDF).norm()
    if error > tol:
        raise ValueError(
            "The anti-holomorphic involution matrix is not "
            "integral. Try increasing the precision of the input "
            "period matrices."
        )
    return R
Пример #9
0
def poly_to_rep(f):
    """
    For a polynomial f in F[x], return the matrix corresponding to the
    left action of x on F[x]/(f).
    """
    assert f.is_monic()
    x = f.parent().gen()
    d = f.degree()
    last_column = [-f[e] for e in range(d)]
    I = identity_matrix(d)
    M = matrix(I.rows()[1:] + [last_column])
    assert M.charpoly() == f
    return M.transpose()
Пример #10
0
def complex_to_lattice(z, d, a, N=None):
    """
    Given an algebraic number z of degree d, set of up the
    lattice which tries to express a in terms of powers of z,
    where the last two colmns are weighted by N.
    """
    if N is None:
        N = ZZ(2)**(z.prec() - 10)
    nums = [z**k for k in range(d)] + [a]
    last_columns = [[round(N * real_part(x)) for x in nums],
                    [round(N * imag_part(x)) for x in nums]]
    A = matrix(identity_matrix(len(nums)).columns() + last_columns)
    return A.transpose()
Пример #11
0
    def _spanning_tree(self, root=None):
        r"""
        Return

        - a list of indices of edges that form a basis
        - a matrix projection to the basis (modulo the triangle relations)
        """
        if root is None:
            root = next(iter(self._surface.edges())).positive()

        root = self._half_edge_to_face(root)
        t = {root: None}  # face -> half edge to take to go to the root
        todo = [root]
        edges = [
        ]  # store edges in topological order to perform Gauss reduction
        while todo:
            f = todo.pop()
            for _ in range(3):
                f1 = -f
                g = self._half_edge_to_face(f1)
                if g not in t:
                    t[g] = f1
                    todo.append(g)
                    edges.append(f1)

                f = self._surface.nextInFace(f)

        # gauss reduction
        n = self._surface.size()
        proj = identity_matrix(ZZ, n)
        edges.reverse()
        for f1 in edges:
            v = [0] * n
            f2 = self._surface.nextInFace(f1)
            f3 = self._surface.nextInFace(f2)
            assert self._surface.nextInFace(f3) == f1

            i1 = f1.index()
            s1 = -1 if i1 % 2 else 1
            i2 = f2.index()
            s2 = -1 if i2 % 2 else 1
            i3 = f3.index()
            s3 = -1 if i3 % 2 else 1
            i1 = f1.edge().index()
            i2 = f2.edge().index()
            i3 = f3.edge().index()
            proj[i1] = -s1 * (s2 * proj[i2] + s3 * proj[i3])
            for j in range(n):
                assert proj[j, i1] == 0

        return (t, proj)
Пример #12
0
def involution_matrix(Pa, Pb, tol=1e-4):
    r"""Returns the transformation matrix `R` corresponding to the anti-holomorphic
    involution on the periods of the Riemann surface.

    Given an aritrary `2g x g` period matrix `[Pa, Pb]^T` of a genus `g`
    Riemann surface `X` the action of the anti-holomorphic involution on `X` of
    these periods is given by left-multiplication by a `2g x 2g` matrix `R`.
    That is, .. math::

        [\tau P_a^T, \tau P_b^T]^T = R [P_a^T, P_b^T]^T

    Parameters
    ----------
    Pa : complex matrix
    Pb : complex matrix
        The a- and b-periods, respectively, of a genus `g` Riemann surface.
    tol : double
        (Default: 1e-4) Tolerance used to veryify integrality of transformation
        matrix. Dependent on precision of period matrices.

    Returns
    -------
    R : complex matrix
        The anti-holomorphic involution matrix.

    Todo
    ----
    For numerical stability, replace matrix inversion with linear system
    solves.
    """
    g,g = Pa.dimensions()
    R_RDF = Matrix(RDF, 2*g, 2*g)

    Ig = identity_matrix(RDF, g)
    M = Im(Pb.T)*Re(Pa) - Im(Pa.T)*Re(Pb)
    Minv = M.inverse()

    R_RDF[:g,:g] = (2*Re(Pb)*Minv*Im(Pa.T) + Ig).T
    R_RDF[:g,g:] = -2*Re(Pa)*Minv*Im(Pa.T)
    R_RDF[g:,:g] = 2*Re(Pb)*Minv*Im(Pb.T)
    R_RDF[g:,g:] = -(2*Re(Pb)*Minv*Im(Pa.T) + Ig)
    R = R_RDF.round().change_ring(ZZ)

    # sanity check: make sure that R_RDF is close to integral. we perform this
    # test here since the matrix returned should be over ZZ
    error = (R_RDF.round() - R_RDF).norm()
    if error > tol:
        raise ValueError("The anti-holomorphic involution matrix is not "
                         "integral. Try increasing the precision of the input "
                         "period matrices.")
    return R
Пример #13
0
    def topologically_evaluate_regular(self, datum):
        if not datum.is_regular():
            raise ValueError('need a regular datum')

        euler_cap = {}
        torus_factor_dim = {}

        N = Set(range(len(datum.polynomials)))
        _, d, _ = split_off_torus([datum.initials[i].num for i in N])
        min_dim = datum.ambient_dim - d

        if datum.RS.dim() < min_dim:
            logger.debug('Totally irrelevant datum')
            return
            yield

        for I in Subsets(N):
            F = [datum.initials[i].num for i in I]
            V = SubvarietyOfTorus(F, torus_dim=datum.ambient_dim)
            U,W = V.split_off_torus()
            torus_factor_dim[I] = W.torus_dim
            euler_cap[I] = U.khovanskii_characteristic() if U.is_nondegenerate() else U.euler_characteristic()
            assert torus_factor_dim[I] >= min_dim

        for I in Subsets(N):
            chi = sum((-1)**len(J) * euler_cap[I+J] for J in Subsets(N-I) if torus_factor_dim[I+J] == min_dim)
            if not chi:
                logger.debug('Vanishing Euler characteristic: I = %s' % I)
                continue

            I = list(I)
            polytopes = []

            id = identity_matrix(ZZ, len(I))
            def vectorise(k, vec):
                w = id[I.index(k)] if k in I else vector(ZZ,len(I))
                return vector(ZZ, list(vec) + list(w))

            assert len(datum._ideal2poly[0]) == len(datum.ideals[0].gens)
            polytopes = [Polyhedron(vertices=[vectorise(k, datum.ideals[0].initials[m].exponents()[0]) for m,k in enumerate(datum._ideal2poly[0])],
                                    ambient_dim=datum.ambient_dim+len(I))]

            extended_RS = datum.RS * RationalSet(StrictlyPositiveOrthant(len(I)))

            assert all(extended_RS.ambient_dim == P.ambient_dim() for P in polytopes)
            for surf in topologically_evaluate_monomial_integral(extended_RS, polytopes,
                                                                 [ (1,), (0,) ],
                                                                 dims=[min_dim + len(I)],
                                                                 ):
                yield SURF(scalar=chi*surf.scalar, rays=surf.rays)
Пример #14
0
    def _compute_echelon(self):
        A = Matrix(self.parent(),
                   self.A.rows())  # we create a copy of the matrix
        U = identity_matrix(self.parent(), A.nrows())

        if (self.have_ideal):  # we do simplifications
            A = self.simplify(A)

        ## Step 1: initialize
        r = 0
        c = 0  # we look from the position (r,c)
        while (r < A.nrows() and c < A.ncols()):
            ir = self.__find_pivot(A, r, c)
            A = self.simplify(A)
            U = self.simplify(U)  # we simplify in case relations pop up

            if (ir != None):  # we found a pivot
                # We do the swapping (if needed)
                if (ir != r):
                    A.swap_rows(r, ir)
                    U.swap_rows(r, ir)

                # We do the bareiss step
                Arc = A[r][c]
                Arows = A.rows()
                Urows = U.rows()
                for i in range(r):  # we create zeros on top of the pivot
                    Aic = A[i][c]
                    A.set_row(i, Arc * Arows[i] - Aic * Arows[r])
                    U.set_row(i, Arc * Urows[i] - Aic * Urows[r])

                # We then leave the row r without change
                for i in range(r + 1,
                               A.nrows()):  # we create zeros below the pivot
                    Aic = A[i][c]
                    A.set_row(i, Aic * Arows[r] - Arc * Arows[i])
                    U.set_row(i, Aic * Urows[r] - Arc * Urows[i])

                r += 1
                c += 1

            else:  # no pivot then only advance in column
                c += 1

        # We finish simplifying the gcds in each row
        gcds = [gcd(row) for row in A]
        T = diagonal_matrix([1 / el if el != 0 else 1 for el in gcds])
        A = (T * A).change_ring(self.parent())
        U = T * U
        return A, U
Пример #15
0
def dual_instance0(A):
    """
    Generate dual attack basis.

    :param A: LWE matrix A

    """
    q = A.base_ring().order()
    B0 = A.left_kernel().basis_matrix().change_ring(ZZ)
    m = B0.ncols()
    n = B0.nrows()
    r = m - n
    B1 = matrix(ZZ, r, n).augment(q * identity_matrix(ZZ, r))
    B = B0.stack(B1)
    return B
Пример #16
0
def dual_instance0(A):
    """
    Generate dual attack basis.

    :param A: LWE matrix A

    """
    q = A.base_ring().order()
    B0 = A.left_kernel().basis_matrix().change_ring(ZZ)
    m = B0.ncols()
    n = B0.nrows()
    r = m-n
    B1 = matrix(ZZ, r, n).augment(q*identity_matrix(ZZ, r))
    B = B0.stack(B1)
    return B
Пример #17
0
        def compute_R(Gamma, H):
            H = H.change_ring(ZZ)
            g, g = H.dimensions()
            A = Gamma[:g, :g]
            B = Gamma[:g, g:]
            C = Gamma[g:, :g]
            D = Gamma[g:, g:]
            Ig = identity_matrix(ZZ, g)

            R = zero_matrix(ZZ, 2 * g, 2 * g)
            R[:g, :g] = (2 * C.T * B - A.T * H * B + Ig).T
            R[:g, g:] = 2 * D.T * B - B.T * H * B
            R[g:, :g] = -2 * C.T * A + A.T * H * A
            R[g:, g:] = -(2 * C.T * B - A.T * H * B + Ig)
            return R
Пример #18
0
        def compute_R(Gamma, H):
            H = H.change_ring(ZZ)
            g,g = H.dimensions()
            A = Gamma[:g,:g]
            B = Gamma[:g,g:]
            C = Gamma[g:,:g]
            D = Gamma[g:,g:]
            Ig = identity_matrix(ZZ,g)

            R = zero_matrix(ZZ,2*g,2*g)
            R[:g,:g] = (2*C.T*B - A.T*H*B + Ig).T
            R[:g,g:] = 2*D.T*B - B.T*H*B
            R[g:,:g] = -2*C.T*A + A.T*H*A
            R[g:,g:] = -(2*C.T*B - A.T*H*B + Ig)
            return R
Пример #19
0
    def padically_evaluate_regular(self, datum, extra_RS=None):
        if not datum.is_regular():
            raise ValueError('need a regular datum')

        # The extra variable's valuation is in extra_RS.
        if extra_RS is None:
            extra_RS = RationalSet(StrictlyPositiveOrthant(1))

        q = var('q')
        count_cap = {}
        N = Set(range(len(datum.polynomials)))

        for I in Subsets(N):
            F = [datum.initials[i].num for i in I]
            V = SubvarietyOfTorus(F, torus_dim=datum.ambient_dim)
            count_cap[I] = V.count()

            # BEGIN SANITY CHECK
            # q = var('q')
            # u, w = V.split_off_torus()
            # assert ((count_cap[I]/(q-1)**w.torus_dim).simplify_full())(q=1) == u.euler_characteristic()
            # END SANITY CHECK

        for I in Subsets(N):
            cnt = sum((-1)**len(J) * count_cap[I + J] for J in Subsets(N - I))
            if not cnt:
                continue

            I = list(I)
            id = identity_matrix(ZZ, len(I))

            def vectorise(first, k, vec):
                w = id[I.index(k)] if k in I else vector(ZZ, len(I))
                return vector(ZZ, [first] + list(vec) + list(w))

            polytopes = []
            for (i, j) in self.pairs:
                vertices = [vectorise(0, k, datum.ideals[i].initials[m].exponents()[0]) for m, k in enumerate(datum._ideal2poly[i])] +\
                           [vectorise(1, k, datum.ideals[j].initials[m].exponents()[0]) for m, k in enumerate(datum._ideal2poly[j])]
                polytopes.append(Polyhedron(vertices=vertices, ambient_dim=1 + datum.ambient_dim + len(I)))

            extended_RS = extra_RS * datum.RS * RationalSet(StrictlyPositiveOrthant(len(I)))

            foo, ring = symbolic_to_ratfun(cnt * (q - 1)**(1 + len(I)) / q**(1 + datum.ambient_dim), [var('t'), var('q')])
            corr_cnt = CyclotomicRationalFunction.from_laurent_polynomial(foo, ring)

            for z in padically_evaluate_monomial_integral(extended_RS, polytopes, self.integrand):
                yield corr_cnt * z
Пример #20
0
def _backward_RNE( rbt, IIi, Si, Vi, dVi, usemotordyn=True, Imzi=None, varify_func=None ) :
  
    from copy import copy
    
    dof = rbt.dof
    Tdhi_inv = copy(rbt.Tdhi_inv)
    Tdhi_inv.append(identity_matrix(4))
    
    Fi = range(0,dof+2)
    tau = matrix(SR,dof,1)
    
    Fi[dof+1] = copy(zero_matrix(SR,6,1))

    if usemotordyn:
      nfi_motor = [zero_matrix(3,1) for i in xrange(dof+1)]
      for mi,m in enumerate(rbt.motors):
        if Imzi == None: Im = m[0]
        else: Im = Imzi[mi]
        qm = m[1]; l = m[2]; zm = m[3]
        dqm = qm.subs(rbt.D_q_v2f).derivative(rbt.t).subs(rbt.D_q_f2v)
        ddqm = dqm.subs(rbt.D_q_v2f).derivative(rbt.t).subs(rbt.D_q_f2v)
        nfi_motor[l] += ddqm * Im * zm + dqm * Im * cross_product( Vi[l][:3,:] , zm )
    
    # Backward
    for i in range(dof,0,-1):
        Fi[i] =  Adjdual( Tdhi_inv[i+1], Fi[i+1] )  +  IIi[i] * dVi[i]  -  adjdual( Vi[i],  IIi[i] * Vi[i] )

        if usemotordyn:
          Fi[i][:3,:] += nfi_motor[i]
        
        if varify_func: Fi[i] = varify_func( Fi[i] , 'F_'+str(i) )
        
        tau[i-1,0] =  ( Si[i].transpose() *  Fi[i] )[0,0]

        if usemotordyn:
          for mi,m in enumerate(rbt.motors):
            if Imzi == None: Im = m[0]
            else: Im = Imzi[mi]
            qm = m[1]; l = m[2]; zm = m[3]
            dqm = qm.subs(rbt.D_q_v2f).derivative(rbt.t).subs(rbt.D_q_f2v)
            ddqm = dqm.subs(rbt.D_q_v2f).derivative(rbt.t).subs(rbt.D_q_f2v)
            km = qm.coeff(rbt.q[i-1,0])
            if km != 0.0:
              tau[i-1,0] += km * Im * ( ( dVi[l][:3,:] + ddqm * zm + dqm * cross_product( Vi[l][:3,:], zm ) ).transpose() * zm )[0,0]
    
    return tau
Пример #21
0
    def _compute_solution(self):
        
        A = self.echelon_form()
        b = self.transformation_matrix()*self.inhomogeneous().change_ring(self.solution_parent())

        ## We compute the solution equation by equation
        r = A.nrows()-1
        while(all(self.is_zero(el) for el in A[r])):
            r-=1
        ## A.row(r) is the first real equation
        solution = vector(self.solution_parent(), self.A.ncols()*[0])
        syzygy = identity_matrix(self.solution_parent(), self.A.ncols())
        while(r >= 0):
            M = Matrix(self.solution_parent(),[A.row(r)]).transpose()
            hs = HermiteSolver(self.solution_parent(), M, vector([b[r]]), self.__euclidean, self.__xgcd)
            ## We check the condition for having a solution
            g = hs.echelon_form()[0][0]
            quo,rem = self.__euclidean(b[r],g)
            if(rem != 0):
                raise NoSolutionError("There is no solution to equation %s = %s" %(M.transpose(), b[r]))
            
            U = hs.transformation_matrix()
            ## Solution to the particular equation (alpha + S*beta)
            alpha = quo*U.row(0)
            S = Matrix(self.solution_parent(), U.rows()[1:]).transpose()
            ##Update the general values
            solution += syzygy*alpha
            if(S.nrows() == 0): # the solution is unique
                if(self.A*solution != self.b): # the solution is not valid --> no solution to system
                    raise NoSolutionError("There is no solution to the system")
                # otherwise, we found the solution, we break the loop
                syzygy = Matrix(self.solution_parent(), [])
                break
            else:
                syzygy *= S

            ## Update the system
            b -= A*alpha
            A *= S

            # We update the index of the equation
            while(r >= 0 and all(self.is_zero(el) for el in A[r])):
                r-=1

        return self.__reduce_solution(solution, syzygy)
Пример #22
0
    def balance(self):
        if self.is_balanced():
            yield self
            return

        # If there are any, first get rid of parallel non-loops with
        # opposite signs.
        res = self._opposing_parallel_nonloop_edges()
        if res is not None:
            I = identity_matrix(self.nvertices)
            i, j = res

            for k, ell, P in zip([i, j], [j, i],
                                 dominating_cones(
                                     [self.weights[i], self.weights[j]])):
                # Now `k' dominates `ell'.

                cd = self.clone()
                cd.polyhedron &= P

                if cd.polyhedron.is_empty():
                    continue

                u, v = self.edges[k]

                assert (u, v) == self.edges[ell]

                cd.edges[ell] = make_edge(v, v)
                cd.weights[ell] += I[u] - I[v]
                yield cd
            return

        # Next, if our graph is social, do something about that.
        if not self.is_solitary():
            for z in self.desocialise():
                yield z
            return

        # Finally, deal with parallel edges that are loops or that
        # have the same sign.
        for z in self.deparallelise():
            yield z
        return
def gen_instance(n, alpha, q, m, t=1):
    D = DiscreteGaussianDistributionIntegerSampler(alpha * q / sqrt(2 * pi))
    lwe = LWE(n, q, D)
    Ac = [lwe() for _ in range(m)]
    A = matrix([a_ for a_, c_ in Ac])
    c = vector(ZZ, [c_ for a_, c_ in Ac])
    B = A.T.echelon_form()
    e = (c - A * lwe._LWE__s).change_ring(ZZ)

    def bm(x):
        return ZZ(x) if ZZ(x) < q // 2 else ZZ(x) - q

    e = vector(map(bm, e))

    N = B.change_ring(ZZ)
    S = matrix(ZZ, m - n, n).augment(q * identity_matrix(ZZ, m - n))
    L = (N.stack(S)).augment(matrix(ZZ, m, 1))
    L = L.stack(matrix(c).augment(matrix(ZZ, 1, 1, [t])))
    return L, e
Пример #24
0
    def eigenvector_with_eigenvalue(self, lin_op, lm):
        '''Let lin_op(f, t) be an endomorphsim of self and assume
        it has a unique eigenvector (up to constant) with eigenvalue lm.
        This medhod returns an eigenvector.
        '''
        basis = self.basis()
        dim = len(basis)
        if hasattr(lm, "parent"):
            K = lm.parent()
            if hasattr(K, "fraction_field"):
                K = K.fraction_field()
        else:
            K = QQ
        A = self.matrix_representaion(lin_op)
        S = PolynomialRing(K, names="x")
        x = S.gens()[0]
        f = S(A.charpoly())
        g = S(f // (x - lm))
        cffs_g = [g[y] for y in range(dim)]
        A_pws = []
        C = identity_matrix(dim)
        for i in range(dim):
            A_pws.append(C)
            C = A * C

        for i in range(dim):
            clm_i = [a.columns()[i] for a in A_pws]
            w = sum((a * v for a, v in zip(cffs_g, clm_i)))
            if w != 0:
                egvec = w
                break

        res = sum([a * b for a, b in zip(egvec, basis)])
        # TODO: Use a construction class to construct basis.
        if all(hasattr(b, "_construction") and
               b._construction is not None for b in basis):
            res._construction = sum([a * b._construction
                                     for a, b in zip(egvec, basis)])

        if hasattr(res, 'set_parent_space'):
            res.set_parent_space(self)
        return res
Пример #25
0
def integer_kernel_basis(R):
    r"""Returns the Z-basis `[S1 \\ S2]` of the kernel of the anti-holomorphic
    involution matrix `R`.

    The `2g x g` matrix `[S1 \\ S2]` represents a Z-basis of the kernel space
    .. math::

        K_\mathbb{Z} = \text{ker}(R^T - \mathbb{I}_{2g})

    That is, the basis of the space of all vectors fixed by the
    anti-holomorphic involution `R`.

    Used as input in `N1_matrix`.

    Parameters
    ----------
    R : integer matrix
        The anti-holomorphic involution matrix of a genus `g` Riemann surface.

    Returns
    -------
    S : integer matrix
        A `2g x g` matrix where each column is a basis element of the fixed
        point space of `R`.

    """
    twog, twog = R.dimensions()
    g = twog/2
    K = R.T - identity_matrix(ZZ, twog)
    r = K.rank()

    # sanity check: the rank of the kernel should be the genus of the curve
    if r != g:
        raise ValueError("The rank of the integer kernel of K should be "
                         "equal to the genus.")

    # compute the integer kernel from the Smith normal form of K
    D,U,V = K.smith_form()
    S = V[:,g:]
    return S
Пример #26
0
def integer_kernel_basis(R):
    r"""Returns the Z-basis `[S1 \\ S2]` of the kernel of the anti-holomorphic
    involution matrix `R`.

    The `2g x g` matrix `[S1 \\ S2]` represents a Z-basis of the kernel space
    .. math::

        K_\mathbb{Z} = \text{ker}(R^T - \mathbb{I}_{2g})

    That is, the basis of the space of all vectors fixed by the
    anti-holomorphic involution `R`.

    Used as input in `N1_matrix`.

    Parameters
    ----------
    R : integer matrix
        The anti-holomorphic involution matrix of a genus `g` Riemann surface.

    Returns
    -------
    S : integer matrix
        A `2g x g` matrix where each column is a basis element of the fixed
        point space of `R`.

    """
    twog, twog = R.dimensions()
    g = twog / 2
    K = R.T - identity_matrix(ZZ, twog)
    r = K.rank()

    # sanity check: the rank of the kernel should be the genus of the curve
    if r != g:
        raise ValueError("The rank of the integer kernel of K should be " "equal to the genus.")

    # compute the integer kernel from the Smith normal form of K
    D, U, V = K.smith_form()
    S = V[:, g:]
    return S
Пример #27
0
    def padically_evaluate_regular(self, datum):
        A = self.A
        n = self.nvertices
        m = self.nedges

        RS = RationalSet(PositiveOrthant(n + 1))

        polytopes = [Polyhedron(vertices=[vector(ZZ, n * [0] + [1])])]

        I = list(identity_matrix(ZZ, n + 1))

        for j in range(m):
            vertices = [vector(ZZ, n * [0] + [1])]
            for i, a in enumerate(A.column(j)):
                if a == 1:
                    vertices.append(I[i])
            polytopes.append(Polyhedron(vertices=vertices))

        for z in padically_evaluate_monomial_integral(RS, polytopes,
                                                      [(1, ) + m * (0, ),
                                                       (m + 1) * (1, )]):
            yield z
Пример #28
0
def MatrixCharpoly(coefficients):
    """
    INPUT:
        - ``coefficients`` -- an array with n + 1, where the first entry is 1
    OUTPUT:
        - a matrix A such that det(1 - t A) = R[](coefficients)
    EXAMPLES:
        sage: list(reversed(yellow.MatrixCharpoly([1,2,3]).characteristic_polynomial().list())) == [1,2,3]
            True
    TESTS: 
        sage: test_pass = True
        sage: for i in range(10):
        ....:     cf = [1] + [ZZ.random_element() for _ in range(randint(1,10))];
        ....:     test_pass = test_pass and (list(reversed(MatrixCharpoly(cf).characteristic_polynomial().list())) == cf)
        sage: print test_pass
            True
    """
    assert coefficients[0] == 1
    n = len(coefficients) - 1
    M = Matrix(1, n - 1).stack(identity_matrix(n - 1, n - 1))
    M = M.augment(-vector(reversed(coefficients[1:])))
    return M
Пример #29
0
    def padically_evaluate_regular(self, datum):
        if not datum.is_regular():
            raise ValueError('need a regular datum')

        q = var('q')
        count_cap = {}
        N = Set(range(len(datum.polynomials)))

        for I in Subsets(N):
            F = [datum.initials[i].num for i in I]
            V = SubvarietyOfTorus(F, torus_dim=datum.ambient_dim)
            count_cap[I] = V.count()

        for I in Subsets(N):
            cnt = sum((-1)**len(J) * count_cap[I+J] for J in Subsets(N-I))
            if not cnt:
                continue

            I = list(I)
            polytopes = []

            id = identity_matrix(ZZ, len(I))
            def vectorise(k, vec):
                w = id[I.index(k)] if k in I else vector(ZZ,len(I))
                return vector(ZZ, list(vec) + list(w))

            assert len(datum._ideal2poly[0]) == len(datum.ideals[0].gens)
            polytopes = [Polyhedron(vertices=[ vectorise(k, datum.ideals[0].initials[m].exponents()[0]) for m,k in enumerate(datum._ideal2poly[0]) ], ambient_dim=datum.ambient_dim+len(I))]

            extended_RS = datum.RS * RationalSet(StrictlyPositiveOrthant(len(I)))

            foo, ring = symbolic_to_ratfun(cnt * (q - 1)**len(I) / q**datum.ambient_dim, [var('t'), var('q')])
            corr_cnt = CyclotomicRationalFunction.from_laurent_polynomial(foo, ring)

            assert all(extended_RS.ambient_dim == P.ambient_dim() for P in polytopes)

            for z in padically_evaluate_monomial_integral(extended_RS, polytopes, [ (1,), (0,) ]):
                yield corr_cnt * z
Пример #30
0
    def __init__(self, fund_group):
        self.domain_gens = fund_group.generators()
        ab_words = [
            abelianize_word(R, self.domain_gens)
            for R in fund_group.relators()
        ]
        if not ab_words:
            n = fund_group.num_generators()
            self.elementary_divisors = n * [
                0,
            ]
            self.U = identity_matrix(n)
        else:
            R = matrix(ZZ, ab_words).transpose()
            D, U, V = R.smith_form()
            m = U.nrows()
            assert m == D.nrows()
            d = min(D.nrows(), D.ncols())
            diag = D.diagonal()
            num_ones = diag.count(1)
            self.elementary_divisors = diag[num_ones:] + [
                0,
            ] * (m - d)
            self.U = U[num_ones:]

        tor = [d for d in self.elementary_divisors if d != 0]
        free = [d for d in self.elementary_divisors if d == 0]
        names = []
        if len(tor) == 1:
            names.append('u')
        else:
            names += ['u%d' % i for i in range(len(tor))]
        if len(free) == 1:
            names.append('t')
        else:
            names += ['t%d' % i for i in range(len(free))]
        self._range = AbelianGroup(self.elementary_divisors, names=names)
Пример #31
0
def gen_massmatrix_RNE( do_varify, rbt, usemotordyn = True, varify_trig = True ):
  
    from copy import deepcopy
    
    Si = _gen_rbt_Si(rbt)
    
    IIi = range(0,rbt.dof+1)
    ### Linear dynamic parameters:
    for i in range(1,rbt.dof+1): IIi[i] = block_matrix( [ rbt.Ifi[i] , skew(rbt.mli[i]) , -skew(rbt.mli[i]) , rbt.mi[i]*identity_matrix(3) ] ,subdivide=False)
    ### Not linear dynamic parameters:
    #for i in range(1,dof+1): IIi[i] = block_matrix( [ rbt.Ifi_from_Ici[i] , skew(rbt.mli_e[i]) , -skew(rbt.mli_e[i]) , rbt.mi[i]*identity_matrix(3) ] ,subdivide=False)
    
    def custom_simplify( expression ):
        #return trig_reduce(expression.expand()).simplify_rational()
        return expression.simplify_rational()
    
    varify_func = None
    
    if do_varify:
        auxvars = []
        def varify_func(exp,varrepr):
            if varify_trig : exp = exp.subs( LoP_to_D(rbt.LoP_trig_f2v) )
            exp = custom_simplify( exp )
            return m_varify(exp, auxvars, poolrepr='auxM', condition_func=is_compound)
    
    M = matrix(SR,rbt.dof,rbt.dof)
    
    rbttmp = deepcopy(rbt)
    rbttmp.grav = zero_matrix(3,1)
    rbttmp.dq = zero_matrix(rbttmp.dof,1)
    
    for i in range(M.nrows()):
        rbttmp.ddq = zero_matrix(rbttmp.dof,1)
        rbttmp.ddq[i,0] = 1.0
        rbttmp.gen_geom()
        
        Vi, dVi = _forward_RNE( rbttmp, Si, varify_func )
        Mcoli = _backward_RNE( rbttmp, IIi, Si, Vi, dVi, usemotordyn, None, varify_func = varify_func )
        
        # Do like this since M is symmetric:
        M[:,i] = matrix(SR,i,1,M[i,:i].list()).stack( Mcoli[i:,:] )
    
    if do_varify:
        if varify_trig : auxvars = rbt.LoP_trig_v2f + auxvars
        return auxvars , M
    else:
        return M
Пример #32
0
    def t1_prime(self, n=5, p=65521):
        """
        Return a multiple of element t1 of the Hecke algebra mod 2,
        computed using the Hecke operator $T_n$, where n is self.n.
        To make computation faster we only check if ...==0 mod p.
        Hence J will contain more elements, hence we get a multiple.
        
        INPUT:
        
            - `n` -- integer (optional default=5)
            - `p` -- prime (optional default=65521)

        OUTPUT:

            - a mod 2 matrix

        EXAMPLES::

            sage: from mdsage import *
            sage: C = KamiennyCriterion(29)
            sage: C.t1_prime()
            22 x 22 dense matrix over Finite Field of size 2 (use the '.str()' method to see the entries)
            sage: C.t1_prime(n=3) == 1
            True
            sage: C = KamiennyCriterion(37)
            sage: C.t1_prime()[0]
            (1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0)
        """
        if self.verbose: tm = cputime(); mem = get_memory_usage(); print "t1 start"
        T = self.S.hecke_matrix(n)
        if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "hecke 1"
        f = self.hecke_polynomial(n) # this is the same as T.charpoly()
        if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "char 1"
        Fint = f.factor()
        if all(i[1]!=1 for i in Fint):
            return matrix_modp(zero_matrix(T.nrows()))
        #    raise ValueError("T_%s needs to be a generator of the hecke algebra"%n)
        if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "factor 1, Fint = %s"%(Fint)
        R = f.parent().change_ring(GF(p))
        F = Fint.base_change(R)
        # Compute the iterators of T acting on the winding element.
        e = self.M([0, oo]).element().dense_vector().change_ring(GF(p))
        if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "wind"
        t = matrix_modp(self.M.hecke_matrix(n).dense_matrix(), p)
        if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "hecke 2"
        g = t.charpoly()
        if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "char 2"
        Z = t.iterates(e, t.nrows(), rows=True)
        if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "iter"
        # We find all factors F[i][0] for f such that
        # (g/F[i][0])(t) * e = 0.
        # We do this by computing the polynomial
        #       h = g/F[i][0],
        # turning it into a vector v, and computing
        # the matrix product v * Z.  If the product
        # is 0, then e is killed by h(t).
        J = []
        for i in range(len(F)):
            if F[i][1]!=1:
                J.append(i)
                continue
            h, r = g.quo_rem(F[i][0] ** F[i][1])
            assert r == 0
            v = vector(GF(p), h.padded_list(t.nrows()))
            if v * Z == 0:
                J.append(i)
        if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "zero check"

        if self.verbose: print "J =", J
        if len(J) == 0:
            # The annihilator of e is the 0 ideal.
            return matrix_modp(identity_matrix(T.nrows()))

        # Finally compute t1.  I'm concerned about how
        # long this will take, so we reduce T mod 2 first.

        # It is important to call "self.T(2)" to get the mod-2
        # reduction of T2 with respect to the right basis (e.g., the
        # integral basis in case use_integral_structure is true.
        Tmod2 = self.T(n)
        if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "hecke mod" 
        g = prod(Fint[i][0].change_ring(GF(2)) ** Fint[i][1] for i in J)
        if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "g has degree %s"%(g.degree())
        t1 = g(Tmod2)
        if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "t1 finnished"
        return t1        
Пример #33
0
def perm_mat2(i, j, n):
    # (i, j) => (0, 1)
    l = identity_matrix(QQ, n).columns()
    rem = [a for a in range(n) if a not in (i, j)]
    l1 = [l[i], l[j]] + [l[a] for a in rem]
    return matrix(QQ, l1).transpose()
Пример #34
0
def padic_smith_form(M, transformation=True):
    r"""
    this uses a rank-1 reduction method
    see: https://uwspace.uwaterloo.ca/bitstream/handle/10012/12241/Elsheikh_Mustafa.pdf Chapter 4
    and is very similar to the p-adic smith form implemented in sage with exact=False
    they find U and V  in Z/p^prec such that
    st U*M*V = diag(elementary divisors) mod p^prec

    On the contrary, we are interested in keep track of loss of precision
    thus we compute U and V where some entries might have lower precision
    U*M*V = diag(elementary divisors) modp^(prec - v)
    where v is the highest valuation of the nonzero elementary divisors that we could detect
    some entries of U and V might have more precision that `prec-v`

    EXAMPLES::

    sage: from crystalline_obstruction.main import padic_smith_form
    sage: entries = [0, 5664461354126771, 12212357361910300, 15947020959157478, 0, 16792952041597449, 9399124951373949, 4818530271686800, 0, 14690359073749623, 11237259451999884, 5117434014428142, 15157488677243483, 9004103062307752, 20761679499270441, 4817969886991856, 19925864281756441, 12021725322600663, 4620722392655416, 5445142895231681, 6605357538252496, 7608812697273777, 18542817615638637, 18194689690271501, 16298292917596268,5029914121037969, 9960884344083847, 0, 20341333098836812, 12117922812876054, 1270149214447437, 0, 10999401748338075, 9493559500408195, 10612080564946174, 0, 4620722392655416, 10891113386038365, 956055025271903, 2162842206467093, 18542817615638637, 1143972982339214, 336113117292612, 469148515686007, 9960884344083847, 13128267973348003, 15817056104759912, 20531311511260484, 13598045280630823, 7585782589268305, 14053895308766769, 3065047087418756, 15664512169571917, 913325863843049]
    sage: M = Matrix(ZpCA(43, prec=10, print_mode='val-unit'), 6, 9, entries)
    sage: S, U, V = padic_smith_form(M)
    sage: S.diagonal()
    [43 * 1 + O(43^10),
     43 * 1 + O(43^10),
     43^2 * 1 + O(43^10),
     43^9 * 1 + O(43^10),
     O(43^10),
     O(43^10)]
    sage: (U*M*V).diagonal()
    [43 * 1 + O(43^10),
     43 * 1 + O(43^10),
     43^2 * 1 + O(43^10),
     O(43^9),
     O(43^2),
     O(43^2)]
    sage: sS, sU, sV = M.smith_form(exact=False)
    sage: (sS, sU, sV) == (S, U, V)
    True
    sage: V.column(4)
    (34 + O(43), 30 + O(43), 38 + O(43), 9 + O(43), 1 + O(43^10), O(43^10), O(43^10), O(43^10), O(43^10))
    sage: sV.column(4)
    (13694996109475306 + O(43^10), 1917185461381533 + O(43^10), 113132459648579 + O(43^10), 9 + O(43^10), 1 + O(43^10), O(43^10), O(43^10), O(43^10), O(43^10))
    """

    n = M.nrows()
    m = M.ncols()
    if m > n:
        if transformation:
            S, U, V = padic_smith_form(M.transpose(), transformation)
            return S.transpose(), V.transpose(), U.transpose()
        else:
            return padic_smith_form(M.transpose(), transformation)

    R = M.base_ring()
    s = [R.zero()] * m
    S = copy(M)
    left = identity_matrix(R, n)
    right = identity_matrix(R, m)
    smith = M.parent()(0)

    val = -infinity

    def find_pivot(l):
        minval = infinity
        ans = None
        for i in range(l, n):
            for j in range(l, m):
                elt = S[i, j]
                if elt != 0 and elt.valuation() < minval:
                    minval = elt.valuation()
                    ans = minval, i, j
                    if minval == val:  # we can't get lower
                        return ans
        return ans

    for l in range(n):
        pos = find_pivot(l)
        if pos:
            val, i, j = pos
        else:
            # the matrix is all zeros
            break
        s[l] = R.one() << val
        smith[l, l] = s[l]
        S.swap_rows(i, l)
        S.swap_columns(j, l)
        if transformation:
            left.swap_rows(i, l)
            right.swap_columns(j, l)
        w = (S[l, l] >> val).inverse_of_unit()
        # this corresponds to S = S - w*(M*x)*(y*M)
        # where x = ej, y =ei
        for i in range(l + 1, n):
            x = -w * (S[i, l] >> val
                      )  # we know that has val is the current min valuation
            S.add_multiple_of_row(i, l, x, l + 1)
            if transformation:
                left.add_multiple_of_row(i, l, x)
        if transformation:
            left.rescale_row(l, w)
            for j in range(l + 1, m):
                right.add_multiple_of_column(j, l, -w * (S[l, j] >> val))
    if transformation:
        return smith, left, right
    else:
        return s
def ad_bracket(A, p):
    if p == A.ncols():
        return identity_matrix(A.base_ring(), 1)
    l = permutations_increasing(A.ncols(), p)
    return matrix([[_ad_bracket_coeffs(A, b, a) for b in l] for a in l])
def bracket_power(A, p):
    if p == 0:
        return identity_matrix(A.base_ring(), 1)
    l = permutations_increasing(A.ncols(), p)
    return matrix([[sub_mat(A, a, b).det() for b in l] for a in l])
Пример #37
0
def symmetric_block_diagonalize(N1):
    r"""Returns matrices `H` and `Q` such that `N1 = Q*H*Q.T` and `H` is block
    diagonal.

    The algorithm used here is as follows. Whenever a row operation is
    performed (via multiplication on the left by a transformation matrix `q`)
    the corresponding symmetric column operation is also performed via
    multiplication on the right by `q^T`.

    For each column `j` of `N1`:

    1. If column `j` consists only of zeros then swap with the last column with
       non-zero entries.

    2. If there is a `1` in position `j` of the column (i.e. a `1` lies on the
       diagonal in this column) then eliminate further entries below as in
       standard Gaussian elimination.

    3. Otherwise, if there is a `1` in the column, but not in position `j` then
       rows are swapped in a way that it appears in the position `j+1` of the
       column. Eliminate further entries below as in standard Gaussian
       elimination.

    4. After elimination, if `1` lies on the diagonal in column `j` then
       increment `j` by one. If instead the block matrix `[0 1 \\ 1 0]` lies
       along the diagonal then eliminate under the `(j,j+1)` element (the upper
       right element) of this `2 x 2` block and increment `j` by two.

    5. Repeat until `j` passes the final column or until further columns
       consists of all zeros.

    6. Finally, perform the appropriate transformations such that all `2 x 2`
       blocks in `H` appear first in the diagonalization. (Uses the
       `diagonal_locations` helper function.)

    Parameters
    ----------
    N1 : GF(2) matrix

    Returns
    -------
    H : GF(2) matrix
        Symmetric `g x g` matrix where the diagonal elements consist of either
        a "1" or a `2 x 2` block matrix `[0 1 \\ 1 0]`.
    Q : GF(2) matrix
        The corresponding transformation matrix.
    """
    g = N1.nrows()
    H = zero_matrix(GF(2), g)
    Q = identity_matrix(GF(2), g)

    # if N1 is the zero matrix the H is also the zero matrix (and Q is the
    # identity transformation)
    if (N1 % 2) == 0:
        return H, Q

    # perform the "modified gaussian elimination"
    B = Matrix(GF(2), [[0, 1], [1, 0]])
    H = N1.change_ring(GF(2))
    j = 0
    while (j < g) and (H[:, j:] != 0):
        # if the current column is zero then swap with the last non-zero column
        if H.column(j) == 0:
            last_non_zero_col = max(k for k in range(j, g) if H.column(k) != 0)
            Q.swap_columns(j, last_non_zero_col)
            H = Q.T * N1 * Q

        # if the current diagonal element is 1 then gaussian eliminate as
        # usual. otherwise, swap rows so that a "1" appears in H[j+1,j] and
        # then eliminate from H[j+1,j]
        if H[j, j] == 1:
            rows_to_eliminate = (r for r in range(g) if H[r, j] == 1 and r != j)
            for r in rows_to_eliminate:
                Q.add_multiple_of_column(r, j, 1)
            H = Q.T * N1 * Q
        else:
            # find the first non-zero element in the column after the diagonal
            # element and swap rows with this element
            first_non_zero = min(k for k in range(j, g) if H[k, j] != 0)
            Q.swap_columns(j + 1, first_non_zero)
            H = Q.T * N1 * Q

            # eliminate *all* other ones in the column, including those above
            # the element (j,j+1)
            rows_to_eliminate = (r for r in range(g) if H[r, j] == 1 and r != j + 1)
            for r in rows_to_eliminate:
                Q.add_multiple_of_column(r, j + 1, 1)
            H = Q.T * N1 * Q

        # increment the column based on the diagonal element
        if H[j, j] == 1:
            j += 1
        elif H[j : (j + 2), j : (j + 2)] == B:
            # in the block diagonal case, need to eliminate below the j+1 term
            rows_to_eliminate = (r for r in range(g) if H[r, j + 1] == 1 and r != j)
            for r in rows_to_eliminate:
                Q.add_multiple_of_column(r, j, 1)
            H = Q.T * N1 * Q
            j += 2

    # finally, check if there are blocks of "special" form. that is, shift all
    # blocks such that they occur first along the diagonal of H
    index_one, index_B = diagonal_locations(H)
    while index_one < index_B:
        j = index_B

        Qtilde = zero_matrix(GF(2), g)
        Qtilde[0, 0] = 1
        Qtilde[j, 0] = 1
        Qtilde[j + 1, 0] = 1
        Qtilde[0, j] = 1
        Qtilde[0, j + 1] = 1
        Qtilde[j : (j + 2), j : (j + 2)] = B

        Q = Q * Qtilde
        H = Q.T * N1 * Q

        # continue until none are left
        index_one, index_B = diagonal_locations(H)

    # above, we used Q to store column operations on N1. switch to rows
    # operations on H so that N1 = Q*H*Q.T
    Q = Q.T.inverse()
    return H, Q
Пример #38
0
    def support(self, basis):
        # Input:  a basis in H**0( D_0) for H**0((g+1)\infty - E), where E is an effective divisor of degree g/2
        # Output: returns the support of E as a list of g points 
 
        # Computing the intersection of 
        # <1, x, x**2,..., x**g> with <basis>
        B = basis.augment( identity_matrix(self.g + 1).stack(Matrix(basis.nrows() - (self.g + 1), (self.g + 1))))
        KB, upper, lower  = Kernel(B, basis.ncols() + self.g )
        if self.verbose:
            print "KB upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        maxlower = self.lower
        
        result = [None for _ in range(self.g)]
        
        # if dim of the intersection of <1, x, x**2,..., x**g> with <basis> is 1
        if self.threshold_check(upper, lower):
            # we have the expected rank, all the roots are simple, unless E = 2*P
            # as in genus = 2 we can't have E = tau(P) + P
            maxlower = max(maxlower, lower);

            Rw = PolynomialRing(self.Rdoubleextraprec, "T")
            poly = Rw( KB.column(0)[-(self.g + 1):].list() )
            
            if self.g == 2:
                a, b, c = list(poly)
                disc = (b**2 - 4*a*c).abs()
                #a2 = (a**2).abs()
                dpoly = poly.derivative()
                if self.threshold_check((a**2).abs(), disc):
                    xcoordinates = dpoly.complex_roots() + dpoly.complex_roots()
                    maxlower = max(maxlower, disc);
                else:
                    xcoordinates = poly.complex_roots()
            else:
                xcoordinates = poly.complex_roots()

            for i, x in enumerate(xcoordinates):
                    y0 = self.Rextraprec(sqrt(self.f(x)));
                    x0 = self.Rextraprec(x)
                    vp = vector(self.R, [x0**u * y0**v for u, v in self.Vexps[:basis.nrows()] ]);
                    vn = vector(self.R, [x0**u * (-y0)**v for u, v in self.Vexps[:basis.nrows()] ]);
                    np = norm( vp * basis);
                    nn = norm( vn * basis);
                    #is it a simple root?
                    if dpoly(x).abs() < self.notzero:
                        assert self.g == 2, "one needs to be extra careful for genus > 2" 
                        
                    if self.threshold_check(np, nn) and not self.threshold_check(nn, np): #np > nn ~ 0
                        result[i] = (x0, -y0);
                        maxlower = max(maxlower, nn);
                    elif  not self.threshold_check(np, nn) and self.threshold_check(nn, np): #nn > np ~ 0
                        result[i] = (x0, y0);
                        maxlower = max(maxlower, np);

                    else:
                        print "sign for y is not clear: neg = %s, pos = %s,\ny = %s + %s * I = 0?" % tuple(vector(RealField(15), (nn, np, y0.real(), y0.imag())));
                        if nn > np:
                            result[i] = (x0, y0);
                            maxlower = max(maxlower, np);

                        else:
                            result[i] = (x0, -y0);
                            maxlower = max(maxlower, nn);

#                    else:
#                        assert self.g == 2, "for now only genus 2"
#                        # for g = 2,  we can't have E = P + tau(P), as (x - x0) \in H**0((g+1)\infty - E)
#                        # thus the rank of B should be at most  basis.ncols() + 1
#                        for j, xj in enumerate(xcoordinates[i+1:]):
#                            if (x0 - xj).abs() < self.notzero:
#                                # we might have a double root, and at the moment this should only work for g == 2
#                                break;
#                        #j is the other root 
#                        if self.threshold_check(np, nn) and not self.threshold_check(nn, np):
#                            result[j] = result[i] = (x0, -y0);
#                        elif not self.threshold_check(np, nn) and self.threshold_check(nn, np):
#                            result[j] = result[i] = (x0, y0);
#                        else:
#                            #this covers the case that y0 ~ 0
#                            if self.f(x0) > self.almostzero:
#                                print "sign for y is not clear: neg = %.2e, pos = %.2e,\nassuming y = %.2e + %.2e * I = 0" % (nn, np, y0.real(), y0.imag());
#                            result[j] = result[i] = (x0, 0);
#                    
#                                
            return result, maxlower;
        else:
            if self.verbose:
                print "there is at least a root at infinity, i.e. \inf_{+,-} \in supp E"
                print (RealField(35)(upper), RealField(35)(lower))
            # there is at least a root at infinity, i.e. \inf_{+,-} \in supp E
            # recall that \inf_{+} + \inf_{-} ~ P + tau(P), and in this case we have booth roots at infinity 
            assert self.g == 2, "for now only genus 2"


            Ebasis, upper, lower = EqnMatrix(basis,  basis.ncols() )
            assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
            maxlower = max(maxlower, lower);

            B = basis.augment( identity_matrix(self.g ).stack(Matrix(basis.nrows() - (self.g ), (self.g ))))
            KB, upper, lower  = Kernel(B, basis.ncols() + self.g - 1 )

            # 1 \in <basis>
            v0 = vector(self.R, [0] * basis.nrows())
            v0[0] = 1
            norm_one = norm(Ebasis * v0)
      
            if not self.threshold_check(upper, lower):
                # dim <1, x> cap <basis> = 2

                #1 \in <basis>
                assert self.threshold_check(1, norm_one),  "upper = %s lower = %s norm_one = %s " % (RealField(35)(upper), RealField(35)(lower), RealField(35)(norm_one));
                maxlower = max(maxlower, norm_one);
                
                #x \in <basis>

                vx = vector(self.R, [0]*basis.nrows())
                vx[1] = 1
                lower = norm(Ebasis * vx)
                assert self.threshold_check(1, lower), "lower = %s" % (RealField(35)(lower),);
                maxlower = max(maxlower, lower);
                
                vx2 = vector(self.R, [0]*basis.nrows())
                vx2[2] = 1
                lower = norm(Ebasis * vx2)
                if self.threshold_check(1, lower):
                    # E = \inf_{+} + \inf_{-} 
                    # <1, x, x^2>  \in H**0((g+1)\infty - E)
                    # x \in H^0 => 0 + 2 \infty - E >= 0
                    # x^2 \in H^0 => 4 * P_0 + \infty - E >= 0 for all P0

                    maxlower = max(maxlower, lower);
                    return [+Infinity, -Infinity], maxlower

                # <1, x>  \in H**0((g+1)\infty - E)
                # but not x^2
                # supp(E) \subsetneq { \inf_{+}, \inf_{-}  }
                if self.f.degree() % 2 == 0:
                    # we need to figure out the sign at infinity
                    Maug = Matrix(basis.nrows() - self.g - 1, self.g + 1).stack(identity_matrix(self.g + 1))
                    B = basis.augment( Maug )
                    KB, upper, lower  = Kernel(B, basis.ncols() + self.g )

                    a, b, c = KB.column(0)[-(2 + 1):].list()
                    assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))

                    tmp = (-b/c) / sqrt(self.f.list()[-1]);
                    assert self.threshold_check( tmp.real(), tmp.imag()), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
                    infsign = round(tmp.real());
                    assert infsign in [1, -1]


                    return [infsign*Infinity, infsign*Infinity], maxlower


                return [+Infinity, +Infinity], maxlower
            else:
                maxlower = max(maxlower, lower);
                #1 \notin <basis>
                assert self.threshold_check(norm_one),  "upper = %s lower = %s norm_one = %s " % (RealField(35)(upper), RealField(35)(lower), RealField(35)(norm_one));
                        
                        
            Rw = PolynomialRing(self.Rdoubleextraprec, "T")
            xcoordinates = Rw(KB.column(0)[-(self.g):].list()).complex_roots()
            assert len(xcoordinates) == 1;
            x0 = xcoordinates[0];
            y0 = self.Rextraprec(sqrt(self.f(x0)));

                        
            
            # if dim <1, x, x**2> cap <basis> >= 2
            # then dim <1, x> cap <basis> >= 1

            
            
            
            # we must have <1, x> \subset <basis>

            # double check that (x - x0) and (x - x0)**2 are in <basis>
            
            # (x - x0)
            v1 = vector(self.R, [0]*basis.nrows())
            v1[0] = -x0
            v1[1] = 1
            lower = norm(Ebasis * v1)
            assert self.threshold_check(1, lower), "lower = %s" % (RealField(35)(lower),);
            maxlower = max(maxlower, lower);

            # (x - x0)**2
            v2 = vector(self.R, [0]*basis.nrows())
            v2[0] = x0**2
            v2[1] = - 2*x0
            v2[2] = 1
            lower = norm(Ebasis * v2)
            assert self.threshold_check(1, lower), "lower = %s" % (RealField(35)(lower),);

            maxlower = max(maxlower, lower);

            
            # (x - x0)**3
            v3 = vector(self.R, [0]*basis.nrows())
            v3[0] = -x0**3
            v3[1] = 3*x0**2
            v3[2] = -3*x0
            v3[3] = 1
            nc = norm(Ebasis * v3)
            
            
            vp = vector(self.R, [x0**i * y0**j for i,j in self.Vexps[:basis.nrows()]]);
            vn = vector(self.R, [x0**i * (-y0)**j for i,j in self.Vexps[:basis.nrows()]]);

            np = norm( vp * basis);
            nn = norm( vn * basis);
            

            # either E = P + \inf_{+/-} 
            # or E = P + tau(P)   with P != \inf_{*}, but in this case E ~ \inf_+ + \inf_-        

            if self.threshold_check(np, nn) and not self.threshold_check(nn, np): #np > nn ~ 0
                result[0] = (x0, -y0);
                maxlower = max(maxlower, nn);

            elif not self.threshold_check(np, nn) and self.threshold_check(nn, np): #nn > np ~ 0
                result[0]  = (x0, y0);
                maxlower = max(maxlower, np);

            else:
                if self.threshold_check(1,nc) and self.threshold_check(1,np) and self.threshold_check(1,nn):
                    result[0] = (x0, y0)
                    result[1] = (x0, -y0)
                    maxlower = max(maxlower, nc, np, nn);
                    # this is equivalent to:  return result, maxlower
                    return [+Infinity, -Infinity], maxlower
                if self.f(x0) > self.almostzero :
                    print "sign for y is not clear: neg = %s, pos = %s,\nassuming y = %s + %s * I = 0" % tuple( vector( RealField(15), (nn, np, y0.real(), y0.imag())));
                result[0] = (x0, 0);
            
            # E = P + \inf_{+/-} 
            # P = result[0]
            x0, y0 = result[0]



            # Now figure out what infinity is in the supp of E
            # by checking if   y - s*x**(g+1) - (y0 - s*x0**(g+1)) \in <basis>
            # for s = sign * sqrt(an)
            sqrtan =  self.Rextraprec( sqrt( self.an) );
            # vp -> no pole at inf_{+} -> inf_{+} \in supp E
            vp = vector(self.R, [0]*basis.nrows())
            # vn -> no pole at inf_{-} -> inf_{-} \in supp E
            vn = vector(self.R, [0]*basis.nrows())
            vp[0] = -(y0 - sqrtan*x0**(self.g + 1))
            vn[0] = -(y0 + sqrtan*x0**(self.g + 1))
            vp[self.g + 1] = -sqrtan
            vn[self.g + 1] = sqrtan
            vp[self.g + 2] = 1
            vn[self.g + 2] = 1
            
            np = norm( Ebasis * vp );
            nn = norm( Ebasis * vn );

            


            if self.threshold_check(np * nc, nn) and not self.threshold_check(nn * nc, np) and not self.threshold_check(nn * np, nc): #np * nc > nn ~ 0
                maxlower = max(maxlower, nn);
                result[1] = -Infinity ;
            elif not self.threshold_check(np * nc, nn) and self.threshold_check(nn * nc, np) and not self.threshold_check(nn * np, nc): #nn * nc > np ~ 0
                maxlower = max(maxlower, np);
                result[1] = +Infinity
            elif not self.threshold_check(np * nc, nn) and not self.threshold_check(nn * nc, np) and self.threshold_check(nn * np, nc): # np*nn > nc
                # this should have been rulled out before, but now it looks more likely to have P + tau(P)
                # instead of E = P + inf
                maxlower = max(maxlower, nc);
                #this is equivalent to: result[1] = (x0, -y0)
                result = [+Infinity, -Infinity]
            else:
                print "inf_{?} \in supp E not clear: neg = %s, pos = %s, conj = %s" % tuple(vector(RealField(15),(nn, np, nc)));
                mn = min(nn, np, nc)
                maxlower = max(maxlower, mn);
                if np == mn:
                    result[1] = +Infinity;
                elif nn == mn:
                    result[1] = -Infinity;
                elif nc == mn:
                    #this is equivalent to: result[1] = (x0, -y0)
                    result = [+Infinity, -Infinity]
                else:
                    assert False, "something went wrong"
            return result, maxlower
Пример #39
0
def prune_dg_module_on_poset(dgm, ab, verbose=False, assume_sorted=False):
    a, b = ab
    tv = dgm.cat.objects[0]
    ring = dgm.ring
    cat = dgm.target_cat
    #diff_dict = {d:dgm.differential(tv, (d,)) for d in range(a - 1, b + 1)}
    diff_dict = {}
    for d in range(a - 1, b + 1):
        if verbose:
            print('computing differential in degree ' + str(d))
        diff_dict[d] = dgm.differential(tv, (d,))
    if verbose:
        print('original differentials computed')

    # Since we assume that cat is a poset,
    # we may convert the differentials to usual sagemath matrices
    # as long as we keep track of the row labels.
    #
    # triv = cat.trivial_representation(ring)
    # m_dict = {}
    # for d in range(a - 1, b + 1):
    #     m_dict[d] = triv(diff_dict[d])

    m_dict = {}
    for d in range(a - 1, b + 1):
        if verbose:
            print('Expanding the differential in degree ' + str(d))
        entries = []
        z = 0
        dv = diff_dict[d].data_vector
        source = diff_dict[d].source
        target = diff_dict[d].target
        for x in source:
            for y in target:
                if len(cat.hom(x, y)) == 1:
                    entries += [dv[z]]
                    z += 1
                else:
                    entries += [ring(0)]
        m_dict[d] = matrix(ring, len(source), len(target), entries)

    # This dict will keep track of the row labels
    m_source = {}
    # and dict will keep track of the target labels
    m_target = {}

    if assume_sorted:
        for d in range(a - 1, b + 1):
            for x in cat.objects:
                m_source[d, x] = 0
                m_target[d, x] = 0
                for y in diff_dict[d].source:
                    if x == y:
                        m_source[d, x] += 1
                for y in diff_dict[d].target:
                    if x == y:
                        m_target[d, x] += 1
            source_assumed = [x for x in cat.objects for _ in range(m_source[d, x])]
            if diff_dict[d].source != source_assumed:
                raise ValueError('This dgModule is not sorted in degree ' + str(d))
    else:
        # Time to sort the rows
        for d in range(a - 1, b + 1):
            targ = m_dict[d].ncols()
            rows = m_dict[d].rows()
            new_rows = []
            for x in cat.objects:
                m_source[d, x] = 0
                for i, r in enumerate(rows):
                    if diff_dict[d].source[i] == x:
                        m_source[d, x] += 1
                        new_rows += [r]
            if len(new_rows) == 0:
                m_dict[d] = zero_matrix(ring, 0, targ)
            else:
                m_dict[d] = block_matrix(ring, [[matrix(ring, 1, targ, list(r))] for r in new_rows])

        # and now the columns
        for d in range(a - 1, b + 1):
            sour = m_dict[d].nrows()
            cols = m_dict[d].columns()
            new_cols = []
            for x in cat.objects:
                m_target[d, x] = 0
                for i, c in enumerate(cols):
                    if diff_dict[d].target[i] == x:
                        m_target[d, x] += 1
                        new_cols += [c]
            if len(new_cols) == 0:
                m_dict[d] = zero_matrix(ring, sour, 0)
            else:
                m_dict[d] = block_matrix(ring, [[matrix(ring, sour, 1, list(c)) for c in new_cols]])

    # if verbose:
    #     for d in range(a - 1, b + 1):
    #         print
    #         print [m_source[d, x] for x in cat.objects]
    #         for r in m_dict[d]:
    #             print r
    #         print [m_target[d, x] for x in cat.objects]

    # Find the desired row- and column-operations
    # and change the labels (slightly prematurely)
    for d in range(a, b):
        for x in cat.objects:
            upper_left = m_dict[d][:m_source[d, x], :m_target[d, x]]
            if verbose:
                print('Computing Smith form of a matrix with dimensions ' + str(upper_left.dimensions()))
            dropped, sc, sr, tc, tr = prune_matrix(upper_left)
            if verbose:
                print('Dropping ' + str(dropped) + ' out of ' + str(m_source[d, x]) + \
                      ' occurrences of ' + str(x) + ' in degree ' + str(d - 1))
            m_target[d - 1, x] -= dropped
            m_source[d + 1, x] -= dropped
            cid = m_dict[d - 1].ncols() - sc.nrows()
            zul = zero_matrix(ring, sc.nrows(), cid)
            zlr = zero_matrix(ring, cid, sc.ncols())
            m_dict[d - 1] = m_dict[d - 1] * block_matrix([[zul, sc], [identity_matrix(ring, cid), zlr]])
            rid = m_dict[d + 1].nrows() - tr.ncols()
            zul = zero_matrix(ring, rid, tr.ncols())
            zlr = zero_matrix(ring, tr.nrows(), rid)
            m_dict[d + 1] = block_matrix([[zul, identity_matrix(ring, rid)], [tr, zlr]]) * m_dict[d + 1]

            row_rest = m_dict[d].nrows() - m_source[d, x]
            col_rest = m_dict[d].ncols() - m_target[d, x]

            m_dict[d] = block_diagonal_matrix([sr, identity_matrix(ring, row_rest)]) * m_dict[d]
            m_dict[d] = m_dict[d] * block_diagonal_matrix([tc, identity_matrix(ring, col_rest)])

            rest_rest = m_dict[d][m_source[d, x]:, m_target[d, x]:]
            rest_dropped = m_dict[d][m_source[d, x]:, :dropped]
            dropped_rest = m_dict[d][:dropped, m_target[d, x]:]
            rest_kept = m_dict[d][m_source[d, x]:, dropped:m_target[d, x]]
            kept_rest = m_dict[d][dropped:m_source[d, x], m_target[d, x]:]
            kept_kept = m_dict[d][dropped:m_source[d, x], dropped:m_target[d, x]]
            m_dict[d] = block_matrix(ring, [[rest_rest - rest_dropped * dropped_rest, rest_kept],
                                            [kept_rest,                               kept_kept]])
            m_source[d, x] -= dropped
            m_target[d, x] -= dropped

    for d in range(a - 1, b + 1):
        source = [x for x in cat.objects for _ in range(m_source[d, x])]
        target = [x for x in cat.objects for _ in range(m_target[d, x])]
        dv = [w for i, r in enumerate(m_dict[d].rows()) for j, w in enumerate(r)
              if len(cat.hom(source[i], target[j])) == 1]
        data_vector = vector(ring, dv)
        diff_dict[d] = CatMat(ring, cat, source, data_vector, target)

    def pruned_f_law(d_singleton, x, f, y):
        d = d_singleton[0]
        if d in range(a - 1, b + 1):
            return CatMat.identity_matrix(ring, cat, diff_dict[d].source)
        return dgm.module_in_degree((d,))(x, f, y)

    def pruned_d_law(x, d_singleton):
        d = d_singleton[0]
        if d in range(a - 1, b + 1):
            return diff_dict[d]
        return dgm.differential(x, (d,))

    return dgModule(TerminalCategory, ring, pruned_f_law, [pruned_d_law], target_cat=cat)
Пример #40
0
    def topologically_evaluate_regular(self, datum):
        T = datum.toric_datum
        if not T.is_regular():
            raise ValueError('Can only processed regular toric data')

        # All our polyhedra all really half-open cones (with a - 1 >=0
        # being an imitation of a >= 0).

        C = conify_polyhedron(T.polyhedron)

        M = Set(range(T.length()))

        logger.debug('Dimension of polyhedron: %d' % T.polyhedron.dim())

        # STEP 1:
        # Compute the Euler characteristcs of the subvarieties of
        # Torus^sth defined by some subsets of T.initials.
        # Afterwards, we'll combine those into Denef-style Euler characteristics
        # via inclusion-exclusion.

        logger.debug('STEP 1')

        alpha = {}
        tdim = {}

        for I in Subsets(M):
            logger.debug('Processing I = %s' % I)
            F = [T.initials[i] for i in I]

            V = SubvarietyOfTorus(F, torus_dim=T.ambient_dim)
            U, W = V.split_off_torus()

            # Keep track of the dimension of the torus factor for F == 0.
            tdim[I] = W.torus_dim

            if tdim[I] > C.dim():
                # In this case, we will never need alpha[I].
                logger.debug('Totally irrelevant intersection.')
                # alpha[I] = ZZ(0)
            else:
                # To ensure that the computation of Euler characteristics succeeds in case
                # of global non-degeneracy, we test this first.
                # The 'euler_characteristic' method may change generating sets,
                # possibly introducing degeneracies.
                alpha[I] = U.khovanskii_characteristic() if U.is_nondegenerate(
                ) else U.euler_characteristic()
                logger.debug(
                    'Essential Euler characteristic alpha[%s] = %d; dimension of torus factor = %d'
                    % (I, alpha[I], tdim[I]))

        logger.debug(
            'Done computing essential Euler characteristics of intersections: %s'
            % alpha)

        # STEP 2:
        # Compute the topological zeta functions of the extended cones.
        # That is, add extra variables, add variable constraints (here: just >= 0),
        # and add newly monomialised conditions.

        def cat(u, v):
            return vector(list(u) + list(v))

        logger.debug('STEP 2')
        for I in Subsets(M):
            logger.debug('Current set: I = %s' % I)

            # P = C_0 x R_(>0)^I in the paper
            P = DirectProductOfPolyhedra(T.polyhedron,
                                         StrictlyPositiveOrthant(len(I)))

            it = iter(identity_matrix(ZZ, len(I)).rows())
            ieqs = []
            for i in M:
                # Turn lhs[i] | monomial of initials[i] * y[i] if in I,
                #      lhs[i] | monomial of initials[i] otherwise
                # into honest cone conditions.
                ieqs.append(
                    cat(
                        vector(ZZ, (0, )),
                        cat(
                            vector(ZZ, T.initials[i].exponents()[0]) -
                            vector(ZZ, T.lhs[i].exponents()[0]),
                            next(it) if i in I else zero_vector(ZZ, len(I)))))

            if not ieqs:
                # For some reason, not providing any constraints yields the empty
                # polyhedron in Sage; it should be all of RR^whatever, IMO.
                ieqs = [vector(ZZ, (T.ambient_dim + len(I) + 1) * [0])]

            Q = Polyhedron(ieqs=ieqs,
                           base_ring=QQ,
                           ambient_dim=T.ambient_dim + len(I))

            sigma = conify_polyhedron(P.intersection(Q))
            logger.debug('Dimension of Hensel cone: %d' % sigma.dim())

            # Obtain the desired Euler characteristic via inclusion-exclusion,
            # restricted to those terms contributing to the constant term mod q-1.
            chi = sum((-1)**len(J) * alpha[I + J] for J in Subsets(M - I)
                      if tdim[I + J] + len(I) == sigma.dim())

            if not chi:
                continue

            # NOTE: dim(P) = dim(sigma): choose any point omega in P
            # then a large point lambda in Pos^I will give (omega,lambda) in sigma.
            # Moreover, small perturbations of (omega,lambda) don't change that
            # so (omega,lambda) is an interior point of sigma inside P.

            surfs = (topologise_cone(
                sigma,
                matrix([
                    cat(T.integrand[0], zero_vector(ZZ, len(I))),
                    cat(T.integrand[1], vector(ZZ,
                                               len(I) * [-1]))
                ]).transpose()))

            for S in surfs:
                yield SURF(scalar=chi * S.scalar, rays=S.rays)
Пример #41
0
    def t1(self, n=5):
        """
        Return choice of element t1 of the Hecke algebra mod 2,
        computed using the Hecke operator $T_n$, where n is self.n
        
        INPUT:
        
            - `n` -- integer (optional default=5)
            
        OUTPUT:

            - a mod 2 matrix

        EXAMPLES::

            sage: from mdsage import *
            sage: C = KamiennyCriterion(29)
            sage: C.t1(n=3)
            22 x 22 dense matrix over Finite Field of size 2 (use the '.str()' method to see the entries)
            sage: C.t1(n=3) == 1
            True
            sage: C.t1()
            Traceback (most recent call last):
            ...
            ValueError: T_5 needs to be a generator of the hecke algebra
            sage: C = KamiennyCriterion(37)
            sage: C.t1()[0]
            (1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0) 
        """
        T = self.S.hecke_matrix(n)
        f = T.charpoly()
        F = f.factor()
        if prod(i[1] for i in F) != 1:
            raise ValueError("T_%s needs to be a generator of the hecke algebra"%n)

        # Compute the iterators of T acting on the winding element.
        e = self.M([0, oo]).element().dense_vector()
        t = self.M.hecke_matrix(n).dense_matrix()
        g = t.charpoly()
        Z = t.iterates(e, t.nrows(), rows=True)
        # We find all factors F[i][0] for f such that
        # (g/F[i][0])(t) * e = 0.
        # We do this by computing the polynomial
        #       h = g/F[i][0],
        # turning it into a vector v, and computing
        # the matrix product v * Z.  If the product
        # is 0, then e is killed by h(t).
        J = []
        for i in range(len(F)):
            h, r = g.quo_rem(F[i][0] ** F[i][1])
            assert r == 0
            v = vector(QQ, h.padded_list(t.nrows()))
            if v * Z == 0:
                J.append(i)


        if self.verbose: print "J =", J
        if len(J) == 0:
            # The annihilator of e is the 0 ideal.
            return matrix_modp(identity_matrix(T.nrows()))
            
        # Finally compute t1.  I'm concerned about how
        # long this will take, so we reduce T mod 2 first.

        # It is important to call "self.T(2)" to get the mod-2
        # reduction of T2 with respect to the right basis (e.g., the
        # integral basis in case use_integral_structure is true.
        Tmod2 = self.T(n) 
        g = prod(F[i][0].change_ring(GF(2)) ** F[i][1] for i in J)
        t1 = g(Tmod2)
        return t1
Пример #42
0
def gen_regressor_RNE( do_varify, rbt, usemotordyn = True, usefricdyn = True, varify_trig = True ):
  
    from copy import copy
    
    Si = _gen_rbt_Si(rbt)

    if usefricdyn:
      fric = gen_Dyn_fricterm(rbt)
    
    def custom_simplify( expression ):
        #return trig_reduce(expression.expand()).simplify_rational()
        return expression.simplify_rational()
    
    varify_func = None
    
    if do_varify:
        auxvars = []
        def varify_func(exp,varrepr):
            if varify_trig : exp = exp.subs( LoP_to_D(rbt.LoP_trig_f2v) )
            exp = custom_simplify( exp )
            return m_varify(exp, auxvars, poolrepr='auxY', condition_func=is_compound)
    
    
    Vi, dVi = _forward_RNE( rbt, Si, varify_func )
    
    P = rbt.Parms(usemotordyn,usefricdyn)
    
    Y = matrix(SR,rbt.dof,P.nrows())
    
    for p in range(P.nrows()) :
        
        select =  subsm( P, zero_matrix(P.nrows(),1) )
        select.update( {P[p,0]:Integer(1)} )
        
        IIi = range(0,rbt.dof+1)
        for i in range(1,rbt.dof+1):
            IIi[i] = block_matrix( [ rbt.Ifi[i].subs(select) , skew(rbt.mli[i].subs(select)) , -skew(rbt.mli[i].subs(select)) , rbt.mi[i].subs(select)*identity_matrix(3) ] ,subdivide=False)
        
        if usemotordyn:
          Imzi = deepcopy(rbt.Imzi)
          for i,Im in enumerate(Imzi):
            Imzi[i] = Im.subs(select)
        else:
          Imzi = None
      
        Y[:,p] = _backward_RNE( rbt, IIi, Si, Vi, dVi, usemotordyn, Imzi, varify_func )
        
        if usefricdyn:
          Y[:,p] += fric.subs(select)
    
    if do_varify:
        if varify_trig : auxvars = rbt.LoP_trig_v2f + auxvars
        return auxvars , Y
    else:
        return Y
Пример #43
0
def mat_to_matlist(A):
    return [
        matrix(QQ, [[a(list(e)) for a in rows] for rows in A])
        for e in identity_matrix(QQ,
                                 A.base_ring().ngens())
    ]
Пример #44
0
 def test_vecor_valued_misc(self):
     prec = 5
     M = vvld_smfs(2, 20, prec)
     m = matrix([M._to_vector(f).list() for f in M.basis()])
     self.assertEqual(m, identity_matrix(QQ, M.dimension()))
Пример #45
0
def symmetric_block_diagonalize(N1):
    r"""Returns matrices `H` and `Q` such that `N1 = Q*H*Q.T` and `H` is block
    diagonal.

    The algorithm used here is as follows. Whenever a row operation is
    performed (via multiplication on the left by a transformation matrix `q`)
    the corresponding symmetric column operation is also performed via
    multiplication on the right by `q^T`.

    For each column `j` of `N1`:

    1. If column `j` consists only of zeros then swap with the last column with
       non-zero entries.

    2. If there is a `1` in position `j` of the column (i.e. a `1` lies on the
       diagonal in this column) then eliminate further entries below as in
       standard Gaussian elimination.

    3. Otherwise, if there is a `1` in the column, but not in position `j` then
       rows are swapped in a way that it appears in the position `j+1` of the
       column. Eliminate further entries below as in standard Gaussian
       elimination.

    4. After elimination, if `1` lies on the diagonal in column `j` then
       increment `j` by one. If instead the block matrix `[0 1 \\ 1 0]` lies
       along the diagonal then eliminate under the `(j,j+1)` element (the upper
       right element) of this `2 x 2` block and increment `j` by two.

    5. Repeat until `j` passes the final column or until further columns
       consists of all zeros.

    6. Finally, perform the appropriate transformations such that all `2 x 2`
       blocks in `H` appear first in the diagonalization. (Uses the
       `diagonal_locations` helper function.)

    Parameters
    ----------
    N1 : GF(2) matrix

    Returns
    -------
    H : GF(2) matrix
        Symmetric `g x g` matrix where the diagonal elements consist of either
        a "1" or a `2 x 2` block matrix `[0 1 \\ 1 0]`.
    Q : GF(2) matrix
        The corresponding transformation matrix.
    """
    g = N1.nrows()
    H = zero_matrix(GF(2), g)
    Q = identity_matrix(GF(2), g)

    # if N1 is the zero matrix the H is also the zero matrix (and Q is the
    # identity transformation)
    if (N1 % 2) == 0:
        return H,Q

    # perform the "modified gaussian elimination"
    B = Matrix(GF(2),[[0,1],[1,0]])
    H = N1.change_ring(GF(2))
    j = 0
    while (j < g) and (H[:,j:] != 0):
        # if the current column is zero then swap with the last non-zero column
        if H.column(j) == 0:
            last_non_zero_col = max(k for k in range(j,g) if H.column(k) != 0)
            Q.swap_columns(j,last_non_zero_col)
            H = Q.T*N1*Q

        # if the current diagonal element is 1 then gaussian eliminate as
        # usual. otherwise, swap rows so that a "1" appears in H[j+1,j] and
        # then eliminate from H[j+1,j]
        if H[j,j] == 1:
            rows_to_eliminate = (r for r in range(g) if H[r,j] == 1 and r != j)
            for r in rows_to_eliminate:
                Q.add_multiple_of_column(r,j,1)
            H = Q.T*N1*Q
        else:
            # find the first non-zero element in the column after the diagonal
            # element and swap rows with this element
            first_non_zero = min(k for k in range(j,g) if H[k,j] != 0)
            Q.swap_columns(j+1,first_non_zero)
            H = Q.T*N1*Q

            # eliminate *all* other ones in the column, including those above
            # the element (j,j+1)
            rows_to_eliminate = (r for r in range(g) if H[r,j] == 1 and r != j+1)
            for r in rows_to_eliminate:
                Q.add_multiple_of_column(r,j+1,1)
            H = Q.T*N1*Q

        # increment the column based on the diagonal element
        if H[j,j] == 1:
            j += 1
        elif H[j:(j+2),j:(j+2)] == B:
            # in the block diagonal case, need to eliminate below the j+1 term
            rows_to_eliminate = (r for r in range(g) if H[r,j+1] == 1 and r != j)
            for r in rows_to_eliminate:
                Q.add_multiple_of_column(r,j,1)
            H = Q.T*N1*Q
            j += 2

    # finally, check if there are blocks of "special" form. that is, shift all
    # blocks such that they occur first along the diagonal of H
    index_one, index_B = diagonal_locations(H)
    while index_one < index_B:
        j = index_B

        Qtilde = zero_matrix(GF(2), g)
        Qtilde[0,0] = 1
        Qtilde[j,0] = 1; Qtilde[j+1,0] = 1
        Qtilde[0,j] = 1; Qtilde[0,j+1] = 1
        Qtilde[j:(j+2),j:(j+2)] = B

        Q = Q*Qtilde
        H = Q.T*N1*Q

        # continue until none are left
        index_one, index_B = diagonal_locations(H)

    # above, we used Q to store column operations on N1. switch to rows
    # operations on H so that N1 = Q*H*Q.T
    Q = Q.T.inverse()
    return H,Q
Пример #46
0
def _gen_tau_atlRNE( do_varify, rbt, usemotordyn = True, varify_trig = True ):
  
    from copy import copy
    
    dof = rbt.dof
    
    Rdhi = copy(rbt.Rdhi)
    Rdhi.append( identity_matrix(SR,3) )
    
    wfi = range(0,dof+1)
    dwfi = range(0,dof+1)
    ddpfi = range(0,dof+1)
    ddpci = range(0,dof+1)
    ffi = range(0,dof+2)
    nfi = range(0,dof+2)
    tau = matrix(SR,dof,1)
    
    wfi[0] = copy(zero_matrix(SR,3,1))
    dwfi[0] = copy(zero_matrix(SR,3,1))
    ddpfi[0] = copy(zero_matrix(SR,3,1))
    ddpci[0] = copy(zero_matrix(SR,3,1))
    ffi[dof+1] = copy(zero_matrix(SR,3,1))
    nfi[dof+1] = copy(zero_matrix(SR,3,1))
    
    if do_varify:
        
        def custom_simplify( expression ):
        #    return trig_reduce(expression.expand()).simplify_rational()
            return expression.simplify_rational()
        
        def varify_func(exp,varpool,varrepr):
            if varify_trig : exp = exp.subs( LoP_to_D(rbt.LoP_trig_f2v) )
            exp = custom_simplify( exp )
            return m_varify(exp,varpool,condition_func=is_compound)
            #return v3R_varify(exp,varpool,varrepr)
        
        auxvars = []
    
    else:
        def varify_func(exp,varpool,varrepr):
            return exp
        auxvars = ()
    
    # Forward
    for i in range(1,dof+1):
        
        wfi[i] = Rdhi[i].transpose() * ( wfi[i-1] + rbt.dq[i-1,0] * rbt.zi[0] )
        wfi[i] = varify_func( wfi[i] , auxvars , 'wf_'+str(i) )
        
        dwfi[i] = Rdhi[i].transpose() * ( dwfi[i-1] + rbt.ddq[i-1,0] * rbt.zi[0] \
        + cross_product( rbt.dq[i-1,0] * wfi[i-1] , rbt.zi[0] ) )
        dwfi[i] = varify_func( dwfi[i] , auxvars , 'dwf_'+str(i) )
        
        ddpfi[i] = Rdhi[i].transpose() * ddpfi[i-1] + cross_product( dwfi[i] , rbt.pdhfi[i] ) \
        + cross_product( wfi[i] , cross_product( wfi[i] , rbt.pdhfi[i] ) )
        ddpfi[i] = varify_func( ddpfi[i] , auxvars , 'ddpf_'+str(i) )
        
        ddpci[i] = ddpfi[i] + cross_product( dwfi[i] , rbt.li[i] ) \
        + cross_product( wfi[i] , cross_product( wfi[i] , rbt.li[i] ) )
        ddpci[i] = varify_func( ddpci[i] , auxvars , 'ddpc_'+str(i) )

    
    # Backward

    if usemotordyn:
      nfi_motor = [zero_matrix(3,1) for i in xrange(dof+1)]
      for m in rbt.motors:
        Im = m[0]; qm = m[1]; l = m[2]; zm = m[3]
        dqm = qm.subs(rbt.D_q_v2f).derivative(rbt.t).subs(rbt.D_q_f2v)
        ddqm = dqm.subs(rbt.D_q_v2f).derivative(rbt.t).subs(rbt.D_q_f2v)
        nfi_motor[l] += ddqm * Im * zm + dqm * Im * cross_product( wfi[l] , zm )
    
    for i in range(dof,0,-1):
        
        ffi[i] = Rdhi[i+1] * ffi[i+1] + rbt.mi[i] * ( ddpci[i] - rbt.Ri[i].transpose()*rbt.grav )
        ffi[i] = varify_func( ffi[i] , auxvars , 'ff_'+str(i) )
        
        nfi[i] = cross_product( - ffi[i] , rbt.pdhfi[i] + rbt.li[i] ) + Rdhi[i+1] * nfi[i+1] + \
        cross_product( Rdhi[i+1] * ffi[i+1] , rbt.li[i] ) + rbt.Ici[i] * dwfi[i] + \
        cross_product( wfi[i] , rbt.Ici[i] * wfi[i] )
        if usemotordyn:
          nfi[i] += nfi_motor[i]
        nfi[i] = varify_func( nfi[i] , auxvars , 'nf_'+str(i) )
    
    for i in range(1,dof+1):
      
        tau[i-1,0] = ( nfi[i].transpose() * Rdhi[i].transpose() * rbt.zi[0] )[0,0]
        
        if usemotordyn:
          for m in rbt.motors:
            Im = m[0]; qm = m[1]; l = m[2]; zm = m[3]
            dqm = qm.subs(rbt.D_q_v2f).derivative(rbt.t).subs(rbt.D_q_f2v)
            ddqm = dqm.subs(rbt.D_q_v2f).derivative(rbt.t).subs(rbt.D_q_f2v)
            km = qm.coeff(rbt.q[i-1,0])
            if km != 0.0:
              tau[i-1,0] += km * Im * ( ( dwfi[l] + ddqm * zm + dqm * cross_product( wfi[l] , zm ) ).transpose() * zm )[0,0]
    
    if do_varify:
        if varify_trig : auxvars = rbt.LoP_trig_v2f + auxvars
        return auxvars,tau
    else:
        return tau
Пример #47
0
def gen_tau_RNE( do_varify, rbt, usemotordyn=True, varify_trig = True ):
    
    Si = _gen_rbt_Si(rbt)
    
    IIi = range(0,rbt.dof+1)
    ### Linear dynamic parameters:
    for i in range(1,rbt.dof+1): IIi[i] = block_matrix( [ rbt.Ifi[i] , skew(rbt.mli[i]) , -skew(rbt.mli[i]) , rbt.mi[i]*identity_matrix(3) ] ,subdivide=False)
    ### Not linear dynamic parameters:
    #for i in range(1,dof+1): IIi[i] = block_matrix( [ rbt.Ifi_from_Ici[i] , skew(rbt.mli_e[i]) , -skew(rbt.mli_e[i]) , rbt.mi[i]*identity_matrix(3) ] ,subdivide=False)
    
    if do_varify:
        auxvars = []
        def custom_simplify( expression ):
        #    return trig_reduce(expression.expand()).simplify_rational()
            return expression.simplify_rational()
        
        def varify_func(exp,varrepr):
            if varify_trig : exp = exp.subs( LoP_to_D(rbt.LoP_trig_f2v) )
            exp = custom_simplify( exp )
            return m_varify(exp,auxvars,condition_func=is_compound)
            #return v6R_varify(exp,auxvars,varrepr)
        
    else:
        def varify_func(exp,varrepr):
            return exp
    
    Vi, dVi = _forward_RNE( rbt, Si, varify_func )
    tau = _backward_RNE( rbt, IIi, Si, Vi, dVi, usemotordyn, None, varify_func = varify_func )
    
    if do_varify:
        if varify_trig : auxvars = rbt.LoP_trig_v2f + auxvars
        return auxvars,tau
    else:
        return tau
Пример #48
0
def upper_bound_tate(cp, frob_matrix, precision, over_Qp=False, pedantic=True):
    """
    Return a upper bound for Tate classes over characteristic 0
    TODO: improove documentation
    """
    p = cp.list()[-1].prime_factors()[0]
    # it would be nice to use QpLF
    OK = ZpCA(p, prec=precision)

    # adjust precision
    frob_matrix = matrix(OK, frob_matrix)

    # get the p-adic eigenvalues
    _, _, cyc_factorization = rank_fieldextension(cp)

    # a bit hacky
    val = [
        min(elt.valuation() for elt in col) for col in frob_matrix.columns()
    ]
    projection_cols = frob_matrix.ncols() - val.index(0)
    assert set(val[-projection_cols:]) == {0}
    # P1 = | zero matrix |
    #      | Identity    |
    P1 = zero_matrix(frob_matrix.ncols() - projection_cols,
                     projection_cols).stack(identity_matrix(projection_cols))
    # computing a kernel, either via smith form or howell form
    # involves some kind of gauss elimination,
    # and thus having the columns with lowest valuation first improves
    # the numerical stability of the algorithms
    P1.reverse_rows_and_columns()
    frob_matrix.reverse_rows_and_columns()

    @cached_function
    def frob_power(k):
        if k == 0:
            return identity_matrix(frob_matrix.ncols())
        elif k == 1:
            return frob_matrix
        else:
            return frob_matrix * frob_power(k - 1)

    factor_i = []
    dim_Ti = []
    obsi = []
    dim_Li = []
    for cyc_fac, cyc_exp in cyc_factorization:
        factor_i.append((cyc_fac, cyc_exp))
        Ti = matrix(0, frob_matrix.ncols())
        obsij = []
        dim_Tij = []
        dim_Lij = []
        for fac, exp in tate_factor_Zp(cyc_fac):
            # the rows of Tij are a basis for Tij
            # the 'computed' argument avoids echelonizing the kernel basis
            # which might induce some precision loss on the projection
            #Tij = fac(frob_matrix).right_kernel_matrix(basis='computed')

            # computing the right kernel with smith form
            # howell form or strong echelon could also be good options
            Tij = padic_right_kernel_matrix(fac(frob_matrix))
            if Tij.nrows() != fac.degree() * exp * cyc_exp:
                raise PrecisionError(
                    "Number of eigenvectors (%d) doesn't match the number of eigenvalues (%d), increasing  precision should solve this"
                    % (Tij.nrows(), fac.degree() * exp * cyc_exp))
            if over_Qp:
                dim_Tij.append(Tij.nrows())
                obs_map = Tij * P1
                rank_obs_ij = obs_map.rank()
                obsij.append(rank_obs_ij)
                Lijmatrix = matrix(Tij.base_ring(), Tij.nrows(), 0)
                for ell in range(fac.degree()):
                    Lijmatrix = Lijmatrix.augment(
                        Tij * frob_power(ell).transpose() * P1)
                # Lij = right_kernel(K) subspace of Tij that is invariant under Frob and unobstructed
                Krank = Lijmatrix.rank()
                dim_Lij.append(Tij.nrows() - Krank)
                if dim_Lij[-1] % fac.degree() != 0:
                    old_dim = dim_Li[-1]
                    deg = fac.degree()
                    new_dim = dim_Li[-1] = deg * (old_dim // deg)
                    if pedantic:
                        warnings.warn(
                            "rounding dimension of Li from %d to %d for factor = %s"
                            % (old_dim, new_dim, fac))

            Ti = Ti.stack(Tij)

        if over_Qp:
            dim_Ti.append(dim_Tij)
            obsi.append(obsij)
            dim_Li.append(dim_Lij)
        else:
            obs_map = Ti * P1
            if Ti.nrows() != cyc_fac.degree() * cyc_exp:
                raise PrecisionError(
                    "Number of eigenvectors (%d) doesn't match the number of eigenvalues (%d), increasing  precision should solve this"
                    % (Tij.nrows(), cyc_fac.degree() * cyc_exp))
            dim_Ti.append(Ti.nrows())
            rank_obs_i = padic_rank(obs_map)
            obsi.append(Ti.nrows() - rank_obs_i)
            Limatrix = matrix(Ti.base_ring(), Ti.nrows(), 0)
            for ell in range(0, cyc_fac.degree()):
                Limatrix = Limatrix.augment(Ti * frob_power(ell).transpose() *
                                            P1)
            #print(Limatrix.smith_form(exact=False, integral=True, transformation=False).diagonal())
            # Li = right_kernel(K) subspace of Tij that is invariant under Frob and unobstructed
            Krank = padic_rank(Limatrix)
            dim_Li.append(Ti.nrows() - Krank)
            if dim_Li[-1] % cyc_fac.degree() != 0:
                old_dim = dim_Li[-1]
                deg = cyc_fac.degree()
                new_dim = dim_Li[-1] = deg * (old_dim // deg)
                if pedantic:
                    warnings.warn(
                        "rounding dimension of Li from %d to %d for cyc_factor = %s"
                        % (old_dim, new_dim, cyc_fac))
    return factor_i, dim_Ti, obsi, dim_Li,
Пример #49
0
def perm_mat(i, j, n):
    l = identity_matrix(QQ, n).columns()
    l[i], l[j] = l[j], l[i]
    return matrix(l)