Beispiel #1
0
    def __init__(self, R, names, index_set, **kwds):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: L = LieAlgebra(QQ, 3, 'x', abelian=True)
            sage: TestSuite(L).run()
        """
        LieAlgebraWithStructureCoefficients.__init__(self, R, Family({}), names, index_set, **kwds)
Beispiel #2
0
    def __init__(self, R, names, index_set, **kwds):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: L = LieAlgebra(QQ, 3, 'x', abelian=True)
            sage: TestSuite(L).run()
        """
        LieAlgebraWithStructureCoefficients.__init__(self, R, Family({}),
                                                     names, index_set, **kwds)
Beispiel #3
0
    def __init__(self, R, names, index_set, category, **kwds):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: L = LieAlgebra(QQ, 3, 'x', abelian=True)
            sage: TestSuite(L).run()
        """
        cat = LieAlgebras(R).FiniteDimensional().WithBasis().Nilpotent()
        category = cat.or_subcategory(category)
        LieAlgebraWithStructureCoefficients.__init__(self, R, Family({}), names,
                                                     index_set, category, **kwds)
Beispiel #4
0
    def __init__(self, R, s_coeff, names, index_set, step=None, **kwds):
        r"""
        Initialize ``self``.

        EXAMPLES::

            sage: L.<X,Y,Z,W> = LieAlgebra(QQ, {('X','Y'): {'Z': 1}}, nilpotent=True)
            sage: TestSuite(L).run()
        """
        if step is not None:
            self._step = step

        LieAlgebraWithStructureCoefficients.__init__(self, R, s_coeff, names,
                                                     index_set, **kwds)
Beispiel #5
0
    def __init__(self, R, s_coeff, names, index_set, step=None, **kwds):
        r"""
        Initialize ``self``.

        EXAMPLES::

            sage: L.<X,Y,Z,W> = LieAlgebra(QQ, {('X','Y'): {'Z': 1}}, nilpotent=True)
            sage: TestSuite(L).run()
        """
        if step is not None:
            self._step = step

        LieAlgebraWithStructureCoefficients.__init__(self, R, s_coeff,
                                                     names, index_set,
                                                     **kwds)
Beispiel #6
0
    def __classcall_private__(cls,
                              R,
                              classification,
                              s_coeff,
                              names,
                              index_set=None,
                              category=None,
                              **kwds):
        r"""
        Normalize input to ensure a unique representation.
        """
        names, index_set = standardize_names_index_set(names, index_set)
        s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff(
            s_coeff, index_set)

        cat = LieAlgebras(R).FiniteDimensional().WithBasis().Nilpotent()
        category = cat.or_subcategory(category)

        return super(ClassifiedNilpotentLieAlgebra,
                     cls).__classcall__(cls,
                                        R,
                                        classification,
                                        s_coeff,
                                        names,
                                        index_set,
                                        category=category,
                                        **kwds)
Beispiel #7
0
    def __classcall_private__(cls, R, s_coeff, names=None, index_set=None,
                              category=None, **kwds):
        """
        Normalize input to ensure a unique representation.

        EXAMPLES:

        If the variable order is specified, the order of structural
        coefficients does not matter::

            sage: from sage.algebras.lie_algebras.nilpotent_lie_algebra import NilpotentLieAlgebra_dense
            sage: L1.<x,y,z> = NilpotentLieAlgebra_dense(QQ, {('x','y'): {'z': 1}})
            sage: L2.<x,y,z> = NilpotentLieAlgebra_dense(QQ, {('y','x'): {'z': -1}})
            sage: L1 is L2
            True

        If the variables are implicitly defined by the structural coefficients,
        the ordering may be different and the Lie algebras will be considered
        different::

            sage: from sage.algebras.lie_algebras.nilpotent_lie_algebra import NilpotentLieAlgebra_dense
            sage: L1 = NilpotentLieAlgebra_dense(QQ, {('x','y'): {'z': 1}})
            sage: L2 = NilpotentLieAlgebra_dense(QQ, {('y','x'): {'z': -1}})
            sage: L1
            Nilpotent Lie algebra on 3 generators (x, y, z) over Rational Field
            sage: L2
            Nilpotent Lie algebra on 3 generators (y, x, z) over Rational Field
            sage: L1 is L2
            False

        Constructed using two different methods from :class:`LieAlgebra`
        yields the same Lie algebra::

            sage: sc = {('X','Y'): {'Z': 1}}
            sage: C = LieAlgebras(QQ).Nilpotent().FiniteDimensional().WithBasis()
            sage: L1.<X,Y,Z> = LieAlgebra(QQ, sc, category=C)
            sage: L2 = LieAlgebra(QQ, sc, nilpotent=True, names=['X','Y','Z'])
            sage: L1 is L2
            True
        """
        if not names:
            # extract names from structural coefficients
            names = []
            for (X, Y), d in s_coeff.items():
                if X not in names: names.append(X)
                if Y not in names: names.append(Y)
                for k in d:
                    if k not in names: names.append(k)

        from sage.structure.indexed_generators import standardize_names_index_set
        names, index_set = standardize_names_index_set(names, index_set)
        s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff(
            s_coeff, index_set)

        cat = LieAlgebras(R).FiniteDimensional().WithBasis().Nilpotent()
        category = cat.or_subcategory(category)

        return super(NilpotentLieAlgebra_dense, cls).__classcall__(
            cls, R, s_coeff, names, index_set, category=category, **kwds)
Beispiel #8
0
    def __init__(self, I, L, names, index_set, category=None):
        r"""
        Initialize ``self``.

        TESTS::

            sage: L.<x,y,z> = LieAlgebra(SR, {('x','y'): {'x':1}})
            sage: K = L.quotient(y)
            sage: K.dimension()
            1
            sage: TestSuite(K).run()
        """
        B = L.basis()
        sm = L.module().submodule_with_basis(
            [I.reduce(B[i]).to_vector() for i in index_set])
        SB = sm.basis()

        # compute and normalize structural coefficients for the quotient
        s_coeff = {}
        for i, ind_i in enumerate(index_set):
            for j in range(i + 1, len(index_set)):
                ind_j = index_set[j]

                brkt = I.reduce(L.bracket(SB[i], SB[j]))
                brktvec = sm.coordinate_vector(brkt.to_vector())
                s_coeff[(ind_i, ind_j)] = dict(zip(index_set, brktvec))
        s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff(
            s_coeff, index_set)

        self._ambient = L
        self._I = I
        self._sm = sm

        LieAlgebraWithStructureCoefficients.__init__(self,
                                                     L.base_ring(),
                                                     s_coeff,
                                                     names,
                                                     index_set,
                                                     category=category)

        # register the quotient morphism as a conversion
        H = Hom(L, self)
        f = SetMorphism(H, self.retract)
        self.register_conversion(f)
Beispiel #9
0
    def __init__(self, I, L, names, index_set, category=None):
        r"""
        Initialize ``self``.

        TESTS::

            sage: L.<x,y,z> = LieAlgebra(SR, {('x','y'): {'x':1}})
            sage: K = L.quotient(y)
            sage: K.dimension()
            1
            sage: TestSuite(K).run()
        """
        B = L.basis()
        sm = L.module().submodule_with_basis([I.reduce(B[i]).to_vector()
                                              for i in index_set])
        SB = sm.basis()

        # compute and normalize structural coefficients for the quotient
        s_coeff = {}
        for i, ind_i in enumerate(index_set):
            for j in range(i + 1, len(index_set)):
                ind_j = index_set[j]

                brkt = I.reduce(L.bracket(SB[i], SB[j]))
                brktvec = sm.coordinate_vector(brkt.to_vector())
                s_coeff[(ind_i, ind_j)] = dict(zip(index_set, brktvec))
        s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff(
            s_coeff, index_set)

        self._ambient = L
        self._I = I
        self._sm = sm

        LieAlgebraWithStructureCoefficients.__init__(
            self, L.base_ring(), s_coeff, names, index_set, category=category)

        # register the quotient morphism as a conversion
        H = Hom(L, self)
        f = SetMorphism(H, self.retract)
        self.register_conversion(f)
Beispiel #10
0
def affine_transformations_line(R, names=['X', 'Y'], representation='bracket'):
    """
    The Lie algebra of affine transformations of the line.

    EXAMPLES::

        sage: L = lie_algebras.affine_transformations_line(QQ)
        sage: L.structure_coefficients()
        Finite family {('X', 'Y'): Y}
        sage: X, Y = L.lie_algebra_generators()
        sage: L[X, Y] == Y
        True
        sage: TestSuite(L).run()
        sage: L = lie_algebras.affine_transformations_line(QQ, representation="matrix")
        sage: X, Y = L.lie_algebra_generators()
        sage: L[X, Y] == Y
        True
        sage: TestSuite(L).run()
    """
    if isinstance(names, str):
        names = names.split(',')
    names = tuple(names)
    if representation == 'matrix':
        from sage.matrix.matrix_space import MatrixSpace
        MS = MatrixSpace(R, 2, sparse=True)
        one = R.one()
        gens = tuple(MS({(0, i): one}) for i in range(2))
        from sage.algebras.lie_algebras.lie_algebra import LieAlgebraFromAssociative
        return LieAlgebraFromAssociative(MS, gens, names=names)
    X = names[0]
    Y = names[1]
    from sage.algebras.lie_algebras.structure_coefficients import LieAlgebraWithStructureCoefficients
    s_coeff = {(X, Y): {Y: R.one()}}
    L = LieAlgebraWithStructureCoefficients(R, s_coeff, names=names)
    L.rename(
        "Lie algebra of affine transformations of a line over {}".format(R))
    return L
Beispiel #11
0
def affine_transformations_line(R, names=['X', 'Y'], representation='bracket'):
    """
    The Lie algebra of affine transformations of the line.

    EXAMPLES::

        sage: L = lie_algebras.affine_transformations_line(QQ)
        sage: L.structure_coefficients()
        Finite family {('X', 'Y'): Y}
        sage: X, Y = L.lie_algebra_generators()
        sage: L[X, Y] == Y
        True
        sage: TestSuite(L).run()
        sage: L = lie_algebras.affine_transformations_line(QQ, representation="matrix")
        sage: X, Y = L.lie_algebra_generators()
        sage: L[X, Y] == Y
        True
        sage: TestSuite(L).run()
    """
    if isinstance(names, str):
        names = names.split(',')
    names = tuple(names)
    if representation == 'matrix':
        from sage.matrix.matrix_space import MatrixSpace
        MS = MatrixSpace(R, 2, sparse=True)
        one = R.one()
        gens = tuple(MS({(0,i):one}) for i in range(2))
        from sage.algebras.lie_algebras.lie_algebra import LieAlgebraFromAssociative
        return LieAlgebraFromAssociative(MS, gens, names=names)
    X = names[0]
    Y = names[1]
    from sage.algebras.lie_algebras.structure_coefficients import LieAlgebraWithStructureCoefficients
    s_coeff = {(X,Y): {Y:R.one()}}
    L = LieAlgebraWithStructureCoefficients(R, s_coeff, names=names)
    L.rename("Lie algebra of affine transformations of a line over {}".format(R))
    return L
Beispiel #12
0
def three_dimensional(R, a, b, c, d, names=['X', 'Y', 'Z']):
    r"""
    The 3-dimensional Lie algebra over a given commutative ring `R`
    with basis `\{X, Y, Z\}` subject to the relations:

    .. MATH::

        [X, Y] = aZ + dY, \quad [Y, Z] = bX, \quad [Z, X] = cY + dZ

    where `a,b,c,d \in R`.

    This is always a well-defined 3-dimensional Lie algebra, as can
    be easily proven by computation.

    EXAMPLES::

        sage: L = lie_algebras.three_dimensional(QQ, 4, 1, -1, 2)
        sage: L.structure_coefficients()
        Finite family {('X', 'Y'): 2*Y + 4*Z, ('X', 'Z'): Y - 2*Z, ('Y', 'Z'): X}
        sage: TestSuite(L).run()
        sage: L = lie_algebras.three_dimensional(QQ, 1, 0, 0, 0)
        sage: L.structure_coefficients()
        Finite family {('X', 'Y'): Z}
        sage: L = lie_algebras.three_dimensional(QQ, 0, 0, -1, -1)
        sage: L.structure_coefficients()
        Finite family {('X', 'Y'): -Y, ('X', 'Z'): Y + Z}
        sage: L = lie_algebras.three_dimensional(QQ, 0, 1, 0, 0)
        sage: L.structure_coefficients()
        Finite family {('Y', 'Z'): X}
        sage: lie_algebras.three_dimensional(QQ, 0, 0, 0, 0)
        Abelian Lie algebra on 3 generators (X, Y, Z) over Rational Field
        sage: Q.<a,b,c,d> = PolynomialRing(QQ)
        sage: L = lie_algebras.three_dimensional(Q, a, b, c, d)
        sage: L.structure_coefficients()
        Finite family {('X', 'Y'): d*Y + a*Z, ('X', 'Z'): (-c)*Y + (-d)*Z, ('Y', 'Z'): b*X}
        sage: TestSuite(L).run()
    """
    if isinstance(names, str):
        names = names.split(',')
    X = names[0]
    Y = names[1]
    Z = names[2]
    from sage.algebras.lie_algebras.structure_coefficients import LieAlgebraWithStructureCoefficients
    s_coeff = {(X,Y): {Z:a, Y:d}, (Y,Z): {X:b}, (Z,X): {Y:c, Z:d}}
    return LieAlgebraWithStructureCoefficients(R, s_coeff, tuple(names))
Beispiel #13
0
def _symbolic_lie_algebra_copy(L):
    r"""
    Create a copy of the Lie algebra ``L`` admitting symbolic coefficients.

    This is used internally to compute a symbolic expression for the group law.

    INPUT:

    - ``L`` -- a finite dimensional Lie algebra with basis

    EXAMPLES::

        sage: from sage.groups.lie_gps.nilpotent_lie_group import _symbolic_lie_algebra_copy
        sage: L = LieAlgebra(QQ, 2, step=2)
        sage: L_SR = _symbolic_lie_algebra_copy(L)
        sage: L.structure_coefficients()
        Finite family {((1,), (2,)): X_12}
        sage: L_SR.structure_coefficients()
        Finite family {((1,), (2,)): L[(1, 2)]}

    TESTS:

    Verify that copying works with something that is not an instance of
    :class:`LieAlgebraWithStructureCoefficients`::

        sage: from sage.groups.lie_gps.nilpotent_lie_group import _symbolic_lie_algebra_copy
        sage: L = lie_algebras.Heisenberg(QQ, 1)
        sage: hasattr(L, 'change_ring')
        False
        sage: L_SR = _symbolic_lie_algebra_copy(L)
        sage: L_SR.structure_coefficients()
        Finite family {('p1', 'q1'): z}
    """
    try:
        return L.change_ring(SR)
    except AttributeError:
        s_coeff = L.structure_coefficients()
        index_set = L.basis().keys()
        names = L.variable_names()
        return LieAlgebraWithStructureCoefficients(SR,
                                                   s_coeff,
                                                   names=names,
                                                   index_set=index_set)
Beispiel #14
0
    def __classcall_private__(cls,
                              R,
                              s_coeff,
                              names=None,
                              index_set=None,
                              category=None,
                              **kwds):
        """
        Normalize input to ensure a unique representation.

        EXAMPLES:

        If the variable order is specified, the order of structural
        coefficients does not matter::

            sage: from sage.algebras.lie_algebras.nilpotent_lie_algebra import NilpotentLieAlgebra_dense
            sage: L1.<x,y,z> = NilpotentLieAlgebra_dense(QQ, {('x','y'): {'z': 1}})
            sage: L2.<x,y,z> = NilpotentLieAlgebra_dense(QQ, {('y','x'): {'z': -1}})
            sage: L1 is L2
            True

        If the variables are implicitly defined by the structural coefficients,
        the ordering may be different and the Lie algebras will be considered
        different::

            sage: from sage.algebras.lie_algebras.nilpotent_lie_algebra import NilpotentLieAlgebra_dense
            sage: L1 = NilpotentLieAlgebra_dense(QQ, {('x','y'): {'z': 1}})
            sage: L2 = NilpotentLieAlgebra_dense(QQ, {('y','x'): {'z': -1}})
            sage: L1
            Nilpotent Lie algebra on 3 generators (x, y, z) over Rational Field
            sage: L2
            Nilpotent Lie algebra on 3 generators (y, x, z) over Rational Field
            sage: L1 is L2
            False

        Constructed using two different methods from :class:`LieAlgebra`
        yields the same Lie algebra::

            sage: sc = {('X','Y'): {'Z': 1}}
            sage: C = LieAlgebras(QQ).Nilpotent().FiniteDimensional().WithBasis()
            sage: L1.<X,Y,Z> = LieAlgebra(QQ, sc, category=C)
            sage: L2 = LieAlgebra(QQ, sc, nilpotent=True, names=['X','Y','Z'])
            sage: L1 is L2
            True
        """
        if not names:
            # extract names from structural coefficients
            names = []
            for (X, Y), d in s_coeff.items():
                if X not in names: names.append(X)
                if Y not in names: names.append(Y)
                for k in d:
                    if k not in names: names.append(k)

        from sage.structure.indexed_generators import standardize_names_index_set
        names, index_set = standardize_names_index_set(names, index_set)
        s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff(
            s_coeff, index_set)

        cat = LieAlgebras(R).FiniteDimensional().WithBasis().Nilpotent()
        category = cat.or_subcategory(category)

        return super(NilpotentLieAlgebra_dense,
                     cls).__classcall__(cls,
                                        R,
                                        s_coeff,
                                        names,
                                        index_set,
                                        category=category,
                                        **kwds)
Beispiel #15
0
    def __init__(self, R, r, s, names, naming, category, **kwds):
        r"""
        Initialize ``self``

        EXAMPLES::

            sage: L = LieAlgebra(ZZ, 2, step=2)
            sage: TestSuite(L).run()

            sage: L = LieAlgebra(QQ, 4, step=3)
            sage: TestSuite(L).run()  # long time
        """
        if r not in ZZ or r <= 0:
            raise ValueError("number of generators %s is not "
                             "a positive integer" % r)
        if s not in ZZ or s <= 0:
            raise ValueError("step %s is not a positive integer" % s)

        # extract an index set from the Lyndon words of the corresponding
        # free Lie algebra, and store the corresponding elements in a dict
        from sage.algebras.lie_algebras.lie_algebra import LieAlgebra

        free_gen_names = ['F%d' % k for k in range(r)]
        free_gen_names_inv = {
            val: i + 1
            for i, val in enumerate(free_gen_names)
        }
        L = LieAlgebra(R, free_gen_names).Lyndon()

        basis_by_deg = {d: [] for d in range(1, s + 1)}
        for d in range(1, s + 1):
            for X in L.graded_basis(d):
                # convert brackets of form [X_1, [X_1, X_2]] to words (1,1,2)
                w = tuple(free_gen_names_inv[s]
                          for s in X.leading_support().to_word())
                basis_by_deg[d].append((w, X))

        index_set = [ind for d in basis_by_deg for ind, val in basis_by_deg[d]]

        if len(names) == 1 and len(index_set) > 1:
            if not naming:
                if r >= 10:
                    naming = 'linear'
                else:
                    naming = 'index'
            if naming == 'linear':
                names = [
                    '%s_%d' % (names[0], k + 1) for k in range(len(index_set))
                ]
            elif naming == 'index':
                if r >= 10:
                    raise ValueError("'index' naming scheme not supported for "
                                     "10 or more generators")
                names = [
                    '%s_%s' % (names[0], "".join(str(s) for s in ind))
                    for ind in index_set
                ]
            else:
                raise ValueError("unknown naming scheme %s" % naming)

        # extract structural coefficients from the free Lie algebra
        s_coeff = {}
        for dx in range(1, s + 1):
            # Brackets are only computed when deg(X) + deg(Y) <= s
            # We also require deg(Y) >= deg(X) by the ordering
            for dy in range(dx, s + 1 - dx):
                if dx == dy:
                    for i, val in enumerate(basis_by_deg[dx]):
                        X_ind, X = val
                        for Y_ind, Y in basis_by_deg[dy][i + 1:]:
                            Z = L[X, Y]
                            if not Z.is_zero():
                                s_coeff[(X_ind, Y_ind)] = {
                                    W_ind: Z[W.leading_support()]
                                    for W_ind, W in basis_by_deg[dx + dy]
                                }
                else:
                    for X_ind, X in basis_by_deg[dx]:
                        for Y_ind, Y in basis_by_deg[dy]:
                            Z = L[X, Y]
                            if not Z.is_zero():
                                s_coeff[(X_ind, Y_ind)] = {
                                    W_ind: Z[W.leading_support()]
                                    for W_ind, W in basis_by_deg[dx + dy]
                                }

        names, index_set = standardize_names_index_set(names, index_set)
        s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff(
            s_coeff, index_set)

        NilpotentLieAlgebra_dense.__init__(self,
                                           R,
                                           s_coeff,
                                           names,
                                           index_set,
                                           s,
                                           category=category,
                                           **kwds)
    def __init__(self, R, cartan_type):
        r"""
        Initialize ``self``.

        TESTS::

            sage: L = LieAlgebra(QQ, cartan_type=['A',2])
            sage: TestSuite(L).run()  # long time
        """
        self._cartan_type = cartan_type
        RL = cartan_type.root_system().root_lattice()
        alpha = RL.simple_roots()
        p_roots = list(RL.positive_roots_by_height())
        n_roots = [-x for x in p_roots]
        self._p_roots_index = {al: i for i,al in enumerate(p_roots)}
        alphacheck = RL.simple_coroots()
        roots = frozenset(RL.roots())
        num_sroots = len(alpha)
        one = R.one()

        # Determine the signs for the structure coefficients from the root system
        # We first create the special roots
        sp_sign = {}
        for i,a in enumerate(p_roots):
            for b in p_roots[i+1:]:
                if a + b not in p_roots:
                    continue

                # Compute the sign for the extra special pair
                x, y = (a + b).extraspecial_pair()

                if (x, y) == (a, b): # If it already is an extra special pair
                    if (x, y) not in sp_sign:
                        # This swap is so the structure coefficients match with GAP
                        if (sum(x.coefficients()) == sum(y.coefficients())
                            and str(x) > str(y)):
                            y,x = x,y
                        sp_sign[(x, y)] = -one
                        sp_sign[(y, x)] = one
                    continue

                if b - x in roots:
                    t1 = ((b-x).norm_squared() / b.norm_squared()
                          * sp_sign[(x, b-x)] * sp_sign[(a, y-a)])
                else:
                    t1 = 0
                if a - x in roots:
                    t2 = ((a-x).norm_squared() / a.norm_squared()
                          * sp_sign[(x, a-x)] * sp_sign[(b, y-b)])
                else:
                    t2 = 0

                if t1 - t2 > 0:
                    sp_sign[(a,b)] = -one
                elif t2 - t1 > 0:
                    sp_sign[(a,b)] = one
                sp_sign[(b,a)] = -sp_sign[(a,b)]

        # Function to construct the structure coefficients (up to sign)
        def e_coeff(r, s):
            p = 1
            while r - p*s in roots:
                p += 1
            return p

        # Now we can compute all necessary structure coefficients
        s_coeffs = {}
        for i,r in enumerate(p_roots):
            # [e_r, h_i] and [h_i, f_r]
            for ac in alphacheck:
                c = r.scalar(ac)
                if c == 0:
                    continue
                s_coeffs[(r, ac)] = {r: -c}
                s_coeffs[(ac, -r)] = {-r: -c}

            # [e_r, f_r]
            s_coeffs[(r, -r)] = {alphacheck[j]: c
                                 for j, c in r.associated_coroot()}

            # [e_r, e_s] and [e_r, f_s] with r != +/-s
            # We assume s is positive, as otherwise we negate
            #   both r and s and the resulting coefficient
            for j, s in enumerate(p_roots[i+1:]):
                j += i+1 # Offset
                # Since h(s) >= h(r), we have s - r > 0 when s - r is a root
                # [f_r, e_s]
                if s - r in p_roots:
                    c = e_coeff(r, -s)
                    a, b = s-r, r
                    if self._p_roots_index[a] > self._p_roots_index[b]: # Note a != b
                        c *= -sp_sign[(b, a)]
                    else:
                        c *= sp_sign[(a, b)]
                    s_coeffs[(-r, s)] = {a: -c}
                    s_coeffs[(r, -s)] = {-a: c}

                # [e_r, e_s]
                a = r + s
                if a in p_roots:
                    # (r, s) is a special pair
                    c = e_coeff(r, s) * sp_sign[(r, s)]
                    s_coeffs[(r, s)] = {a: c}
                    s_coeffs[(-r, -s)] = {-a: -c}

        # Lastly, make sure a < b for all (a, b) in the coefficients and flip if necessary
        for k in s_coeffs.keys():
            a,b = k[0], k[1]
            if self._basis_key(a) > self._basis_key(b):
                s_coeffs[(b,a)] = [(index, -v) for index,v in s_coeffs[k].items()]
                del s_coeffs[k]
            else:
                s_coeffs[k] = s_coeffs[k].items()

        names = ['e{}'.format(i) for i in range(1, num_sroots+1)]
        names += ['f{}'.format(i) for i in range(1, num_sroots+1)]
        names += ['h{}'.format(i) for i in range(1, num_sroots+1)]
        category = LieAlgebras(R).FiniteDimensional().WithBasis()
        index_set = p_roots + list(alphacheck) + n_roots
        names = tuple(names)
        from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
        index_set = FiniteEnumeratedSet(index_set)
        LieAlgebraWithStructureCoefficients.__init__(self, R, s_coeffs, names, index_set,
                                                     category, prefix='E', bracket='[',
                                                     sorting_key=self._basis_key)
Beispiel #17
0
def three_dimensional_by_rank(R, n, a=None, names=['X', 'Y', 'Z']):
    """
    Return a 3-dimensional Lie algebra of rank ``n``, where `0 \leq n \leq 3`.

    Here, the *rank* of a Lie algebra `L` is defined as the dimension
    of its derived subalgebra `[L, L]`. (We are assuming that `R` is
    a field of characteristic `0`; otherwise the Lie algebras
    constructed by this function are still well-defined but no longer
    might have the correct ranks.) This is not to be confused with
    the other standard definition of a rank (namely, as the
    dimension of a Cartan subalgebra, when `L` is semisimple).

    INPUT:

    - ``R`` -- the base ring
    - ``n`` -- the rank
    - ``a`` -- the deformation parameter (used for `n = 2`); this should
      be a nonzero element of `R` in order for the resulting Lie
      algebra to actually have the right rank(?)
    - ``names`` -- (optional) the generator names

    EXAMPLES::

        sage: lie_algebras.three_dimensional_by_rank(QQ, 0)
        Abelian Lie algebra on 3 generators (X, Y, Z) over Rational Field
        sage: L = lie_algebras.three_dimensional_by_rank(QQ, 1)
        sage: L.structure_coefficients()
        Finite family {('Y', 'Z'): X}
        sage: L = lie_algebras.three_dimensional_by_rank(QQ, 2, 4)
        sage: L.structure_coefficients()
        Finite family {('X', 'Y'): Y, ('X', 'Z'): Y + Z}
        sage: L = lie_algebras.three_dimensional_by_rank(QQ, 2, 0)
        sage: L.structure_coefficients()
        Finite family {('X', 'Y'): Y}
        sage: lie_algebras.three_dimensional_by_rank(QQ, 3)
        sl2 over Rational Field
    """
    if isinstance(names, str):
        names = names.split(',')
    names = tuple(names)

    if n == 0:
        from sage.algebras.lie_algebras.abelian import AbelianLieAlgebra
        return AbelianLieAlgebra(R, names=names)

    if n == 1:
        L = three_dimensional(R, 0, 1, 0, 0, names=names) # Strictly upper triangular matrices
        L.rename("Lie algebra of 3x3 strictly upper triangular matrices over {}".format(R))
        return L

    if n == 2:
        if a is None:
            raise ValueError("The parameter 'a' must be specified")
        X = names[0]
        Y = names[1]
        Z = names[2]
        from sage.algebras.lie_algebras.structure_coefficients import LieAlgebraWithStructureCoefficients
        if a == 0:
            s_coeff = {(X,Y): {Y:R.one()}, (X,Z): {Y:R(a)}}
            # Why use R(a) here if R == 0 ? Also this has rank 1.
            L = LieAlgebraWithStructureCoefficients(R, s_coeff, tuple(names))
            L.rename("Degenerate Lie algebra of dimension 3 and rank 2 over {}".format(R))
        else:
            s_coeff = {(X,Y): {Y:R.one()}, (X,Z): {Y:R.one(), Z:R.one()}}
            # a doesn't appear here :/
            L = LieAlgebraWithStructureCoefficients(R, s_coeff, tuple(names))
            L.rename("Lie algebra of dimension 3 and rank 2 with parameter {} over {}".format(a, R))
        return L

    if n == 3:
        #return sl(R, 2)
        from sage.algebras.lie_algebras.structure_coefficients import LieAlgebraWithStructureCoefficients
        E = names[0]
        F = names[1]
        H = names[2]
        s_coeff = { (E,F): {H:R.one()}, (H,E): {E:R(2)}, (H,F): {F:R(-2)} }
        L = LieAlgebraWithStructureCoefficients(R, s_coeff, tuple(names))
        L.rename("sl2 over {}".format(R))
        return L

    raise ValueError("Invalid rank")
Beispiel #18
0
    def __init__(self, R, r, s, names, naming, category, **kwds):
        r"""
        Initialize ``self``

        EXAMPLES::

            sage: L = LieAlgebra(ZZ, 2, step=2)
            sage: TestSuite(L).run()

            sage: L = LieAlgebra(QQ, 4, step=3)
            sage: TestSuite(L).run()  # long time
        """
        if r not in ZZ or r <= 0:
            raise ValueError("number of generators %s is not "
                             "a positive integer" % r)
        if s not in ZZ or s <= 0:
            raise ValueError("step %s is not a positive integer" % s)

        # extract an index set from the Lyndon words of the corresponding
        # free Lie algebra, and store the corresponding elements in a dict
        from sage.algebras.lie_algebras.lie_algebra import LieAlgebra

        free_gen_names = ['F%d' % k for k in range(r)]
        free_gen_names_inv = {val: i + 1 for i, val in enumerate(free_gen_names)}
        L = LieAlgebra(R, free_gen_names).Lyndon()

        basis_by_deg = {d: [] for d in range(1, s + 1)}
        for d in range(1, s + 1):
            for X in L.graded_basis(d):
                # convert brackets of form [X_1, [X_1, X_2]] to words (1,1,2)
                w = tuple(free_gen_names_inv[s]
                          for s in X.leading_support().to_word())
                basis_by_deg[d].append((w, X))

        index_set = [ind for d in basis_by_deg for ind, val in basis_by_deg[d]]

        if len(names) == 1 and len(index_set) > 1:
            if not naming:
                if r >= 10:
                    naming = 'linear'
                else:
                    naming = 'index'
            if naming == 'linear':
                names = ['%s_%d' % (names[0], k + 1)
                         for k in range(len(index_set))]
            elif naming == 'index':
                if r >= 10:
                    raise ValueError("'index' naming scheme not supported for "
                                     "10 or more generators")
                names = ['%s_%s' % (names[0], "".join(str(s) for s in w))
                         for w in index_set]
            else:
                raise ValueError("unknown naming scheme %s" % naming)

        # extract structural coefficients from the free Lie algebra
        s_coeff = {}
        for dx in range(1, s + 1):
            # Brackets are only computed when deg(X) + deg(Y) <= s
            # We also require deg(Y) >= deg(X) by the ordering
            for dy in range(dx, s + 1 - dx):
                if dx == dy:
                    for i, val in enumerate(basis_by_deg[dx]):
                        X_ind, X = val
                        for Y_ind, Y in basis_by_deg[dy][i + 1:]:
                            Z = L[X, Y]
                            if not Z.is_zero():
                                s_coeff[(X_ind, Y_ind)] = {W_ind: Z[W.leading_support()]
                                                           for W_ind, W in basis_by_deg[dx + dy]}
                else:
                    for X_ind, X in basis_by_deg[dx]:
                        for Y_ind, Y in basis_by_deg[dy]:
                            Z = L[X, Y]
                            if not Z.is_zero():
                                s_coeff[(X_ind, Y_ind)] = {W_ind: Z[W.leading_support()]
                                                           for W_ind, W in basis_by_deg[dx + dy]}

        names, index_set = standardize_names_index_set(names, index_set)
        s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff(
            s_coeff, index_set)

        NilpotentLieAlgebra_dense.__init__(self, R, s_coeff, names,
                                           index_set, s,
                                           category=category, **kwds)
Beispiel #19
0
def three_dimensional_by_rank(R, n, a=None, names=['X', 'Y', 'Z']):
    r"""
    Return a 3-dimensional Lie algebra of rank ``n``, where `0 \leq n \leq 3`.

    Here, the *rank* of a Lie algebra `L` is defined as the dimension
    of its derived subalgebra `[L, L]`. (We are assuming that `R` is
    a field of characteristic `0`; otherwise the Lie algebras
    constructed by this function are still well-defined but no longer
    might have the correct ranks.) This is not to be confused with
    the other standard definition of a rank (namely, as the
    dimension of a Cartan subalgebra, when `L` is semisimple).

    INPUT:

    - ``R`` -- the base ring
    - ``n`` -- the rank
    - ``a`` -- the deformation parameter (used for `n = 2`); this should
      be a nonzero element of `R` in order for the resulting Lie
      algebra to actually have the right rank(?)
    - ``names`` -- (optional) the generator names

    EXAMPLES::

        sage: lie_algebras.three_dimensional_by_rank(QQ, 0)
        Abelian Lie algebra on 3 generators (X, Y, Z) over Rational Field
        sage: L = lie_algebras.three_dimensional_by_rank(QQ, 1)
        sage: L.structure_coefficients()
        Finite family {('Y', 'Z'): X}
        sage: L = lie_algebras.three_dimensional_by_rank(QQ, 2, 4)
        sage: L.structure_coefficients()
        Finite family {('X', 'Y'): Y, ('X', 'Z'): Y + Z}
        sage: L = lie_algebras.three_dimensional_by_rank(QQ, 2, 0)
        sage: L.structure_coefficients()
        Finite family {('X', 'Y'): Y}
        sage: lie_algebras.three_dimensional_by_rank(QQ, 3)
        sl2 over Rational Field
    """
    if isinstance(names, str):
        names = names.split(',')
    names = tuple(names)

    if n == 0:
        from sage.algebras.lie_algebras.abelian import AbelianLieAlgebra
        return AbelianLieAlgebra(R, names=names)

    if n == 1:
        L = three_dimensional(R, 0, 1, 0, 0, names=names) # Strictly upper triangular matrices
        L.rename("Lie algebra of 3x3 strictly upper triangular matrices over {}".format(R))
        return L

    if n == 2:
        if a is None:
            raise ValueError("The parameter 'a' must be specified")
        X = names[0]
        Y = names[1]
        Z = names[2]
        from sage.algebras.lie_algebras.structure_coefficients import LieAlgebraWithStructureCoefficients
        if a == 0:
            s_coeff = {(X,Y): {Y:R.one()}, (X,Z): {Y:R(a)}}
            # Why use R(a) here if R == 0 ? Also this has rank 1.
            L = LieAlgebraWithStructureCoefficients(R, s_coeff, tuple(names))
            L.rename("Degenerate Lie algebra of dimension 3 and rank 2 over {}".format(R))
        else:
            s_coeff = {(X,Y): {Y:R.one()}, (X,Z): {Y:R.one(), Z:R.one()}}
            # a doesn't appear here :/
            L = LieAlgebraWithStructureCoefficients(R, s_coeff, tuple(names))
            L.rename("Lie algebra of dimension 3 and rank 2 with parameter {} over {}".format(a, R))
        return L

    if n == 3:
        #return sl(R, 2)
        from sage.algebras.lie_algebras.structure_coefficients import LieAlgebraWithStructureCoefficients
        E = names[0]
        F = names[1]
        H = names[2]
        s_coeff = { (E,F): {H:R.one()}, (H,E): {E:R(2)}, (H,F): {F:R(-2)} }
        L = LieAlgebraWithStructureCoefficients(R, s_coeff, tuple(names))
        L.rename("sl2 over {}".format(R))
        return L

    raise ValueError("Invalid rank")
Beispiel #20
0
    def __classcall_private__(cls,
                              R=None,
                              arg0=None,
                              arg1=None,
                              names=None,
                              index_set=None,
                              abelian=False,
                              **kwds):
        """
        Select the correct parent based upon input.

        TESTS::

            sage: LieAlgebra(QQ, abelian=True, names='x,y,z')
            Abelian Lie algebra on 3 generators (x, y, z) over Rational Field
            sage: LieAlgebra(QQ, {('e','h'): {'e':-2}, ('f','h'): {'f':2},
            ....:                 ('e','f'): {'h':1}}, names='e,f,h')
            Lie algebra on 3 generators (e, f, h) over Rational Field
        """
        # Parse associative algebra input
        # -----

        assoc = kwds.get("associative", None)
        if assoc is not None:
            return LieAlgebraFromAssociative(assoc,
                                             names=names,
                                             index_set=index_set)

        # Parse input as a Cartan type
        # -----

        ct = kwds.get("cartan_type", None)
        if ct is not None:
            from sage.combinat.root_system.cartan_type import CartanType
            ct = CartanType(ct)
            if ct.is_affine():
                from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra
                return AffineLieAlgebra(R,
                                        cartan_type=ct,
                                        kac_moody=kwds.get("kac_moody", True))
            if not ct.is_finite():
                raise NotImplementedError(
                    "non-finite types are not implemented yet, see trac #14901 for details"
                )
            rep = kwds.get("representation", "bracket")
            if rep == 'bracket':
                from sage.algebras.lie_algebras.classical_lie_algebra import LieAlgebraChevalleyBasis
                return LieAlgebraChevalleyBasis(R, ct)
            if rep == 'matrix':
                from sage.algebras.lie_algebras.classical_lie_algebra import ClassicalMatrixLieAlgebra
                return ClassicalMatrixLieAlgebra(R, ct)
            raise ValueError("invalid representation")

        # Parse the remaining arguments
        # -----

        if R is None:
            raise ValueError("invalid arguments")

        check_assoc = lambda A: (isinstance(A, (Ring, MatrixSpace)) or A in
                                 Rings() or A in Algebras(R).Associative())
        if arg0 in ZZ or check_assoc(arg1):
            # Check if we need to swap the arguments
            arg0, arg1 = arg1, arg0

        # Parse the first argument
        # -----

        if isinstance(arg0, dict):
            if not arg0:
                from sage.algebras.lie_algebras.abelian import AbelianLieAlgebra
                return AbelianLieAlgebra(R, names, index_set)
            elif isinstance(next(iter(arg0.keys())), (list, tuple)):
                # We assume it is some structure coefficients
                arg1, arg0 = arg0, arg1

        if isinstance(arg0, (list, tuple)):
            if all(isinstance(x, str) for x in arg0):
                # If they are all strings, then it is a list of variables
                names = tuple(arg0)

        if isinstance(arg0, str):
            names = tuple(arg0.split(','))
        elif isinstance(names, str):
            names = tuple(names.split(','))

        # Parse the second argument

        if isinstance(arg1, dict):
            # Assume it is some structure coefficients
            from sage.algebras.lie_algebras.structure_coefficients import LieAlgebraWithStructureCoefficients
            return LieAlgebraWithStructureCoefficients(R, arg1, names,
                                                       index_set, **kwds)

        # Otherwise it must be either a free or abelian Lie algebra

        if arg1 in ZZ:
            if isinstance(arg0, str):
                names = arg0
            if names is None:
                index_set = list(range(arg1))
            else:
                if isinstance(names, str):
                    names = tuple(names.split(','))
                    if arg1 != 1 and len(names) == 1:
                        names = tuple('{}{}'.format(names[0], i)
                                      for i in range(arg1))
                if arg1 != len(names):
                    raise ValueError("the number of names must equal the"
                                     " number of generators")

        if abelian:
            from sage.algebras.lie_algebras.abelian import AbelianLieAlgebra
            return AbelianLieAlgebra(R, names, index_set)

        # Otherwise it is the free Lie algebra
        rep = kwds.get("representation", "bracket")
        if rep == "polynomial":
            # Construct the free Lie algebra from polynomials in the
            #   free (associative unital) algebra
            # TODO: Change this to accept an index set once FreeAlgebra accepts one
            from sage.algebras.free_algebra import FreeAlgebra
            F = FreeAlgebra(R, names)
            if index_set is None:
                index_set = F.variable_names()
            # TODO: As part of #16823, this should instead construct a
            #   subclass with specialized methods for the free Lie algebra
            return LieAlgebraFromAssociative(F,
                                             F.gens(),
                                             names=names,
                                             index_set=index_set)

        raise NotImplementedError("the free Lie algebra has only been"
                                  " implemented using polynomials in the"
                                  " free algebra, see trac ticket #16823")