Exemple #1
0
def modform_cusp_info(calc, S, l, precLimit):
	"""
	This goes through all the cusps and compares the space given by `(f|R)[S]`
	with the space of Elliptic modular forms expansion at those cusps.
	"""

	assert l == S.det()
	assert list(calc.curlS) == [S]

	D = calc.D
	HermWeight = calc.HermWeight
	reducedCurlFSize = calc.matrixColumnCount
	herm_modform_fe_expannsion = FreeModule(QQ, reducedCurlFSize)

	if not Integer(l).is_squarefree():
		# The calculation of the cusp expansion space takes very long here, thus
		# we skip them for now.
		return None

	for cusp in Gamma0(l).cusps():
		if cusp == Infinity: continue
		M = cusp_matrix(cusp)

		try:
			gamma, R, tM = solveR(M, S, space=CurlO(D))
		except Exception:
			print (M, S)
			raise
		R.set_immutable() # for caching, we need it hashable

		herm_modforms = herm_modform_fe_expannsion.echelonized_basis_matrix().transpose()
		ell_R_denom, ell_R_order, M_R = calcMatrixTrans(calc, R)
		CycloDegree_R = CyclotomicField(ell_R_order).degree()
		print "M_R[0] nrows, ell_R_denom, ell_R_order, Cyclo degree:", \
			M_R[0].nrows(), ell_R_denom, ell_R_order, CycloDegree_R

		# The maximum precision we can use is M_R[0].nrows().
		# However, that can be quite huge (e.g. 600).
		ce_prec = min(precLimit, M_R[0].nrows())

		ce = cuspExpansions(level=l, weight=2*HermWeight, prec=ce_prec)
		ell_M_denom, ell_M = ce.expansion_at(SL2Z(M))
		print "ell_M_denom, ell_M nrows:", ell_M_denom, ell_M.nrows()
		ell_M_order = ell_R_order # not sure here. just try the one from R. toCyclPowerBase would fail if this doesn't work
		# CyclotomicField(l / prod(l.prime_divisors())) should also work.

		# Transform to same denom.
		denom_lcm = int(lcm(ell_R_denom, ell_M_denom))
		ell_M = addRows(ell_M, denom_lcm / ell_M_denom)
		M_R = [addRows(M_R_i, denom_lcm / ell_R_denom) for M_R_i in M_R]
		ell_R_denom = ell_M_denom = denom_lcm
		print "new denom:", denom_lcm
		assert ell_R_denom == ell_M_denom

		# ell_M rows are the elliptic FE. M_R[i] columns are the elliptic FE.
		# We expect that M_R gives a higher precision for the ell FE. I'm not sure
		# if this is always true but we expect it here (maybe not needed, though).
		print "precision of M_R[0], ell_M, wanted:", M_R[0].nrows(), ell_M.ncols(), ce_prec
		assert ell_M.ncols() >= ce_prec
		prec = min(M_R[0].nrows(), ell_M.ncols())
		# cut to have same precision
		M_R = [M_R_i[:prec,:] for M_R_i in M_R]
		ell_M = ell_M[:,:prec]
		assert ell_M.ncols() == M_R[0].nrows() == prec

		print "M_R[0] rank, herm rank, mult rank:", \
			M_R[0].rank(), herm_modforms.rank(), (M_R[0] * herm_modforms).rank()
		ell_R = [M_R_i * herm_modforms for M_R_i in M_R]

		# I'm not sure on this. Seems to be true and it simplifies things in the following.
		assert ell_M_order <= ell_R_order, "{0}".format((ell_M_order, ell_R_order))
		assert ell_R_order % ell_M_order == 0, "{0}".format((ell_M_order, ell_R_order))

		# Transform to same Cyclomotic Field in same power base.
		ell_M2 = toCyclPowerBase(ell_M, ell_M_order)
		ell_R2 = toLowerCyclBase(ell_R, ell_R_order, ell_M_order)
		# We must work with the matrix. maybe we should transform hf_M instead to a
		# higher order field instead, if this ever fails (I'm not sure).
		assert ell_R2 is not None
		assert len(ell_M2) == len(ell_R2) # They should have the same power base & same degree now.
		print "ell_M2[0], ell_R2[0] rank with order %i:" % ell_M_order, ell_M2[0].rank(), ell_R2[0].rank()

		assert len(M_R) == len(ell_M2)
		for i in range(len(ell_M2)):
			ell_M_space = ell_M2[i].row_space()
			ell_R_space = ell_R2[i].column_space()
			merged = ell_M_space.intersection(ell_R_space)

			herm_modform_fe_expannsion_Ci = M_R[i].solve_right( merged.basis_matrix().transpose() )
			herm_modform_fe_expannsion_Ci_module = herm_modform_fe_expannsion_Ci.column_module()
			herm_modform_fe_expannsion_Ci_module += M_R[i].right_kernel()

			extra_check_on_herm_superspace(
				vs=herm_modform_fe_expannsion_Ci_module,
				D=D, B_cF=calc.B_cF, HermWeight=HermWeight
			)

			herm_modform_fe_expannsion = herm_modform_fe_expannsion.intersection( herm_modform_fe_expannsion_Ci_module )
			print "power", i, merged.dimension(), herm_modform_fe_expannsion_Ci_module.dimension(), \
				herm_modform_fe_expannsion.dimension()
			current_dimension = herm_modform_fe_expannsion.dimension()

	return herm_modform_fe_expannsion
Exemple #2
0
    def is_finite(self):
        r"""
        Check whether the group is finite.

        A group is finite if and only if it is conjugate to a (finite) subgroup
        of O(2). This is actually also true in higher dimensions.

        EXAMPLES::

            sage: from flatsurf.geometry.finitely_generated_matrix_group import FinitelyGenerated2x2MatrixGroup
            sage: G = FinitelyGenerated2x2MatrixGroup([identity_matrix(2)])
            sage: G.is_finite()
            True

            sage: t = matrix(2, [2,1,1,1])

            sage: m1 = matrix([[0,1],[-1,0]])
            sage: m2 = matrix([[1,-1],[1,0]])
            sage: FinitelyGenerated2x2MatrixGroup([m1]).is_finite()
            True
            sage: FinitelyGenerated2x2MatrixGroup([t*m1*~t]).is_finite()
            True
            sage: FinitelyGenerated2x2MatrixGroup([m2]).is_finite()
            True
            sage: FinitelyGenerated2x2MatrixGroup([m1,m2]).is_finite()
            False
            sage: FinitelyGenerated2x2MatrixGroup([t*m1*~t,t*m2*~t]).is_finite()
            False

            sage: from flatsurf.geometry.polygon import number_field_elements_from_algebraics
            sage: c5 = QQbar.zeta(5).real()
            sage: s5 = QQbar.zeta(5).imag()
            sage: K, (c5,s5) = number_field_elements_from_algebraics([c5,s5])
            sage: r = matrix(K, 2, [c5,-s5,s5,c5])
            sage: FinitelyGenerated2x2MatrixGroup([m1,r]).is_finite()
            True
            sage: FinitelyGenerated2x2MatrixGroup([t*m1*~t,t*r*~t]).is_finite()
            True
            sage: FinitelyGenerated2x2MatrixGroup([m2,r]).is_finite()
            False
            sage: FinitelyGenerated2x2MatrixGroup([t*m2*~t, t*r*~t]).is_finite()
            False
        """
        # determinant and trace tests
        # (the code actually check that each generator is of finite order)
        for m in self._generators:
            if (m.det() != 1 and m.det() != -1) or \
               m.trace().abs() > 2 or \
               (m.trace().abs() == 2 and (m[0,1] or m[1,0])):
                return False

        gens = [g for g in self._generators if not g.is_scalar()]

        if len(gens) <= 1:
            return True

        # now we try to find a non-trivial invariant quadratic form
        from sage.modules.free_module import FreeModule
        V = FreeModule(self._matrix_space.base_ring(), 3)
        for g in gens:
            V = V.intersection(invariant_quadratic_forms(g))
            if not contains_definite_form(V):
                return False

        return True
def maximal_grading(L):
    r"""
    Return a maximal grading of a Lie algebra defined over an
    algebraically closed field.

    A maximal grading of a Lie algebra `\mathfrak{g}` is the finest
    possible grading of `\mathfrak{g}` over torsion free abelian groups.
    If `\mathfrak{g} = \bigoplus_{n\in \mathbb{Z}^k} \mathfrak{g}_n`
    is a maximal grading, then there exists no other grading
    `\mathfrak{g} = \bigoplus_{a\in A} \mathfrak{g}_a` over a torsion
    free abelian group `A` such that every `\mathfrak{g}_a` is contained
    in some `\mathfrak{g}_n`.

    EXAMPLES:

    A maximal grading of an abelian Lie algebra puts each basis element
    into an independent layer::

        sage: import sys, pathlib
        sage: sys.path.append(str(pathlib.Path().absolute()))
        sage: from lie_gradings.gradings.grading import maximal_grading
        sage: L = LieAlgebra(QQbar, 4, abelian=True)
        sage: maximal_grading(L)
        Grading over Additive abelian group isomorphic to Z + Z + Z + Z
        of Abelian Lie algebra on 4 generators (L[0], L[1], L[2], L[3])
        over Algebraic Field with nonzero layers
          (1, 0, 0, 0) : (L[3],)
          (0, 1, 0, 0) : (L[2],)
          (0, 0, 1, 0) : (L[1],)
          (0, 0, 0, 1) : (L[0],)

    A maximal grading of a free nilpotent Lie algebra decomposes the Lie
    algebra based on how many times each generator appears in the
    defining Lie bracket::

        sage: L = LieAlgebra(QQbar, 3, step=3)
        sage: maximal_grading(L)
        Grading over Additive abelian group isomorphic to Z + Z + Z of
        Free Nilpotent Lie algebra on 14 generators (X_1, X_2, X_3,
        X_12, X_13, X_23, X_112, X_113, X_122, X_123, X_132, X_133,
        X_223, X_233) over Algebraic Field with nonzero layers
          (1, 0, 0) : (X_1,)
          (0, 1, 0) : (X_2,)
          (1, 1, 0) : (X_12,)
          (1, 2, 0) : (X_122,)
          (2, 1, 0) : (X_112,)
          (0, 0, 1) : (X_3,)
          (0, 1, 1) : (X_23,)
          (0, 1, 2) : (X_233,)
          (0, 2, 1) : (X_223,)
          (1, 0, 1) : (X_13,)
          (1, 0, 2) : (X_133,)
          (1, 1, 1) : (X_123, X_132)
          (2, 0, 1) : (X_113,)
    """

    # define utilities to convert from matrices to vectors and back
    R = L.base_ring()
    n = L.dimension()
    MS = MatrixSpace(R, n, n)

    def matrix_to_vec(A):
        return vector(R, sum((list(Ar) for Ar in A.rows()), []))

    db = L.derivations_basis()

    def derivation_lincomb(vec):
        return sum((vk * dk for vk, dk in zip(vec, db)), MS.zero())

    # iteratively construct larger and larger tori of derivations
    t = []
    while True:
        # compute the centralizer of the torus in the derivation algebra
        ker = FreeModule(R, len(db))
        for der in t:
            # form the matrix of ad(der) with rows
            # the images of basis derivations
            A = matrix([matrix_to_vec(der * X - X * der) for X in db])
            ker = ker.intersection(A.left_kernel())
        cb = [derivation_lincomb(v) for v in ker.basis()]

        # check the basis of the centralizer for semisimple parts outside of t
        gl = FreeModule(R, n * n)
        t_submodule = gl.submodule([matrix_to_vec(der) for der in t])
        for A in cb:
            As, An = jordan_decomposition(A)
            if matrix_to_vec(As) not in t_submodule:
                # extend the torus by As
                t.append(As)
                break
        else:
            # no new elements found, so the torus is maximal
            break

    # compute the eigenspace intersections to get the concrete grading
    common_eigenspaces = [([], FreeModule(R, n))]
    for A in t:
        new_eigenspaces = []
        eig = A.right_eigenspaces()
        for ev, V in common_eigenspaces:
            for ew, W in eig:
                VW = V.intersection(W)
                if VW.dimension() > 0:
                    new_eigenspaces.append((ev + [ew], VW))
        common_eigenspaces = new_eigenspaces

    if not t:
        # zero dimensional maximal torus
        # the only grading is the trivial grading
        magma = AdditiveAbelianGroup([])
        layers = {magma.zero(): L.basis().list()}
        return grading(L, layers, magma=magma)

    # define a grading with layers indexed by tuples of eigenvalues
    cm = get_coercion_model()
    all_eigenvalues = sum((ev for ev, V in common_eigenspaces), [])
    k = len(common_eigenspaces[0][0])
    evR = cm.common_parent(*all_eigenvalues)
    layers = {
        tuple(ev): [L.from_vector(v) for v in V.basis()]
        for ev, V in common_eigenspaces
    }
    magma = evR.cartesian_product(*[evR] * (k - 1))
    gr = grading(L, layers, magma=magma)

    # convert to a grading over Z^k
    return gr.universal_realization()
    def is_finite(self):
        r"""
        Check whether the group is finite.

        A group is finite if and only if it is conjugate to a (finite) subgroup
        of O(2). This is actually also true in higher dimensions.

        EXAMPLES::

            sage: from flatsurf.geometry.finitely_generated_matrix_group import FinitelyGenerated2x2MatrixGroup
            sage: G = FinitelyGenerated2x2MatrixGroup([identity_matrix(2)])
            sage: G.is_finite()
            True

            sage: t = matrix(2, [2,1,1,1])

            sage: m1 = matrix([[0,1],[-1,0]])
            sage: m2 = matrix([[1,-1],[1,0]])
            sage: FinitelyGenerated2x2MatrixGroup([m1]).is_finite()
            True
            sage: FinitelyGenerated2x2MatrixGroup([t*m1*~t]).is_finite()
            True
            sage: FinitelyGenerated2x2MatrixGroup([m2]).is_finite()
            True
            sage: FinitelyGenerated2x2MatrixGroup([m1,m2]).is_finite()
            False
            sage: FinitelyGenerated2x2MatrixGroup([t*m1*~t,t*m2*~t]).is_finite()
            False

            sage: from flatsurf.geometry.polygon import number_field_elements_from_algebraics
            sage: c5 = QQbar.zeta(5).real()
            sage: s5 = QQbar.zeta(5).imag()
            sage: K, (c5,s5) = number_field_elements_from_algebraics([c5,s5])
            sage: r = matrix(K, 2, [c5,-s5,s5,c5])
            sage: FinitelyGenerated2x2MatrixGroup([m1,r]).is_finite()
            True
            sage: FinitelyGenerated2x2MatrixGroup([t*m1*~t,t*r*~t]).is_finite()
            True
            sage: FinitelyGenerated2x2MatrixGroup([m2,r]).is_finite()
            False
            sage: FinitelyGenerated2x2MatrixGroup([t*m2*~t, t*r*~t]).is_finite()
            False
        """
        # determinant and trace tests
        # (the code actually check that each generator is of finite order)
        for m in self._generators:
            if (m.det() != 1 and m.det() != -1) or \
               m.trace().abs() > 2 or \
               (m.trace().abs() == 2 and (m[0,1] or m[1,0])):
                   return False

        gens = [g for g in self._generators if not g.is_scalar()]

        if len(gens) <= 1:
            return True

        # now we try to find a non-trivial invariant quadratic form
        from sage.modules.free_module import FreeModule
        V = FreeModule(self._matrix_space.base_ring(), 3)
        for g in gens:
            V = V.intersection(invariant_quadratic_forms(g))
            if not contains_definite_form(V):
                return False

        return True