예제 #1
0
    def space(self):
        r'''
        Calculates the space of cocyles modulo coboundaries, as a Z-module.

        TESTS:

        sage: from darmonpoints.sarithgroup import *
        sage: from darmonpoints.cohomology_abstract import *
        sage: from darmonpoints.ocmodule import *
        sage: GS = BigArithGroup(5, 6,1,use_shapiro=False,outfile='/tmp/darmonpoints.tmp') #  optional - magma
        sage: G = GS.large_group() #  optional - magma
        sage: V = OCVn(5,1)     #  optional - magma
        sage: Coh = CohomologyGroup(G,V,trivial_action = False) #  optional - magma
        '''
        verb = get_verbose()
        set_verbose(0)
        V = self.coefficient_module()
        R = V.base_ring()
        Vdim = V.dimension()
        G = self.group()
        gens = G.gens()
        ambient = R**(Vdim * len(gens))
        # Now find the subspace of cocycles
        A = Matrix(R, Vdim * len(gens), 0)
        for r in G.get_relation_words():
            Alist = self.fox_gradient(r)
            newA = block_matrix(Alist, nrows = 1)
            A = A.augment(newA.transpose())
        A = A.transpose()
        cocycles = ambient.submodule([ambient(o) for o in A.right_kernel_matrix().rows()])
        gmat = block_matrix([self._gen_pows[i][1] - 1 for i in range(len(G.gens()))], nrows = len(G.gens()))
        coboundaries = cocycles.submodule([ambient(o) for o in gmat.columns()])
        ans = cocycles.quotient(coboundaries)
        set_verbose(verb)
        return ans
예제 #2
0
    def diagonal_matrix(self):
        r"""
        Returns a diagonal matrix `D` and a matrix `T` such that `T^t A T = D`
        holds, where `(x, y, z) A (x, y, z)^t` is the defining polynomial
        of the conic ``self``.

        EXAMPLES:

        ::

            sage: c = Conic(QQ, [1,2,3,4,5,6])
            sage: d, t = c.diagonal_matrix(); d, t
            (
            [    1     0     0]  [   1   -1 -7/6]
            [    0     3     0]  [   0    1 -1/3]
            [    0     0 41/12], [   0    0    1]
            )
            sage: t.transpose()*c.symmetric_matrix()*t
            [    1     0     0]
            [    0     3     0]
            [    0     0 41/12]

        Diagonal matrices are only defined in characteristic different
        from `2`:

        ::

            sage: c = Conic(GF(4, 'a'), [0, 1, 1, 1, 1, 1])
            sage: c.is_smooth()
            True
            sage: c.diagonal_matrix()
            Traceback (most recent call last):
            ...
            ValueError: The conic self (= Projective Conic Curve over Finite Field in a of size 2^2 defined by x*y + y^2 + x*z + y*z + z^2) has no symmetric matrix because the base field has characteristic 2
        """
        A = self.symmetric_matrix()
        B = self.base_ring()
        basis = [vector(B,{2:0,i:1}) for i in range(3)]
        for i in range(3):
            zerovalue = (basis[i]*A*basis[i].column()== 0)
            if zerovalue:
                for j in range(i+1,3):
                    if basis[j]*A*basis[j].column() != 0:
                        b = basis[i]
                        basis[i] = basis[j]
                        basis[j] = b
                        zerovalue = False
            if zerovalue:
                for j in range(i+1,3):
                    if basis[i]*A*basis[j].column() != 0:
                        basis[i] = basis[i]+basis[j]
                        zerovalue = False
            if not zerovalue:
                l = (basis[i]*A*basis[i].column())
                for j in range(i+1,3):
                    basis[j] = basis[j] - \
                               (basis[i]*A*basis[j].column())/l * basis[i]
        T = Matrix(basis).transpose()
        return T.transpose()*A*T, T
예제 #3
0
파일: con_field.py 프로젝트: chos9/sage
    def diagonal_matrix(self):
        r"""
        Returns a diagonal matrix `D` and a matrix `T` such that `T^t A T = D`
        holds, where `(x, y, z) A (x, y, z)^t` is the defining polynomial
        of the conic ``self``.

        EXAMPLES:

        ::

            sage: c = Conic(QQ, [1,2,3,4,5,6])
            sage: d, t = c.diagonal_matrix(); d, t
            (
            [    1     0     0]  [   1   -1 -7/6]
            [    0     3     0]  [   0    1 -1/3]
            [    0     0 41/12], [   0    0    1]
            )
            sage: t.transpose()*c.symmetric_matrix()*t
            [    1     0     0]
            [    0     3     0]
            [    0     0 41/12]

        Diagonal matrices are only defined in characteristic different
        from `2`:

        ::

            sage: c = Conic(GF(4, 'a'), [0, 1, 1, 1, 1, 1])
            sage: c.is_smooth()
            True
            sage: c.diagonal_matrix()
            Traceback (most recent call last):
            ...
            ValueError: The conic self (= Projective Conic Curve over Finite Field in a of size 2^2 defined by x*y + y^2 + x*z + y*z + z^2) has no symmetric matrix because the base field has characteristic 2
        """
        A = self.symmetric_matrix()
        B = self.base_ring()
        basis = [vector(B,{2:0,i:1}) for i in range(3)]
        for i in range(3):
            zerovalue = (basis[i]*A*basis[i].column()== 0)
            if zerovalue:
                for j in range(i+1,3):
                    if basis[j]*A*basis[j].column() != 0:
                        b = basis[i]
                        basis[i] = basis[j]
                        basis[j] = b
                        zerovalue = False
            if zerovalue:
                for j in range(i+1,3):
                    if basis[i]*A*basis[j].column() != 0:
                        basis[i] = basis[i]+basis[j]
                        zerovalue = False
            if not zerovalue:
                l = (basis[i]*A*basis[i].column())
                for j in range(i+1,3):
                    basis[j] = basis[j] - \
                               (basis[i]*A*basis[j].column())/l * basis[i]
        T = Matrix(basis).transpose()
        return T.transpose()*A*T, T
예제 #4
0
    def LocalizedMomentMatrix(self, idx):
        """
        Returns localized moment matrix corresponding to $g_{idx}$
        """

        tmp_vec = self.MonomialsVec(self.Relaxation - self.HalfDegs[idx])
        m = Matrix(1, len(tmp_vec), tmp_vec)
        return self.Constraints[idx] * (m.transpose() * m)
예제 #5
0
 def LocalizedMomentMatrix(self, idx):
     """
     Returns localized moment matrix corresponding to $g_{idx}$
     """
     
     tmp_vec = self.MonomialsVec(self.Relaxation-self.HalfDegs[idx])
     m = Matrix(1, len(tmp_vec), tmp_vec)
     return self.Constraints[idx]* (m.transpose() * m)
예제 #6
0
    def decompose(self):
        """
            Gives an SOS decomposition of f if exists as a list of polynomials
            of at most half degree of f.
            This method also fills the 'Info' as 'minimize' does. In addition,
            returns Info['is sos'] which is Boolean depending on the status of 
            sdp solver.
        """
        n = self.NumVars
        N0 = self.NumMonomials(n, self.MainPolyHlfDeg)
        N1 = self.NumMonomials(n, self.MainPolyTotDeg)
        self.MatSize = [N0, N1]

        vec = self.MonomialsVec(self.MainPolyHlfDeg)
        m = Matrix(1, N0, vec)
        Mmnt = m.transpose() * m
        Blck = [[] for i in range(N1)]
        C = []

        h = Matrix(self.Field, N0, N0, 0)
        C.append(h)
        decomp = []

        for i in range(N1):
            p = self.Monomials[i]
            A = self.Calpha(p, Mmnt)
            Blck[i].append(A)

        from SDP import SDP
        sos_sdp = SDP.sdp(solver=self.solver, Settings={'detail': self.detail})
        sos_sdp.solve(C, self.PolyCoefFullVec(), Blck)

        if sos_sdp.Info['Status'] == 'Optimal':
            self.Info['status'] = 'Feasible'
            GramMtx = Matrix(sos_sdp.Info['X'][0])
            try:
                self.Info[
                    'Message'] = "A SOS decomposition of the polynomial were found."
                self.Info['is sos'] = True
                H1 = GramMtx.cholesky()
                tmpM = Matrix(1, N0, vec)
                decomp = list(tmpM * H1)[0]
                self.Info['Wall'] = sos_sdp.Info['Wall']
                self.Info['CPU'] = sos_sdp.Info['CPU']
            except:
                self.Info[
                    'Message'] = "The given polynomial seems to be a sum of squares, but no SOS decomposition were extracted."
                self.Info['is sos'] = False
                self.Info['Wall'] = sos_sdp.Info['Wall']
                self.Info['CPU'] = sos_sdp.Info['CPU']
        else:
            self.Info[
                'Message'] = "The given polynomial is not a sum of squares."
            self.Info['status'] = 'Infeasible'
            self.Info['is sos'] = False

        self.Info["Size"] = self.MatSize
        return decomp
예제 #7
0
    def linear_approximation_matrix(self):
        """
        Return linear approximation matrix ``A`` for this S-box.

        Let ``i_b`` be the ``b``-th bit of ``i`` and ``o_b`` the
        ``b``-th bit of ``o``. Then ``v = A[i,o]`` encodes the bias of
        the equation ``sum( i_b * x_i ) = sum( o_b * y_i )`` if
        ``x_i`` and ``y_i`` represent the input and output variables
        of the S-box.

        See [He2002]_ for an introduction to linear cryptanalysis.

        EXAMPLES::

            sage: from sage.crypto.sbox import SBox
            sage: S = SBox(7,6,0,4,2,5,1,3)
            sage: S.linear_approximation_matrix()
            [ 4  0  0  0  0  0  0  0]
            [ 0  0  0  0  2  2  2 -2]
            [ 0  0 -2 -2 -2  2  0  0]
            [ 0  0 -2  2  0  0 -2 -2]
            [ 0  2  0  2 -2  0  2  0]
            [ 0 -2  0  2  0  2  0  2]
            [ 0 -2 -2  0  0 -2  2  0]
            [ 0 -2  2  0 -2  0  0 -2]

        According to this matrix the first bit of the input is equal
        to the third bit of the output 6 out of 8 times::

            sage: for i in srange(8): print(S.to_bits(i)[0] == S.to_bits(S(i))[2])
            False
            True
            True
            True
            False
            True
            True
            True
        """
        m = self.m
        n = self.n

        nrows = 1<<m
        ncols = 1<<n

        B = BooleanFunction(self.m)
        L = []
        for j in range(ncols):
            for i in range(nrows):
                B[i] = ZZ(self(i)&j).popcount()
            L.append(B.walsh_hadamard_transform())

        A = Matrix(ZZ, ncols, nrows, L)
        A = -A.transpose()/2
        A.set_immutable()

        return A
예제 #8
0
def angle_equations(M):
    """
    Given a snappy manifold M, returns the matrix of left-hand-sides
    of angle equations (that is, the tet, edge, and cusp equations).
    """
    num_tet = M.num_tetrahedra()
    G = M.gluing_equations()
    T = Matrix(ZZ, [tet_vector(i, num_tet) for i in range(num_tet)])
    return T.transpose().augment(G.transpose()).transpose()  # sigh
예제 #9
0
파일: sbox.py 프로젝트: mcognetta/sage
    def linear_approximation_matrix(self):
        """
        Return linear approximation matrix ``A`` for this S-box.

        Let ``i_b`` be the ``b``-th bit of ``i`` and ``o_b`` the
        ``b``-th bit of ``o``. Then ``v = A[i,o]`` encodes the bias of
        the equation ``sum( i_b * x_i ) = sum( o_b * y_i )`` if
        ``x_i`` and ``y_i`` represent the input and output variables
        of the S-box.

        See [He2002]_ for an introduction to linear cryptanalysis.

        EXAMPLES::

            sage: from sage.crypto.sbox import SBox
            sage: S = SBox(7,6,0,4,2,5,1,3)
            sage: S.linear_approximation_matrix()
            [ 4  0  0  0  0  0  0  0]
            [ 0  0  0  0  2  2  2 -2]
            [ 0  0 -2 -2 -2  2  0  0]
            [ 0  0 -2  2  0  0 -2 -2]
            [ 0  2  0  2 -2  0  2  0]
            [ 0 -2  0  2  0  2  0  2]
            [ 0 -2 -2  0  0 -2  2  0]
            [ 0 -2  2  0 -2  0  0 -2]

        According to this matrix the first bit of the input is equal
        to the third bit of the output 6 out of 8 times::

            sage: for i in srange(8): print(S.to_bits(i)[0] == S.to_bits(S(i))[2])
            False
            True
            True
            True
            False
            True
            True
            True
        """
        m = self.m
        n = self.n

        nrows = 1<<m
        ncols = 1<<n

        B = BooleanFunction(self.m)
        L = []
        for j in range(ncols):
            for i in range(nrows):
                B[i] = ZZ(self(i)&j).popcount()
            L.append(B.walsh_hadamard_transform())

        A = Matrix(ZZ, ncols, nrows, L)
        A = -A.transpose()/2
        A.set_immutable()

        return A
예제 #10
0
 def linear_relation(self, List, Psi, verbose=True, prec=None):
     for Phi in List:
         assert Phi.valuation() >= 0, "Symbols must be integral"
     assert Psi.valuation() >= 0
     R = self.base()
     Rbase = R.base()
     w = R.gen()
     d = len(List)
     if d == 0:
         if Psi.is_zero():
             return [None, R(1)]
         else:
             return [None, 0]
     if prec is None:
         M, var_prec = Psi.precision_absolute()
     else:
         M, var_prec = prec
     p = self.prime()
     V = R**d
     RSR = LaurentSeriesRing(Rbase, R.variable_name())
     VSR = RSR**self.source().ngens()
     List_TMs = [VSR(Phi.list_of_total_measures()) for Phi in List]
     Psi_TMs = VSR(Psi.list_of_total_measures())
     A = Matrix(RSR, List_TMs).transpose()
     try:
         sol = V([vv.power_series() for vv in A.solve_right(Psi_TMs)])
     except ValueError:
         #try "least squares"
         if verbose:
             print "Trying least squares."
         sol = (A.transpose() * A).solve_right(A.transpose() * Psi_TMs)
         #check precision (could make this better, checking each power of w)
         p_prec = M
         diff = Psi_TMs - sum([sol[i] * List_TMs[i] for i in range(len(List_TMs))])
         for i in diff:
             for j in i.list():
                 if p_prec > j.valuation():
                     p_prec = j.valuation()
         if verbose:
             print "p-adic precision is now", p_prec
         #Is this right?
         sol = V([R([j.add_bigoh(p_prec) for j in i.list()]) for i in sol])
     return [sol, R(-1)]
예제 #11
0
def projection_to_homology(tri,angle):
    non_tree_as_cycles = non_tree_edge_cycles(tri, angle)
    Q = Matrix(non_tree_as_cycles)
    S, U, V = faces_in_smith(tri,angle,[])
    rank, dimU, dimV = rank_of_quotient(S)
    U = Matrix(U)
    P = U.transpose().inverse()
    P = P.delete_rows(range(0, dimU-rank))
    A = P*Q
    return A
예제 #12
0
 def decompose(self):
     """
         Gives an SOS decomposition of f if exists as a list of polynomials
         of at most half degree of f.
         This method also fills the 'Info' as 'minimize' does. In addition,
         returns Info['is sos'] which is Boolean depending on the status of 
         sdp solver.
     """
     n = self.NumVars
     N0 = self.NumMonomials(n, self.MainPolyHlfDeg)
     N1 = self.NumMonomials(n, self.MainPolyTotDeg)
     self.MatSize = [N0, N1]
     
     vec = self.MonomialsVec(self.MainPolyHlfDeg)
     m = Matrix(1, N0, vec)
     Mmnt = m.transpose() * m
     Blck = [[] for i in range(N1)]
     C = []
     
     h = Matrix(self.Field, N0, N0, 0)
     C.append(h)
     decomp = []
     
     for i in range(N1):
         p = self.Monomials[i]
         A = self.Calpha(p, Mmnt)
         Blck[i].append(A)
     
     from SDP import SDP
     sos_sdp = SDP.sdp(solver = self.solver, Settings = {'detail':self.detail})
     sos_sdp.solve(C, self.PolyCoefFullVec(), Blck)
     
     if sos_sdp.Info['Status'] == 'Optimal':
         self.Info['status'] = 'Feasible'
         GramMtx = Matrix(sos_sdp.Info['X'][0])
         try:
             self.Info['Message'] = "A SOS decomposition of the polynomial were found."
             self.Info['is sos'] = True
             H1 = GramMtx.cholesky();
             tmpM = Matrix(1, N0, vec)
             decomp = list(tmpM*H1)[0]
             self.Info['Wall'] = sos_sdp.Info['Wall']
             self.Info['CPU'] = sos_sdp.Info['CPU']
         except:
             self.Info['Message'] = "The given polynomial seems to be a sum of squares, but no SOS decomposition were extracted."
             self.Info['is sos'] = False
             self.Info['Wall'] = sos_sdp.Info['Wall']
             self.Info['CPU'] = sos_sdp.Info['CPU']
     else:
         self.Info['Message'] = "The given polynomial is not a sum of squares."
         self.Info['status'] = 'Infeasible'
         self.Info['is sos']= False
     
     self.Info["Size"] = self.MatSize
     return decomp
예제 #13
0
def monomial_multiplier(elts, ZH):
    if all(elt == 0 for elt in elts):
        # Zero (unlike other constants) has valuation -\infty.  This
        # can show up as an issue when computing the big polynomial.
        # For an example, compute ET for
        # "kLLLMPPkcdgfehijjijhshassqhdqr_1222011022"
        return ZH(1)
    elts = [ZH(elt) for elt in elts]
    A = Matrix(ZZ, join_lists([uniform_exponents(p) for p in elts]))
    min_exp = tuple([min(row) for row in A.transpose()])
    return ZH({min_exp: 1})
예제 #14
0
def poly_dual_basis(P, poly_basis):
    r"""
    Return a collection of polynomials which are dual under the differential
    bilinear form to a given homogeneous collection

    INPUT:

    - ``P`` -- a polynomial ring
    - ``poly_basis`` -- a collection of polynomials in ``P`` which are
      homogeneous and linearly independent

    OUTPUT:

    - the dual basis of the polynomials in ``poly_basis`` in their span

    EXAMPLES:

        sage: P.<x, y> = PolynomialRing(QQ)
        sage: poly_basis = (1, x, x+y)
        sage: poly_dual_basis(P, poly_basis)
        [1, x - y, y]
        sage: poly_basis = (1, 2*x - y, x^2, x^2 + x*y)
        sage: poly_dual_basis(P, poly_basis)
        [1, 2/5*x - 1/5*y, 1/2*x^2 - x*y, x*y]
    """
    # recast poly_basis to ensure elements are all from P
    poly_basis = [P(p) for p in poly_basis]
    # compute max degree of basis polynomials for linear algebra computations
    deg = max([p.degree() for p in poly_basis])
    # construct polynomial free module for linear algebra computations
    monoms = Monomials(P, (0, deg))
    poly_module = PolynomialFreeModule(P, basis=monoms)
    # compute the values of the bilinear form <m|m> for basis monomials m
    bilinear_form_coeffs = []
    for b in poly_module.basis().keys():
        # each b is a monomial in P of degree at most deg
        b = P(b)
        bilinear_form_coeffs.append(prod(map(factorial, b.degrees())))
    # compute dual basis
    A = Matrix([poly_module(p).to_vector() for p in poly_basis])
    D = Matrix.diagonal(bilinear_form_coeffs, sparse=False)
    B = (A * D * A.transpose()).inverse()
    # reconstruct dual basis polynomials from corresponding vectors
    dual_basis = []
    for col in B.columns():
        q = sum([coeff * p for coeff, p in zip(col, poly_basis)])
        dual_basis.append(q)
    return dual_basis
예제 #15
0
    def space(self):
        r'''
        Calculates the space of cocyles modulo coboundaries, as a Z-module.

        TESTS:

        sage: from darmonpoints.sarithgroup import *
        sage: from darmonpoints.cohomology_abstract import *
        sage: from darmonpoints.ocmodule import *
        sage: GS = BigArithGroup(5, 6,1,use_shapiro=False,outfile='/tmp/darmonpoints.tmp') #  optional - magma
        sage: G = GS.large_group() #  optional - magma
        sage: V = OCVn(5,1)     #  optional - magma
        sage: Coh = CohomologyGroup(G,V,trivial_action = False) #  optional - magma
        '''
        verb = get_verbose()
        set_verbose(0)
        V = self.coefficient_module()
        R = V.base_ring()
        Vdim = V.dimension()
        G = self.group()
        gens = G.gens()
        ambient = R**(Vdim * len(gens))
        # Now find the subspace of cocycles
        A = Matrix(R, Vdim * len(gens), 0)
        for nr, r in enumerate(G.get_relation_words()):
            set_verbose(verb)
            verbose('Processing relation word %s' % nr)
            set_verbose(0)
            Alist = [
                MatrixSpace(R, Vdim, Vdim)(self.GA_to_local(o))
                for o in self.fox_gradient(tuple(r))
            ]
            newA = block_matrix(Alist, nrows=1)
            A = A.augment(newA.transpose())
        A = A.transpose()
        cocycles = ambient.submodule(
            [ambient(o) for o in A.right_kernel_matrix().rows()])
        gmat = block_matrix(
            [self._acting_matrix(g, Vdim) - 1 for g in G.gens()],
            nrows=len(G.gens()))
        coboundaries = cocycles.submodule([ambient(o) for o in gmat.columns()])
        ans = cocycles.quotient(coboundaries)
        set_verbose(verb)
        return ans
예제 #16
0
def taut_cone_homological_dim(tri, angle):
    # find the dimension of the projection of the taut cone into
    # homology

    # boundaries of tets
    bdys = zeroth_coboundary(tri)
    bdys = matrix_transpose(bdys)
    rays = taut_rays(tri, angle)
    # but these are all 'upwards', so we need to fix the
    # co-orientations
    coorient = is_transverse_taut(tri, angle, return_type = "face_coorientations")
    rays = [[int(a * b) for a, b in zip(coorient, ray)] for ray in rays]

    # now work in the space of two-chains
    Rays = IntegerLattice(rays + bdys)
    Bdys = Matrix(bdys)
    Cobs = Bdys.transpose()
    Anns = Cobs.kernel()
    return Rays.intersection(Anns).dimension()
예제 #17
0
파일: weyl_group.py 프로젝트: sagemath/sage
 def to_elt(alp):
     ref = self.domain().reflection(alp)
     m = Matrix([ref(x).to_vector() for x in self.domain().basis()])
     return self(m.transpose())
예제 #18
0
파일: utilities.py 프로젝트: shalec/sage
def make_regular_matroid_from_matroid(matroid):
    r"""
    Attempt to construct a regular representation of a matroid.

    INPUT:

    - ``matroid`` -- a matroid.

    OUTPUT:

    Return a `(0, 1, -1)`-matrix over the integers such that, if the input is
    a regular matroid, then the output is a totally unimodular matrix
    representing that matroid.

    EXAMPLES::

        sage: from sage.matroids.utilities import make_regular_matroid_from_matroid
        sage: make_regular_matroid_from_matroid(
        ....:               matroids.CompleteGraphic(6)).is_isomorphic(
        ....:                                     matroids.CompleteGraphic(6))
        True
    """
    import sage.matroids.linear_matroid
    M = matroid
    if isinstance(M, sage.matroids.linear_matroid.RegularMatroid):
        return M
    rk = M.full_rank()
    # First create a reduced 0-1 matrix
    B = list(M.basis())
    NB = list(M.groundset().difference(B))
    dB = {}
    i = 0
    for e in B:
        dB[e] = i
        i += 1
    dNB = {}
    i = 0
    for e in NB:
        dNB[e] = i
        i += 1
    A = Matrix(ZZ, len(B), len(NB), 0)
    G = BipartiteGraph(
        A.transpose()
    )  # Sage's BipartiteGraph uses the column set as first color class. This is an edgeless graph.
    for e in NB:
        C = M.circuit(B + [e])
        for f in C.difference([e]):
            A[dB[f], dNB[e]] = 1
    # Change some entries from -1 to 1
    entries = BipartiteGraph(A.transpose()).edges(labels=False)
    while len(entries) > 0:
        L = [G.shortest_path(u, v) for u, v in entries]
        mindex, minval = min(enumerate(L), key=lambda x: len(x[1]))

        # if minval = 0, there is an edge not spanned by the current subgraph. Its entry is free to be scaled any way.
        if len(minval) > 0:
            # Check the subdeterminant
            S = frozenset(L[mindex])
            rows = []
            cols = []
            for i in S:
                if i < rk:
                    rows.append(i)
                else:
                    cols.append(i - rk)
            if A[rows, cols].det() != 0:
                A[entries[mindex][0], entries[mindex][1] - rk] = -1
        G.add_edge(entries[mindex][0], entries[mindex][1])
        entries.pop(mindex)
    return sage.matroids.linear_matroid.RegularMatroid(groundset=B + NB,
                                                       reduced_matrix=A)
예제 #19
0
def automorphisms(self):
    """
    Return a list of the automorphisms of the quadratic form.

    EXAMPLES::

        sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
        sage: Q.number_of_automorphisms()                     # optional -- souvigner
        48
        sage: 2^3 * factorial(3)
        48
        sage: len(Q.automorphisms())
        48

    ::

        sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
        sage: Q.number_of_automorphisms()                     # optional -- souvigner
        16
        sage: aut = Q.automorphisms()
        sage: len(aut)
        16
        sage: print([Q(M) == Q for M in aut])
        [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]

        sage: Q = QuadraticForm(ZZ, 3, [2, 1, 2, 2, 1, 3])
        sage: Q.automorphisms()
        [
        [1 0 0]  [-1  0  0]
        [0 1 0]  [ 0 -1  0]
        [0 0 1], [ 0  0 -1]
        ]

    ::

        sage: Q = DiagonalQuadraticForm(ZZ, [1, -1])
        sage: Q.automorphisms()
        Traceback (most recent call last):
        ...
        ValueError: not a definite form in QuadraticForm.automorphisms()
    """
    ## only for definite forms
    if not self.is_definite():
        raise ValueError("not a definite form in QuadraticForm.automorphisms()")

    ## Check for a cached value
    try:
        return self.__automorphisms
    except AttributeError:
        pass

    ## Find a basis of short vectors, and their lengths
    basis, pivot_lengths = self.basis_of_short_vectors(show_lengths=True)

    ## List the relevant vectors by length
    max_len = max(pivot_lengths)
    vector_list_by_length = self.short_primitive_vector_list_up_to_length(max_len + 1)

    ## Make the matrix A:e_i |--> v_i to our new basis.
    A = Matrix(basis).transpose()
    Ainv = A.inverse()
    # A1 = A.inverse() * A.det()
    # Q1 = A1.transpose() * self.matrix() * A1       ## This is the matrix of Q
    # Q = self.matrix() * A.det()**2
    Q2 = A.transpose() * self.matrix() * A  ## This is the matrix of Q in the new basis
    Q3 = self.matrix()

    ## Determine all automorphisms
    n = self.dim()
    Auto_list = []
    # ct = 0

    ## DIAGNOSTIC
    # print "n = " + str(n)
    # print "pivot_lengths = " + str(pivot_lengths)
    # print "vector_list_by_length = " + str(vector_list_by_length)
    # print "length of vector_list_by_length = " + str(len(vector_list_by_length))

    for index_vec in mrange([len(vector_list_by_length[pivot_lengths[i]]) for i in range(n)]):
        M = Matrix([vector_list_by_length[pivot_lengths[i]][index_vec[i]] for i in range(n)]).transpose()
        # Q1 = self.matrix()
        # if self(M) == self:
        # ct += 1
        # print "ct = ", ct, "   M = "
        # print M
        # print
        if M.transpose() * Q3 * M == Q2:  ## THIS DOES THE SAME THING! =(
            Auto_list.append(M * Ainv)

    ## Cache the answer and return the list
    self.__automorphisms = Auto_list
    self.__number_of_automorphisms = len(Auto_list)
    return Auto_list
예제 #20
0
def make_regular_matroid_from_matroid(matroid):
    r"""
    Attempt to construct a regular representation of a matroid.

    INPUT:

    - ``matroid`` -- a matroid.

    OUTPUT:

    Return a `(0, 1, -1)`-matrix over the integers such that, if the input is
    a regular matroid, then the output is a totally unimodular matrix
    representing that matroid.

    EXAMPLES::

        sage: from sage.matroids.utilities import make_regular_matroid_from_matroid
        sage: make_regular_matroid_from_matroid(
        ....:               matroids.CompleteGraphic(6)).is_isomorphic(
        ....:                                     matroids.CompleteGraphic(6))
        True
    """
    import sage.matroids.linear_matroid
    M = matroid
    if isinstance(M, sage.matroids.linear_matroid.RegularMatroid):
        return M
    rk = M.full_rank()
    # First create a reduced 0-1 matrix
    B = list(M.basis())
    NB = list(M.groundset().difference(B))
    dB = {}
    i = 0
    for e in B:
        dB[e] = i
        i += 1
    dNB = {}
    i = 0
    for e in NB:
        dNB[e] = i
        i += 1
    A = Matrix(ZZ, len(B), len(NB), 0)
    G = BipartiteGraph(A.transpose())  # Sage's BipartiteGraph uses the column set as first color class. This is an edgeless graph.
    for e in NB:
        C = M.circuit(B + [e])
        for f in C.difference([e]):
            A[dB[f], dNB[e]] = 1
    # Change some entries from -1 to 1
    entries = BipartiteGraph(A.transpose()).edges(labels=False)
    while len(entries) > 0:
        L = [G.shortest_path(u, v) for u, v in entries]
        mindex, minval = min(enumerate(L), key=lambda x: len(x[1]))

        # if minval = 0, there is an edge not spanned by the current subgraph. Its entry is free to be scaled any way.
        if len(minval) > 0:
            # Check the subdeterminant
            S = frozenset(L[mindex])
            rows = []
            cols = []
            for i in S:
                if i < rk:
                    rows.append(i)
                else:
                    cols.append(i - rk)
            if A[rows, cols].det() != 0:
                A[entries[mindex][0], entries[mindex][1] - rk] = -1
        G.add_edge(entries[mindex][0], entries[mindex][1])
        entries.pop(mindex)
    return sage.matroids.linear_matroid.RegularMatroid(groundset=B + NB, reduced_matrix=A)
def is_globally_equivalent_to(self, other, return_matrix=False, check_theta_to_precision='sturm', check_local_equivalence=True):
    """
    Determines if the current quadratic form is equivalent to the
    given form over ZZ.  If return_matrix is True, then we also return
    the transformation matrix M so that self(M) == other.

    INPUT:
        a QuadraticForm

    OUTPUT:
        boolean, and optionally a matrix

    EXAMPLES::
    
        sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
        sage: M = Matrix(ZZ, 4, 4, [1,2,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1])
        sage: Q1 = Q(M)
        sage: Q.(Q1)                                                    # optional -- souvigner
        True
        sage: MM = Q.is_globally_equivalent_to(Q1, return_matrix=True)  # optional -- souvigner
        sage: Q(MM) == Q1                                               # optional -- souvigner
        True
        
    ::
    
        sage: Q1 = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5])
        sage: Q2 = QuadraticForm(ZZ, 3, [2, 1, 2, 2, 1, 3])
        sage: Q3 = QuadraticForm(ZZ, 3, [8, 6, 5, 3, 4, 2])
        sage: Q1.is_globally_equivalent_to(Q2)                          # optional -- souvigner
        False
        sage: Q1.is_globally_equivalent_to(Q3)                          # optional -- souvigner
        True
        sage: M = Q1.is_globally_equivalent_to(Q3, True) ; M            # optional -- souvigner
        [-1 -1  0]
        [ 1  1  1]
        [-1  0  0]
        sage: Q1(M) == Q3                                               # optional -- souvigner
        True
        
    ::
        
        sage: Q = DiagonalQuadraticForm(ZZ, [1, -1])
        sage: Q.is_globally_equivalent_to(Q)
        Traceback (most recent call last):
        ...
        ValueError: not a definite form in QuadraticForm.is_globally_equivalent_to()
    
    """
    ## only for definite forms
    if not self.is_definite():
        raise ValueError, "not a definite form in QuadraticForm.is_globally_equivalent_to()"

    ## Check that other is a QuadraticForm
    #if not isinstance(other, QuadraticForm):
    if not is_QuadraticForm(other): 
        raise TypeError, "Oops!  You must compare two quadratic forms, but the argument is not a quadratic form. =("


    ## Now use the Souvigner code by default! =)
    return other.is_globally_equivalent__souvigner(self, return_matrix)    ## Note: We switch this because the Souvigner code has the opposite mapping convention to us.  (It takes the second argument to the first!)



    ## ----------------------------------  Unused Code below  ---------------------------------------------------------

    ## Check if the forms are locally equivalent
    if (check_local_equivalence == True):
        if not self.is_locally_equivalent_to(other):
            return False

    ## Check that the forms have the same theta function up to the desired precision (this can be set so that it determines the cusp form)
    if check_theta_to_precision != None:
        if self.theta_series(check_theta_to_precision, var_str='', safe_flag=False) != other.theta_series(check_theta_to_precision, var_str='', safe_flag=False):
            return False


    ## Make all possible matrices which give an isomorphism -- can we do this more intelligently?
    ## ------------------------------------------------------------------------------------------

    ## Find a basis of short vectors for one form, and try to match them with vectors of that length in the other one.
    basis_for_self, self_lengths = self.basis_of_short_vectors(show_lengths=True)
    max_len = max(self_lengths)
    short_vectors_of_other = other.short_vector_list_up_to_length(max_len + 1)

    ## Make the matrix A:e_i |--> v_i to our new basis.
    A = Matrix(basis_for_self).transpose()
    Q2 = A.transpose() * self.matrix() * A       ## This is the matrix of 'self' in the new basis
    Q3 = other.matrix()
        
    ## Determine all automorphisms
    n = self.dim()
    Auto_list = []
    
    ## DIAGNOSTIC
    #print "n = " + str(n)
    #print "pivot_lengths = " + str(pivot_lengths)
    #print "vector_list_by_length = " + str(vector_list_by_length)
    #print "length of vector_list_by_length = " + str(len(vector_list_by_length))
    
    for index_vec in mrange([len(short_vectors_of_other[self_lengths[i]])  for i in range(n)]):
        M = Matrix([short_vectors_of_other[self_lengths[i]][index_vec[i]]   for i in range(n)]).transpose()
        if M.transpose() * Q3 * M == Q2:
            if return_matrix:
                return A * M.inverse()
            else:
                return True
                        
    ## If we got here, then there is no isomorphism
    return False
def is_globally_equivalent__souvigner(self, other, return_transformation=False):
    """
    Uses the Souvigner code to compute the number of automorphisms.
    
    INPUT:
        a QuadraticForm

    OUTPUT:
        boolean, and optionally a matrix    
    
    EXAMPLES::

        sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5])
        sage: Q1 = QuadraticForm(ZZ, 3, [8, 6, 5, 3, 4, 2])
        sage: M = Q.is_globally_equivalent__souvigner(Q1, True) ; M   # optional -- souvigner
        [ 0  0 -1]
        [ 1  0  0]
        [-1  1  1]
        sage: Q1(M) == Q                                              # optional -- souvigner
        True
        
    """
    ## Write an input text file
    F_filename = '/tmp/tmp_isom_input' + str(random()) + ".txt"
    F = open(F_filename, 'w')
    #F = tempfile.NamedTemporaryFile(prefix='tmp_isom_input', suffix=".txt")  ## This failed because it may have hyphens, which are interpreted badly by the Souvigner code.
    F.write("\n #1 \n")

    ## Write the first form
    n = self.dim()
    F.write(str(n) + "x0 \n")      ## Use the lower-triangular form
    for i in range(n):
        for j in range(i+1):
            if i == j:
                F.write(str(2 * self[i,j]) + " ")
            else:
                F.write(str(self[i,j]) + " ")
        F.write("\n")

    ## Write the second form
    F.write("\n")
    n = self.dim()
    F.write(str(n) + "x0 \n")      ## Use the lower-triangular form
    for i in range(n):
        for j in range(i+1):
            if i == j:
                F.write(str(2 * other[i,j]) + " ")
            else:
                F.write(str(other[i,j]) + " ")
        F.write("\n")
    F.flush()
    #print "Input filename = ", F.name
    #os.system("less " + F.name)

    ## Call the Souvigner automorphism code
    souvigner_isom_path = os.path.join(SAGE_LOCAL,'bin','Souvigner_ISOM')
    G1 = tempfile.NamedTemporaryFile(prefix='tmp_isom_ouput', suffix=".txt")
    #print "Output filename = ", G1.name
    #print  "Executing the shell command:   " + souvigner_isom_path + " '" +  F.name + "' > '" + G1.name + "'"
    os.system(souvigner_isom_path + " '" +  F.name + "' > '" + G1.name +"'")


    ## Read the output
    G2 = open(G1.name, 'r')
    line = G2.readline()
    if line.startswith("Error:"):
        raise RuntimeError, "There is a problem using the souvigner code...  " + line
    elif line.find("not isomorphic") != -1:     ## Checking if this text appears, if so then they're not isomorphic!
        return False
    else:
        ## Decide whether to read the transformation matrix, and return true
        if not return_transformation:
            F.close()
            G1.close()
            G2.close()
            os.system("rm -f " + F_filename)
            return True
        else:
            ## Try to read the isomorphism matrix
            M = Matrix(ZZ, n, n)
            for i in range(n):
                new_row_text = G2.readline().split()
                #print new_row_text
                for j in range(n):
                    M[i,j] = new_row_text[j]

            ## Remove temporary files and return the value
            F.close()
            G1.close()
            G2.close()
            os.system("rm -f " + F_filename)
            if return_transformation:
                return M.transpose()
            else:
                return True
            #return True, M

    ## Raise and error if we're here:
    raise RuntimeError, "Oops! There is a problem..."
예제 #23
0
 def to_elt(alp):
     ref = self.domain().reflection(alp)
     m = Matrix([ref(x).to_vector() for x in self.domain().basis()])
     return self(m.transpose())
def automorphisms(self):
    """
    Return a list of the automorphisms of the quadratic form.

    EXAMPLES::

        sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
        sage: Q.number_of_automorphisms()                     # optional -- souvigner
        48
        sage: 2^3 * factorial(3)
        48
        sage: len(Q.automorphisms())
        48

    ::

        sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
        sage: Q.number_of_automorphisms()                     # optional -- souvigner
        16
        sage: aut = Q.automorphisms()
        sage: len(aut)
        16
        sage: print([Q(M) == Q for M in aut])
        [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]

        sage: Q = QuadraticForm(ZZ, 3, [2, 1, 2, 2, 1, 3])
        sage: Q.automorphisms()
        [
        [1 0 0]  [-1  0  0]
        [0 1 0]  [ 0 -1  0]
        [0 0 1], [ 0  0 -1]
        ]

    ::

        sage: Q = DiagonalQuadraticForm(ZZ, [1, -1])
        sage: Q.automorphisms()
        Traceback (most recent call last):
        ...
        ValueError: not a definite form in QuadraticForm.automorphisms()
    """
    ## only for definite forms
    if not self.is_definite():
        raise ValueError("not a definite form in QuadraticForm.automorphisms()")

    ## Check for a cached value
    try:
        return self.__automorphisms
    except AttributeError:
        pass


    ## Find a basis of short vectors, and their lengths
    basis, pivot_lengths = self.basis_of_short_vectors(show_lengths=True)

    ## List the relevant vectors by length
    max_len = max(pivot_lengths)
    vector_list_by_length = self.short_primitive_vector_list_up_to_length(max_len + 1)


    ## Make the matrix A:e_i |--> v_i to our new basis.
    A = Matrix(basis).transpose()
    Ainv = A.inverse()
    #A1 = A.inverse() * A.det()
    #Q1 = A1.transpose() * self.matrix() * A1       ## This is the matrix of Q
    #Q = self.matrix() * A.det()**2
    Q2 = A.transpose() * self.matrix() * A       ## This is the matrix of Q in the new basis
    Q3 = self.matrix()


    ## Determine all automorphisms
    n = self.dim()
    Auto_list = []
    #ct = 0

    ## DIAGNOSTIC
    #print "n = " + str(n)
    #print "pivot_lengths = " + str(pivot_lengths)
    #print "vector_list_by_length = " + str(vector_list_by_length)
    #print "length of vector_list_by_length = " + str(len(vector_list_by_length))

    for index_vec in mrange([len(vector_list_by_length[pivot_lengths[i]])  for i in range(n)]):
        M = Matrix([vector_list_by_length[pivot_lengths[i]][index_vec[i]]   for i in range(n)]).transpose()
        #Q1 = self.matrix()
        #if self(M) == self:
        #ct += 1
        #print "ct = ", ct, "   M = "
        #print M
        #print
        if M.transpose() * Q3 * M == Q2:       ## THIS DOES THE SAME THING! =(
            Auto_list.append(M * Ainv)


    ## Cache the answer and return the list
    self.__automorphisms = Auto_list
    self.__number_of_automorphisms = len(Auto_list)
    return Auto_list
예제 #25
0
def faces_in_smith(triangulation, angle_structure, cycles):
    N = edge_equation_matrix_taut_reduced(triangulation, angle_structure,
                                          cycles)
    N = Matrix(N)
    N = N.transpose()
    return N.smith_form()
예제 #26
0
def is_globally_equivalent__souvigner(self,
                                      other,
                                      return_transformation=False):
    """
    Uses the Souvigner code to compute the number of automorphisms.

    INPUT:
        a QuadraticForm

    OUTPUT:
        boolean, and optionally a matrix

    EXAMPLES::

        sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5])
        sage: Q1 = QuadraticForm(ZZ, 3, [8, 6, 5, 3, 4, 2])
        sage: M = Q.is_globally_equivalent__souvigner(Q1, True) ; M   # optional -- souvigner
        [ 0  0 -1]
        [ 1  0  0]
        [-1  1  1]
        sage: Q1(M) == Q                                              # optional -- souvigner
        True

    """
    ## Write an input text file
    F_filename = '/tmp/tmp_isom_input' + str(random()) + ".txt"
    F = open(F_filename, 'w')
    #F = tempfile.NamedTemporaryFile(prefix='tmp_isom_input', suffix=".txt")  ## This failed because it may have hyphens, which are interpreted badly by the Souvigner code.
    F.write("\n #1 \n")

    ## Write the first form
    n = self.dim()
    F.write(str(n) + "x0 \n")  ## Use the lower-triangular form
    for i in range(n):
        for j in range(i + 1):
            if i == j:
                F.write(str(2 * self[i, j]) + " ")
            else:
                F.write(str(self[i, j]) + " ")
        F.write("\n")

    ## Write the second form
    F.write("\n")
    n = self.dim()
    F.write(str(n) + "x0 \n")  ## Use the lower-triangular form
    for i in range(n):
        for j in range(i + 1):
            if i == j:
                F.write(str(2 * other[i, j]) + " ")
            else:
                F.write(str(other[i, j]) + " ")
        F.write("\n")
    F.flush()
    #print "Input filename = ", F.name
    #os.system("less " + F.name)

    ## Call the Souvigner automorphism code
    souvigner_isom_path = os.path.join(SAGE_LOCAL, 'bin', 'Souvigner_ISOM')
    G1 = tempfile.NamedTemporaryFile(prefix='tmp_isom_ouput', suffix=".txt")
    #print "Output filename = ", G1.name
    #print  "Executing the shell command:   " + souvigner_isom_path + " '" +  F.name + "' > '" + G1.name + "'"
    os.system(souvigner_isom_path + " '" + F.name + "' > '" + G1.name + "'")

    ## Read the output
    G2 = open(G1.name, 'r')
    line = G2.readline()
    if line.startswith("Error:"):
        raise RuntimeError("There is a problem using the souvigner code...  " +
                           line)
    elif line.find(
            "not isomorphic"
    ) != -1:  ## Checking if this text appears, if so then they're not isomorphic!
        return False
    else:
        ## Decide whether to read the transformation matrix, and return true
        if not return_transformation:
            F.close()
            G1.close()
            G2.close()
            os.system("rm -f " + F_filename)
            return True
        else:
            ## Try to read the isomorphism matrix
            M = Matrix(ZZ, n, n)
            for i in range(n):
                new_row_text = G2.readline().split()
                #print new_row_text
                for j in range(n):
                    M[i, j] = new_row_text[j]

            ## Remove temporary files and return the value
            F.close()
            G1.close()
            G2.close()
            os.system("rm -f " + F_filename)
            if return_transformation:
                return M.transpose()
            else:
                return True
            #return True, M

    ## Raise and error if we're here:
    raise RuntimeError("Oops! There is a problem...")
예제 #27
0
def is_globally_equivalent_to(self,
                              other,
                              return_matrix=False,
                              check_theta_to_precision='sturm',
                              check_local_equivalence=True):
    """
    Determines if the current quadratic form is equivalent to the
    given form over ZZ.  If return_matrix is True, then we also return
    the transformation matrix M so that self(M) == other.

    INPUT:
        a QuadraticForm

    OUTPUT:
        boolean, and optionally a matrix

    EXAMPLES::

        sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
        sage: M = Matrix(ZZ, 4, 4, [1,2,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1])
        sage: Q1 = Q(M)
        sage: Q.(Q1)                                                    # optional -- souvigner
        True
        sage: MM = Q.is_globally_equivalent_to(Q1, return_matrix=True)  # optional -- souvigner
        sage: Q(MM) == Q1                                               # optional -- souvigner
        True

    ::

        sage: Q1 = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5])
        sage: Q2 = QuadraticForm(ZZ, 3, [2, 1, 2, 2, 1, 3])
        sage: Q3 = QuadraticForm(ZZ, 3, [8, 6, 5, 3, 4, 2])
        sage: Q1.is_globally_equivalent_to(Q2)                          # optional -- souvigner
        False
        sage: Q1.is_globally_equivalent_to(Q3)                          # optional -- souvigner
        True
        sage: M = Q1.is_globally_equivalent_to(Q3, True) ; M            # optional -- souvigner
        [-1 -1  0]
        [ 1  1  1]
        [-1  0  0]
        sage: Q1(M) == Q3                                               # optional -- souvigner
        True

    ::

        sage: Q = DiagonalQuadraticForm(ZZ, [1, -1])
        sage: Q.is_globally_equivalent_to(Q)
        Traceback (most recent call last):
        ...
        ValueError: not a definite form in QuadraticForm.is_globally_equivalent_to()

    """
    ## only for definite forms
    if not self.is_definite():
        raise ValueError(
            "not a definite form in QuadraticForm.is_globally_equivalent_to()")

    ## Check that other is a QuadraticForm
    #if not isinstance(other, QuadraticForm):
    if not is_QuadraticForm(other):
        raise TypeError(
            "Oops!  You must compare two quadratic forms, but the argument is not a quadratic form. =("
        )

    ## Now use the Souvigner code by default! =)
    return other.is_globally_equivalent__souvigner(
        self, return_matrix
    )  ## Note: We switch this because the Souvigner code has the opposite mapping convention to us.  (It takes the second argument to the first!)

    ## ----------------------------------  Unused Code below  ---------------------------------------------------------

    ## Check if the forms are locally equivalent
    if (check_local_equivalence == True):
        if not self.is_locally_equivalent_to(other):
            return False

    ## Check that the forms have the same theta function up to the desired precision (this can be set so that it determines the cusp form)
    if check_theta_to_precision is not None:
        if self.theta_series(
                check_theta_to_precision, var_str='',
                safe_flag=False) != other.theta_series(
                    check_theta_to_precision, var_str='', safe_flag=False):
            return False

    ## Make all possible matrices which give an isomorphism -- can we do this more intelligently?
    ## ------------------------------------------------------------------------------------------

    ## Find a basis of short vectors for one form, and try to match them with vectors of that length in the other one.
    basis_for_self, self_lengths = self.basis_of_short_vectors(
        show_lengths=True)
    max_len = max(self_lengths)
    short_vectors_of_other = other.short_vector_list_up_to_length(max_len + 1)

    ## Make the matrix A:e_i |--> v_i to our new basis.
    A = Matrix(basis_for_self).transpose()
    Q2 = A.transpose() * self.matrix(
    ) * A  ## This is the matrix of 'self' in the new basis
    Q3 = other.matrix()

    ## Determine all automorphisms
    n = self.dim()
    Auto_list = []

    ## DIAGNOSTIC
    #print "n = " + str(n)
    #print "pivot_lengths = " + str(pivot_lengths)
    #print "vector_list_by_length = " + str(vector_list_by_length)
    #print "length of vector_list_by_length = " + str(len(vector_list_by_length))

    for index_vec in mrange(
        [len(short_vectors_of_other[self_lengths[i]]) for i in range(n)]):
        M = Matrix([
            short_vectors_of_other[self_lengths[i]][index_vec[i]]
            for i in range(n)
        ]).transpose()
        if M.transpose() * Q3 * M == Q2:
            if return_matrix:
                return A * M.inverse()
            else:
                return True

    ## If we got here, then there is no isomorphism
    return False
예제 #28
0
 def _borcherds_product_polyhedron(self, pole_order, prec, verbose=False):
     r"""
     Construct a polyhedron representing a cone of Heegner divisors. For internal use in the methods borcherds_input_basis() and borcherds_input_Qbasis().
     INPUT:
     - ``pole_order`` -- pole order
     - ``prec`` -- precision
     OUTPUT: a tuple consisting of an integral matrix M, a Polyhedron p, and a WeilRepModularFormsBasis X
     """
     K = self.weilrep().base_field()
     O_K = K.maximal_order()
     S = self.gram_matrix()
     wt = self.input_wt()
     w = self.weilrep()
     rds = w.rds()
     norm_dict = w.norm_dict()
     X = w.nearly_holomorphic_modular_forms_basis(wt,
                                                  pole_order,
                                                  prec,
                                                  verbose=verbose)
     N = len([g for g in rds if not norm_dict[tuple(g)]])
     v_list = w.coefficient_vector_exponents(0,
                                             1,
                                             starting_from=-pole_order,
                                             include_vectors=True)
     exp_list = [v[1] for v in v_list]
     d = w._ds_to_hds()
     v_list = [vector(d[tuple(v[0])]) for v in v_list]
     d = K.discriminant()
     positive = []
     zero = vector([0] * (len(exp_list) + 1))
     M = Matrix([
         x.coefficient_vector(starting_from=-pole_order, ending_with=0)[:-N]
         for x in X
     ])
     vs = M.transpose().kernel().basis()
     prec = floor(min(exp_list) / max(filter(bool, exp_list)))
     norm_list = w._norm_form().short_vector_list_up_to_length(prec + 1)
     units = w._units()
     _w = w._w()
     norm_list = [[a + b * _w for a, b in x] for x in norm_list]
     excluded_list = set([])
     if d >= -4:
         if d == -4:
             f = w.multiplication_by_i()
             f2 = None
         else:
             f = w.multiplication_by_zeta()
             f2 = f * f
     ys = []
     mult = len(units) // 2
     for i, n in enumerate(exp_list):
         if i not in excluded_list:
             ieq = copy(zero)
             ieq[i + 1] = 1
             v1 = v_list[i]
             if d >= -4:
                 v2 = f(v1)
                 j = next(j for j, x in enumerate(v_list)
                          if exp_list[i] == exp_list[j] and (all(
                              t in O_K
                              for t in x - v2) or all(t in O_K
                                                      for t in x + v2)))
                 ieq[j + 1] += 1
                 if i != j:
                     excluded_list.add(j)
                     y = copy(zero)
                     y[i + 1] = 1
                     y[j + 1] = -1
                     ys.append(y)
                 if f2 is not None:
                     v2 = f2(v1)
                     j = next(j for j, x in enumerate(v_list)
                              if exp_list[i] == exp_list[j] and (all(
                                  t in O_K
                                  for t in x - v2) or all(t in O_K
                                                          for t in x + v2)))
                     ieq[j + 1] += 1
                     if i != j:
                         excluded_list.add(j)
                         y = copy(zero)
                         y[i + 1] = 1
                         y[j + 1] = -1
                         ys.append(y)
             for j, m in enumerate(exp_list[:i]):
                 if j not in excluded_list:
                     N = m / n
                     if N in ZZ and N > 1:
                         v2 = v_list[j]
                         ieq[j + 1] = mult * any(
                             all(t in O_K for t in x * v1 + u * v2)
                             for x in norm_list[N] for u in units)
             positive.append(ieq)  # * denominator(ieq)
     p = Polyhedron(ieqs=positive,
                    eqns=[vector([0] + list(v)) for v in vs] + ys)
     return M, p, X