def __init__(self, W_types, index_set=None, hyperplane_index_set=None, reflection_index_set=None): r""" Initialize ``self``. TESTS:: sage: W = ReflectionGroup(['A',3]) # optional - gap3 sage: TestSuite(W).run() # optional - gap3 """ W_types = tuple([tuple(W_type) if isinstance(W_type, (list, tuple)) else W_type for W_type in W_types]) cartan_types = [] for W_type in W_types: W_type = CartanType(W_type) if not W_type.is_finite() or not W_type.is_irreducible(): raise ValueError("the given Cartan type of a component is not irreducible and finite") cartan_types.append(W_type) if len(W_types) == 1: cls = IrreducibleComplexReflectionGroup else: cls = ComplexReflectionGroup cls.__init__( self, W_types, index_set=index_set, hyperplane_index_set=hyperplane_index_set, reflection_index_set=reflection_index_set, )
def _element_constructor_(self, cartan_type, **kwds): """ The element constructor. This method is called internally when we try to convert something into an element. In this case, the only thing that can be converted into an associahedron is the Cartan type. EXAMPLES:: sage: from sage.combinat.root_system.associahedron import Associahedra sage: parent = Associahedra(QQ,2) sage: parent(['A',2]) Generalized associahedron of type ['A', 2] with 5 vertices sage: parent._element_constructor_(['A',2]) Generalized associahedron of type ['A', 2] with 5 vertices """ cartan_type = CartanType(cartan_type) assert cartan_type.is_finite() root_space = cartan_type.root_system().root_space() # TODO: generalize this as a method of root lattice realization rhocheck = sum(beta.associated_coroot() for beta in root_space.positive_roots()) / 2 I = root_space.index_set() inequalities = [] for orbit in root_space.almost_positive_roots_decomposition(): c = rhocheck.coefficient(orbit[0].leading_support()) for beta in orbit: inequalities.append([c] + [beta.coefficient(i) for i in I]) associahedron = super(Associahedra, self)._element_constructor_( None, [inequalities, []]) associahedron._cartan_type = cartan_type return associahedron
def __init__(self, W_types, index_set=None, hyperplane_index_set=None, reflection_index_set=None): r""" Initialize ``self``. TESTS:: sage: W = ReflectionGroup(['A',3]) # optional - gap3 sage: TestSuite(W).run() # optional - gap3 """ W_types = tuple([ tuple(W_type) if isinstance(W_type, (list, tuple)) else W_type for W_type in W_types ]) cartan_types = [] for W_type in W_types: W_type = CartanType(W_type) if not W_type.is_finite() or not W_type.is_irreducible(): raise ValueError( "the given Cartan type of a component is not irreducible and finite" ) cartan_types.append(W_type) if len(W_types) == 1: cls = IrreducibleComplexReflectionGroup else: cls = ComplexReflectionGroup cls.__init__(self, W_types, index_set=index_set, hyperplane_index_set=hyperplane_index_set, reflection_index_set=reflection_index_set)
def _element_constructor_(self, cartan_type, **kwds): """ The element constructor. This method is called internally when we try to convert something into an element. In this case, the only thing that can be converted into an associahedron is the Cartan type. EXAMPLES:: sage: from sage.combinat.root_system.associahedron import Associahedra sage: parent = Associahedra(QQ,2) sage: parent(['A',2]) Generalized associahedron of type ['A', 2] with 5 vertices sage: parent._element_constructor_(['A',2]) Generalized associahedron of type ['A', 2] with 5 vertices """ cartan_type = CartanType(cartan_type) if not cartan_type.is_finite(): raise ValueError("the Cartan type must be finite") root_space = cartan_type.root_system().root_space() # TODO: generalize this as a method of root lattice realization rhocheck = sum(beta.associated_coroot() for beta in root_space.positive_roots()) / 2 I = root_space.index_set() inequalities = [] for orbit in root_space.almost_positive_roots_decomposition(): c = rhocheck.coefficient(orbit[0].leading_support()) for beta in orbit: inequalities.append([c] + [beta.coefficient(i) for i in I]) associahedron = super(Associahedra, self)._element_constructor_(None, [inequalities, []]) associahedron._cartan_type = cartan_type return associahedron
def __classcall_private__(cls, ct, c=1, t=None, base_ring=None, prefix=('a', 's', 'ac')): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: R1 = algebras.RationalCherednik(['B',2], 1, 1, QQ) sage: R2 = algebras.RationalCherednik(CartanType(['B',2]), [1,1], 1, QQ, ('a', 's', 'ac')) sage: R1 is R2 True """ ct = CartanType(ct) if not ct.is_finite(): raise ValueError("the Cartan type must be finite") if base_ring is None: if t is None: base_ring = QQ else: base_ring = t.parent() if t is None: t = base_ring.one() else: t = base_ring(t) # Normalize the parameter c if isinstance(c, (tuple, list)): if ct.is_simply_laced(): if len(c) != 1: raise ValueError( "1 parameter c_s must be given for simply-laced types") c = (base_ring(c[0]), ) else: if len(c) != 2: raise ValueError( "2 parameters c_s must be given for non-simply-laced types" ) c = (base_ring(c[0]), base_ring(c[1])) else: c = base_ring(c) if ct.is_simply_laced(): c = (c, ) else: c = (c, c) return super(RationalCherednikAlgebra, cls).__classcall__(cls, ct, c, t, base_ring, tuple(prefix))
def __init__(self, R, ct, names=None, prefix=None, bracket=None): """ Initialize self. TESTS:: sage: V = lie_conformal_algebras.Affine(QQ,'A1') sage: TestSuite(V).run() """ if type(ct) is str: from sage.combinat.root_system.cartan_type import CartanType try: ct = CartanType(ct) except IndexError: raise ValueError("ct must be a valid Cartan Type") if not (ct.is_finite() and ct.is_irreducible): raise ValueError( "only affine algebras of simple finite dimensional" "Lie algebras are implemented") hv = Integer(ct.dual_coxeter_number()) g = LieAlgebra(R, cartan_type=ct) B = g.basis() S = B.keys() gdict = {} for k1 in S: for k2 in S: if S.rank(k2) <= S.rank(k1): myb = B[k1].bracket(B[k2]).monomial_coefficients() myf = R(2).inverse_of_unit()*R(hv).inverse_of_unit()\ *g.killing_form(B[k1],B[k2]) if myb or myf: gdict[(k1, k2)] = {} if myb: gdict[(k1,k2)][0] = {(nk,0):v for nk,v in \ myb.items()} if myf: gdict[(k1, k2)][1] = {('K', 0): myf} weights = (1, ) * B.cardinality() self._ct = ct if prefix is None and names is None: prefix = 'B' GradedLieConformalAlgebra.__init__(self, R, gdict, index_set=S, central_elements=('K', ), weights=weights, names=names, prefix=prefix, bracket=bracket)
def __classcall__(cls, cartan_type): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: B1 = crystals.infinity.PBW(['A', 2]) sage: B2 = crystals.infinity.PBW("A2") sage: B3 = crystals.infinity.PBW(CartanType("A2")) sage: B1 is B2 and B2 is B3 True """ cartan_type = CartanType(cartan_type) if not cartan_type.is_finite(): raise NotImplementedError("only implemented for finite types") return super(PBWCrystal, cls).__classcall__(cls, cartan_type)
def __classcall__(cls, cartan_type): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: B1 = crystals.infinity.PBW(['A', 2]) sage: B2 = crystals.infinity.PBW("A2") sage: B3 = crystals.infinity.PBW(CartanType("A2")) sage: B1 is B2 and B2 is B3 True """ cartan_type = CartanType(cartan_type) if not cartan_type.is_finite(): raise NotImplementedError("only implemented for finite types") return super(PBWCrystal, cls).__classcall__(cls, cartan_type)
def __classcall_private__(cls, ct, c=1, t=None, base_ring=None, prefix=('a', 's', 'ac')): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: R1 = algebras.RationalCherednik(['B',2], 1, 1, QQ) sage: R2 = algebras.RationalCherednik(CartanType(['B',2]), [1,1], 1, QQ, ('a', 's', 'ac')) sage: R1 is R2 True """ ct = CartanType(ct) if not ct.is_finite(): raise ValueError("the Cartan type must be finite") if base_ring is None: if t is None: base_ring = QQ else: base_ring = t.parent() if t is None: t = base_ring.one() else: t = base_ring(t) # Normalize the parameter c if isinstance(c, (tuple, list)): if ct.is_simply_laced(): if len(c) != 1: raise ValueError("1 parameter c_s must be given for simply-laced types") c = (base_ring(c[0]),) else: if len(c) != 2: raise ValueError("2 parameters c_s must be given for non-simply-laced types") c = (base_ring(c[0]), base_ring(c[1])) else: c = base_ring(c) if ct.is_simply_laced(): c = (c,) else: c = (c, c) return super(RationalCherednikAlgebra, cls).__classcall__(cls, ct, c, t, base_ring, tuple(prefix))
def __classcall_private__(cls, R, cartan_type): """ Return the correct parent based on input. EXAMPLES:: sage: lie_algebras.ClassicalMatrix(QQ, ['A', 4]) Special linear Lie algebra of rank 5 over Rational Field sage: lie_algebras.ClassicalMatrix(QQ, CartanType(['B',4])) Special orthogonal Lie algebra of rank 9 over Rational Field sage: lie_algebras.ClassicalMatrix(QQ, 'C4') Symplectic Lie algebra of rank 8 over Rational Field sage: lie_algebras.ClassicalMatrix(QQ, cartan_type=['D',4]) Special orthogonal Lie algebra of rank 8 over Rational Field """ if isinstance(cartan_type, (CartanMatrix, DynkinDiagram_class)): cartan_type = cartan_type.cartan_type() else: cartan_type = CartanType(cartan_type) if not cartan_type.is_finite(): raise ValueError("only for finite types") if cartan_type.type() == 'A': return sl(R, cartan_type.rank() + 1) if cartan_type.type() == 'B': return so(R, 2*cartan_type.rank() + 1) if cartan_type.type() == 'C': return sp(R, 2*cartan_type.rank()) if cartan_type.type() == 'D': return so(R, 2*cartan_type.rank()) if cartan_type.type() == 'E': if cartan_type.rank() == 6: return e6(R) if cartan_type.rank() in [7,8]: raise NotImplementedError("not yet implemented") if cartan_type.type() == 'F' and cartan_type.rank() == 4: return f4(R) if cartan_type.type() == 'G' and cartan_type.rank() == 2: return g2(R) raise ValueError("invalid Cartan type")
def WeylGroup(x, prefix=None, implementation='matrix'): """ Returns the Weyl group of the root system defined by the Cartan type (or matrix) ``ct``. INPUT: - ``x`` - a root system or a Cartan type (or matrix) OPTIONAL: - ``prefix`` -- changes the representation of elements from matrices to products of simple reflections - ``implementation`` -- one of the following: * ``'matrix'`` - as matrices acting on a root system * ``"permutation"`` - as a permutation group acting on the roots EXAMPLES: The following constructions yield the same result, namely a weight lattice and its corresponding Weyl group:: sage: G = WeylGroup(['F',4]) sage: L = G.domain() or alternatively and equivalently:: sage: L = RootSystem(['F',4]).ambient_space() sage: G = L.weyl_group() sage: W = WeylGroup(L) Either produces a weight lattice, with access to its roots and weights. :: sage: G = WeylGroup(['F',4]) sage: G.order() 1152 sage: [s1,s2,s3,s4] = G.simple_reflections() sage: w = s1*s2*s3*s4; w [ 1/2 1/2 1/2 1/2] [-1/2 1/2 1/2 -1/2] [ 1/2 1/2 -1/2 -1/2] [ 1/2 -1/2 1/2 -1/2] sage: type(w) == G.element_class True sage: w.order() 12 sage: w.length() # length function on Weyl group 4 The default representation of Weyl group elements is as matrices. If you prefer, you may specify a prefix, in which case the elements are represented as products of simple reflections. :: sage: W=WeylGroup("C3",prefix="s") sage: [s1,s2,s3]=W.simple_reflections() # lets Sage parse its own output sage: s2*s1*s2*s3 s1*s2*s3*s1 sage: s2*s1*s2*s3 == s1*s2*s3*s1 True sage: (s2*s3)^2==(s3*s2)^2 True sage: (s1*s2*s3*s1).matrix() [ 0 0 -1] [ 0 1 0] [ 1 0 0] :: sage: L = G.domain() sage: fw = L.fundamental_weights(); fw Finite family {1: (1, 1, 0, 0), 2: (2, 1, 1, 0), 3: (3/2, 1/2, 1/2, 1/2), 4: (1, 0, 0, 0)} sage: rho = sum(fw); rho (11/2, 5/2, 3/2, 1/2) sage: w.action(rho) # action of G on weight lattice (5, -1, 3, 2) We can also do the same for arbitrary Cartan matrices:: sage: cm = CartanMatrix([[2,-5,0],[-2,2,-1],[0,-1,2]]) sage: W = WeylGroup(cm) sage: W.gens() ( [-1 5 0] [ 1 0 0] [ 1 0 0] [ 0 1 0] [ 2 -1 1] [ 0 1 0] [ 0 0 1], [ 0 0 1], [ 0 1 -1] ) sage: s0,s1,s2 = W.gens() sage: s1*s2*s1 [ 1 0 0] [ 2 0 -1] [ 2 -1 0] sage: s2*s1*s2 [ 1 0 0] [ 2 0 -1] [ 2 -1 0] sage: s0*s1*s0*s2*s0 [ 9 0 -5] [ 2 0 -1] [ 0 1 -1] Same Cartan matrix, but with a prefix to display using simple reflections:: sage: W = WeylGroup(cm, prefix='s') sage: s0,s1,s2 = W.gens() sage: s0*s2*s1 s2*s0*s1 sage: (s1*s2)^3 1 sage: (s0*s1)^5 s0*s1*s0*s1*s0*s1*s0*s1*s0*s1 sage: s0*s1*s2*s1*s2 s2*s0*s1 sage: s0*s1*s2*s0*s2 s0*s1*s0 TESTS:: sage: TestSuite(WeylGroup(["A",3])).run() sage: TestSuite(WeylGroup(["A",3,1])).run() # long time sage: W = WeylGroup(['A',3,1]) sage: s = W.simple_reflections() sage: w = s[0]*s[1]*s[2] sage: w.reduced_word() [0, 1, 2] sage: w = s[0]*s[2] sage: w.reduced_word() [2, 0] sage: W = groups.misc.WeylGroup(['A',3,1]) """ if implementation == "permutation": return WeylGroup_permutation(x, prefix) elif implementation != "matrix": raise ValueError("invalid implementation") if x in RootLatticeRealizations: return WeylGroup_gens(x, prefix=prefix) try: ct = CartanType(x) except TypeError: ct = CartanMatrix(x) # See if it is a Cartan matrix if ct.is_finite(): return WeylGroup_gens(ct.root_system().ambient_space(), prefix=prefix) return WeylGroup_gens(ct.root_system().root_space(), prefix=prefix)
def FundamentalGroupOfExtendedAffineWeylGroup(cartan_type, prefix='pi', general_linear=None): r""" Factory for the fundamental group of an extended affine Weyl group. INPUT: - ``cartan_type`` -- a Cartan type that is either affine or finite, with the latter being a shorthand for the untwisted affinization - ``prefix`` (default: 'pi') -- string that labels the elements of the group - ``general_linear`` -- (default: None, meaning False) In untwisted type A, if True, use the universal central extension .. RUBRIC:: Fundamental group Associated to each affine Cartan type `\tilde{X}` is an extended affine Weyl group `E`. Its subgroup of length-zero elements is called the fundamental group `F`. The group `F` can be identified with a subgroup of the group of automorphisms of the affine Dynkin diagram. As such, every element of `F` can be viewed as a permutation of the set `I` of affine Dynkin nodes. Let `0 \in I` be the distinguished affine node; it is the one whose removal produces the associated finite Cartan type (call it `X`). A node `i \in I` is called *special* if some automorphism of the affine Dynkin diagram, sends `0` to `i`. The node `0` is always special due to the identity automorphism. There is a bijection of the set of special nodes with the fundamental group. We denote the image of `i` by `\pi_i`. The structure of `F` is determined as follows. - `\tilde{X}` is untwisted -- `F` is isomorphic to `P^\vee/Q^\vee` where `P^\vee` and `Q^\vee` are the coweight and coroot lattices of type `X`. The group `P^\vee/Q^\vee` consists of the cosets `\omega_i^\vee + Q^\vee` for special nodes `i`, where `\omega_0^\vee = 0` by convention. In this case the special nodes `i` are the *cominuscule* nodes, the ones such that `\omega_i^\vee(\alpha_j)` is `0` or `1` for all `j\in I_0 = I \setminus \{0\}`. For `i` special, addition by `\omega_i^\vee+Q^\vee` permutes `P^\vee/Q^\vee` and therefore permutes the set of special nodes. This permutation extends uniquely to an automorphism of the affine Dynkin diagram. - `\tilde{X}` is dual untwisted -- (that is, the dual of `\tilde{X}` is untwisted) `F` is isomorphic to `P/Q` where `P` and `Q` are the weight and root lattices of type `X`. The group `P/Q` consists of the cosets `\omega_i + Q` for special nodes `i`, where `\omega_0 = 0` by convention. In this case the special nodes `i` are the *minuscule* nodes, the ones such that `\alpha_j^\vee(\omega_i)` is `0` or `1` for all `j \in I_0`. For `i` special, addition by `\omega_i+Q` permutes `P/Q` and therefore permutes the set of special nodes. This permutation extends uniquely to an automorphism of the affine Dynkin diagram. - `\tilde{X}` is mixed -- (that is, not of the above two types) `F` is the trivial group. EXAMPLES:: sage: from sage.combinat.root_system.fundamental_group import FundamentalGroupOfExtendedAffineWeylGroup sage: F = FundamentalGroupOfExtendedAffineWeylGroup(['A',3,1]); F Fundamental group of type ['A', 3, 1] sage: F.cartan_type().dynkin_diagram() 0 O-------+ | | | | O---O---O 1 2 3 A3~ sage: F.special_nodes() (0, 1, 2, 3) sage: F(1)^2 pi[2] sage: F(1)*F(2) pi[3] sage: F(3)^(-1) pi[1] sage: F = FundamentalGroupOfExtendedAffineWeylGroup("B3"); F Fundamental group of type ['B', 3, 1] sage: F.cartan_type().dynkin_diagram() O 0 | | O---O=>=O 1 2 3 B3~ sage: F.special_nodes() (0, 1) sage: F = FundamentalGroupOfExtendedAffineWeylGroup("C2"); F Fundamental group of type ['C', 2, 1] sage: F.cartan_type().dynkin_diagram() O=>=O=<=O 0 1 2 C2~ sage: F.special_nodes() (0, 2) sage: F = FundamentalGroupOfExtendedAffineWeylGroup("D4"); F Fundamental group of type ['D', 4, 1] sage: F.cartan_type().dynkin_diagram() O 4 | | O---O---O 1 |2 3 | O 0 D4~ sage: F.special_nodes() (0, 1, 3, 4) sage: (F(4), F(4)^2) (pi[4], pi[0]) sage: F = FundamentalGroupOfExtendedAffineWeylGroup("D5"); F Fundamental group of type ['D', 5, 1] sage: F.cartan_type().dynkin_diagram() 0 O O 5 | | | | O---O---O---O 1 2 3 4 D5~ sage: F.special_nodes() (0, 1, 4, 5) sage: (F(5), F(5)^2, F(5)^3, F(5)^4) (pi[5], pi[1], pi[4], pi[0]) sage: F = FundamentalGroupOfExtendedAffineWeylGroup("E6"); F Fundamental group of type ['E', 6, 1] sage: F.cartan_type().dynkin_diagram() O 0 | | O 2 | | O---O---O---O---O 1 3 4 5 6 E6~ sage: F.special_nodes() (0, 1, 6) sage: F(1)^2 pi[6] sage: F = FundamentalGroupOfExtendedAffineWeylGroup(['D',4,2]); F Fundamental group of type ['C', 3, 1]^* sage: F.cartan_type().dynkin_diagram() O=<=O---O=>=O 0 1 2 3 C3~* sage: F.special_nodes() (0, 3) We also implement a fundamental group for `GL_n`. It is defined to be the group of integers, which is the covering group of the fundamental group Z/nZ for affine `SL_n`:: sage: F = FundamentalGroupOfExtendedAffineWeylGroup(['A',2,1], general_linear=True); F Fundamental group of GL(3) sage: x = F.an_element(); x pi[5] sage: x*x pi[10] sage: x.inverse() pi[-5] sage: wt = F.cartan_type().classical().root_system().ambient_space().an_element(); wt (2, 2, 3) sage: x.act_on_classical_ambient(wt) (2, 3, 2) sage: w = WeylGroup(F.cartan_type(),prefix="s").an_element(); w s0*s1*s2 sage: x.act_on_affine_weyl(w) s2*s0*s1 """ cartan_type = CartanType(cartan_type) if cartan_type.is_finite(): cartan_type = cartan_type.affine() if not cartan_type.is_affine(): raise NotImplementedError("Cartan type is not affine") if general_linear is True: if cartan_type.is_untwisted_affine() and cartan_type.type() == "A": return FundamentalGroupGL(cartan_type, prefix) else: raise ValueError( "General Linear Fundamental group is untwisted type A") return FundamentalGroupOfExtendedAffineWeylGroup_Class(cartan_type, prefix, finite=True)
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")
class Associahedron(Polyhedron): r""" The generalized associahedron is a polytopal complex with vertices in one-to-one correspondence with clusters in the cluster complex, and with edges between two vertices if and only if the associated two clusters intersect in codimension 1. The associahedron of type `A_n` is one way to realize the classical associahedron as defined in http://en.wikipedia.org/wiki/Associahedron. A polytopal realization of the associahedron can be found in [CFZ]. The implementation is based on [CFZ, Theorem 1.5, Remark 1.6, and Corollary 1.9.]. EXAMPLES:: sage: Asso = Associahedron(['A',2]); Asso Generalized associahedron of type ['A', 2] with 5 vertices sage: sorted(Asso.Hrepresentation(), key=repr) [An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0, An inequality (1, 0) x + 1 >= 0, An inequality (1, 1) x + 1 >= 0] sage: Asso.Vrepresentation() [A vertex at (-1, 1), A vertex at (1, 1), A vertex at (1, -1), A vertex at (0, -1), A vertex at (-1, 0)] sage: Associahedron(['B',2]) Generalized associahedron of type ['B', 2] with 6 vertices The two pictures of [CFZ] can be recovered with:: sage: Asso = Associahedron(['A',3]); Asso Generalized associahedron of type ['A', 3] with 14 vertices sage: Asso.plot() sage: Asso = Associahedron(['B',3]); Asso Generalized associahedron of type ['B', 3] with 20 vertices sage: Asso.plot() TESTS:: sage: sorted(Associahedron(['A',3]).vertices()) [[-3/2, 0, -1/2], [-3/2, 0, 3/2], [-3/2, 1, -3/2], [-3/2, 2, -3/2], [-3/2, 2, 3/2], [-1/2, -1, -1/2], [-1/2, 0, -3/2], [1/2, -2, 1/2], [1/2, -2, 3/2], [3/2, -2, 1/2], [3/2, -2, 3/2], [3/2, 0, -3/2], [3/2, 2, -3/2], [3/2, 2, 3/2]] sage: sorted(Associahedron(['B',3]).vertices()) [[-3, 0, 0], [-3, 0, 3], [-3, 2, -2], [-3, 4, -3], [-3, 5, -3], [-3, 5, 3], [-2, 1, -2], [-2, 3, -3], [-1, -2, 0], [-1, -1, -1], [1, -4, 1], [1, -3, 0], [2, -5, 2], [2, -5, 3], [3, -5, 2], [3, -5, 3], [3, -3, 0], [3, 3, -3], [3, 5, -3], [3, 5, 3]] sage: Associahedron(['A',4]).f_vector() (1, 42, 84, 56, 14, 1) sage: Associahedron(['B',4]).f_vector() (1, 70, 140, 90, 20, 1) REFERENCES: - [CFZ] Chapoton, Fomin, Zelevinsky - Polytopal realizations of generalized associahedra, arXiv:0202004. """ def __init__(self, cartan_type): """ TESTS:: sage: Asso = Associahedron(['A',2]); Asso Generalized associahedron of type ['A', 2] with 5 vertices sage: TestSuite(Asso).run() """ self._cartan_type = CartanType( cartan_type ) assert self._cartan_type.is_finite() root_space = self._cartan_type.root_system().root_space() # TODO: generalize this as a method of root lattice realization rhocheck = sum( beta.associated_coroot() for beta in root_space.positive_roots() )/2 I = root_space.index_set() inequalities = [] for orbit in root_space.almost_positive_roots_decomposition(): c = rhocheck.coefficient(orbit[0].leading_support()) for beta in orbit: inequalities.append( [c] + [ beta.coefficient(i) for i in I ] ) Polyhedron.__init__(self,ieqs=inequalities) # check that there are non non trivial facets assert self.n_facets() == len(inequalities) def _repr_(self): r""" Returns a string representation of self. EXAMPLES:: sage: Associahedron(['A',3])._repr_() "Generalized associahedron of type ['A', 3] with 14 vertices" """ return 'Generalized associahedron of type %s with %s vertices'%(self._cartan_type,self.n_vertices()) def cartan_type(self): r""" Returns the Cartan type of self. EXAMPLES:: sage: Associahedron(['A',3]).cartan_type() ['A', 3] """ return self._cartan_type def vertices_in_root_space(self): r""" Returns the vertices of ``self`` as elements in the root space EXAMPLES:: sage: Asso = Associahedron(['A',2]) sage: Asso.vertices() [[-1, 1], [1, 1], [1, -1], [0, -1], [-1, 0]] sage: Asso.vertices_in_root_space() [-alpha[1] + alpha[2], alpha[1] + alpha[2], alpha[1] - alpha[2], -alpha[2], -alpha[1]] """ root_space = self._cartan_type.root_system().root_space() return [ root_space.from_vector(vector(V)) for V in self.vertex_generator() ]
def FundamentalGroupOfExtendedAffineWeylGroup(cartan_type, prefix='pi', general_linear=None): r""" Factory for the fundamental group of an extended affine Weyl group. INPUT: - ``cartan_type`` -- a Cartan type that is either affine or finite, with the latter being a shorthand for the untwisted affinization - ``prefix`` (default: 'pi') -- string that labels the elements of the group - ``general_linear`` -- (default: None, meaning False) In untwisted type A, if True, use the universal central extension .. RUBRIC:: Fundamental group Associated to each affine Cartan type `\tilde{X}` is an extended affine Weyl group `E`. Its subgroup of length-zero elements is called the fundamental group `F`. The group `F` can be identified with a subgroup of the group of automorphisms of the affine Dynkin diagram. As such, every element of `F` can be viewed as a permutation of the set `I` of affine Dynkin nodes. Let `0 \in I` be the distinguished affine node; it is the one whose removal produces the associated finite Cartan type (call it `X`). A node `i \in I` is called *special* if some automorphism of the affine Dynkin diagram, sends `0` to `i`. The node `0` is always special due to the identity automorphism. There is a bijection of the set of special nodes with the fundamental group. We denote the image of `i` by `\pi_i`. The structure of `F` is determined as follows. - `\tilde{X}` is untwisted -- `F` is isomorphic to `P^\vee/Q^\vee` where `P^\vee` and `Q^\vee` are the coweight and coroot lattices of type `X`. The group `P^\vee/Q^\vee` consists of the cosets `\omega_i^\vee + Q^\vee` for special nodes `i`, where `\omega_0^\vee = 0` by convention. In this case the special nodes `i` are the *cominuscule* nodes, the ones such that `\omega_i^\vee(\alpha_j)` is `0` or `1` for all `j\in I_0 = I \setminus \{0\}`. For `i` special, addition by `\omega_i^\vee+Q^\vee` permutes `P^\vee/Q^\vee` and therefore permutes the set of special nodes. This permutation extends uniquely to an automorphism of the affine Dynkin diagram. - `\tilde{X}` is dual untwisted -- (that is, the dual of `\tilde{X}` is untwisted) `F` is isomorphic to `P/Q` where `P` and `Q` are the weight and root lattices of type `X`. The group `P/Q` consists of the cosets `\omega_i + Q` for special nodes `i`, where `\omega_0 = 0` by convention. In this case the special nodes `i` are the *minuscule* nodes, the ones such that `\alpha_j^\vee(\omega_i)` is `0` or `1` for all `j \in I_0`. For `i` special, addition by `\omega_i+Q` permutes `P/Q` and therefore permutes the set of special nodes. This permutation extends uniquely to an automorphism of the affine Dynkin diagram. - `\tilde{X}` is mixed -- (that is, not of the above two types) `F` is the trivial group. EXAMPLES:: sage: from sage.combinat.root_system.fundamental_group import FundamentalGroupOfExtendedAffineWeylGroup sage: F = FundamentalGroupOfExtendedAffineWeylGroup(['A',3,1]); F Fundamental group of type ['A', 3, 1] sage: F.cartan_type().dynkin_diagram() 0 O-------+ | | | | O---O---O 1 2 3 A3~ sage: F.special_nodes() (0, 1, 2, 3) sage: F(1)^2 pi[2] sage: F(1)*F(2) pi[3] sage: F(3)^(-1) pi[1] sage: F = FundamentalGroupOfExtendedAffineWeylGroup("B3"); F Fundamental group of type ['B', 3, 1] sage: F.cartan_type().dynkin_diagram() O 0 | | O---O=>=O 1 2 3 B3~ sage: F.special_nodes() (0, 1) sage: F = FundamentalGroupOfExtendedAffineWeylGroup("C2"); F Fundamental group of type ['C', 2, 1] sage: F.cartan_type().dynkin_diagram() O=>=O=<=O 0 1 2 C2~ sage: F.special_nodes() (0, 2) sage: F = FundamentalGroupOfExtendedAffineWeylGroup("D4"); F Fundamental group of type ['D', 4, 1] sage: F.cartan_type().dynkin_diagram() O 4 | | O---O---O 1 |2 3 | O 0 D4~ sage: F.special_nodes() (0, 1, 3, 4) sage: (F(4), F(4)^2) (pi[4], pi[0]) sage: F = FundamentalGroupOfExtendedAffineWeylGroup("D5"); F Fundamental group of type ['D', 5, 1] sage: F.cartan_type().dynkin_diagram() 0 O O 5 | | | | O---O---O---O 1 2 3 4 D5~ sage: F.special_nodes() (0, 1, 4, 5) sage: (F(5), F(5)^2, F(5)^3, F(5)^4) (pi[5], pi[1], pi[4], pi[0]) sage: F = FundamentalGroupOfExtendedAffineWeylGroup("E6"); F Fundamental group of type ['E', 6, 1] sage: F.cartan_type().dynkin_diagram() O 0 | | O 2 | | O---O---O---O---O 1 3 4 5 6 E6~ sage: F.special_nodes() (0, 1, 6) sage: F(1)^2 pi[6] sage: F = FundamentalGroupOfExtendedAffineWeylGroup(['D',4,2]); F Fundamental group of type ['C', 3, 1]^* sage: F.cartan_type().dynkin_diagram() O=<=O---O=>=O 0 1 2 3 C3~* sage: F.special_nodes() (0, 3) We also implement a fundamental group for `GL_n`. It is defined to be the group of integers, which is the covering group of the fundamental group Z/nZ for affine `SL_n`:: sage: F = FundamentalGroupOfExtendedAffineWeylGroup(['A',2,1], general_linear=True); F Fundamental group of GL(3) sage: x = F.an_element(); x pi[5] sage: x*x pi[10] sage: x.inverse() pi[-5] sage: wt = F.cartan_type().classical().root_system().ambient_space().an_element(); wt (2, 2, 3) sage: x.act_on_classical_ambient(wt) (2, 3, 2) sage: w = WeylGroup(F.cartan_type(),prefix="s").an_element(); w s0*s1*s2 sage: x.act_on_affine_weyl(w) s2*s0*s1 """ cartan_type = CartanType(cartan_type) if cartan_type.is_finite(): cartan_type = cartan_type.affine() if not cartan_type.is_affine(): raise NotImplementedError("Cartan type is not affine") if general_linear is True: if cartan_type.is_untwisted_affine() and cartan_type.type() == "A": return FundamentalGroupGL(cartan_type, prefix) else: raise ValueError("General Linear Fundamental group is untwisted type A") return FundamentalGroupOfExtendedAffineWeylGroup_Class(cartan_type,prefix,finite=True)
def CoxeterGroup(cartan_type, implementation = None): """ INPUT: - ``cartan_type`` -- a cartan type (or coercible into; see :class:`CartanType`) - ``implementation`` -- "permutation", "matrix", "coxeter3", or None (default: None) Returns an implementation of the Coxeter group of type ``cartan_type``. EXAMPLES: If ``implementation`` is not specified, a permutation representation is returned whenever possible (finite irreducible Cartan type, with the GAP3 Chevie package available):: sage: W = CoxeterGroup(["A",2]) sage: W # optional - chevie Permutation Group with generators [(1,3)(2,5)(4,6), (1,4)(2,3)(5,6)] Otherwise, a Weyl group is returned:: sage: W = CoxeterGroup(["A",3,1]) sage: W Weyl Group of type ['A', 3, 1] (as a matrix group acting on the root space) We now use the ``implementation`` option:: sage: W = CoxeterGroup(["A",2], implementation = "permutation") # optional - chevie sage: W # optional - chevie Permutation Group with generators [(1,3)(2,5)(4,6), (1,4)(2,3)(5,6)] sage: W.category() # optional - chevie Join of Category of finite permutation groups and Category of finite coxeter groups sage: W = CoxeterGroup(["A",2], implementation = "matrix") sage: W Weyl Group of type ['A', 2] (as a matrix group acting on the ambient space) sage: W = CoxeterGroup(["H",3], implementation = "matrix") Traceback (most recent call last): ... NotImplementedError: Coxeter group of type ['H', 3] as matrix group not implemented sage: W = CoxeterGroup(["A",4,1], implementation = "permutation") Traceback (most recent call last): ... NotImplementedError: Coxeter group of type ['A', 4, 1] as permutation group not implemented """ assert implementation in ["permutation", "matrix", "coxeter3", None] cartan_type = CartanType(cartan_type) if implementation is None: if cartan_type.is_finite() and cartan_type.is_irreducible() and is_chevie_available(): implementation = "permutation" else: implementation = "matrix" if implementation == "coxeter3": try: from sage.libs.coxeter3.coxeter_group import CoxeterGroup except ImportError: raise RuntimeError, "coxeter3 must be installed" else: return CoxeterGroup(cartan_type) if implementation == "permutation" and is_chevie_available() and \ cartan_type.is_finite() and cartan_type.is_irreducible(): return CoxeterGroupAsPermutationGroup(cartan_type) elif implementation == "matrix" and cartan_type.is_crystallographic(): return WeylGroup(cartan_type) else: raise NotImplementedError, "Coxeter group of type %s as %s group not implemented "%(cartan_type, implementation)
def WeylGroup(x, prefix=None, implementation='matrix'): """ Returns the Weyl group of the root system defined by the Cartan type (or matrix) ``ct``. INPUT: - ``x`` - a root system or a Cartan type (or matrix) OPTIONAL: - ``prefix`` -- changes the representation of elements from matrices to products of simple reflections - ``implementation`` -- one of the following: * ``'matrix'`` - as matrices acting on a root system * ``"permutation"`` - as a permutation group acting on the roots EXAMPLES: The following constructions yield the same result, namely a weight lattice and its corresponding Weyl group:: sage: G = WeylGroup(['F',4]) sage: L = G.domain() or alternatively and equivalently:: sage: L = RootSystem(['F',4]).ambient_space() sage: G = L.weyl_group() sage: W = WeylGroup(L) Either produces a weight lattice, with access to its roots and weights. :: sage: G = WeylGroup(['F',4]) sage: G.order() 1152 sage: [s1,s2,s3,s4] = G.simple_reflections() sage: w = s1*s2*s3*s4; w [ 1/2 1/2 1/2 1/2] [-1/2 1/2 1/2 -1/2] [ 1/2 1/2 -1/2 -1/2] [ 1/2 -1/2 1/2 -1/2] sage: type(w) == G.element_class True sage: w.order() 12 sage: w.length() # length function on Weyl group 4 The default representation of Weyl group elements is as matrices. If you prefer, you may specify a prefix, in which case the elements are represented as products of simple reflections. :: sage: W=WeylGroup("C3",prefix="s") sage: [s1,s2,s3]=W.simple_reflections() # lets Sage parse its own output sage: s2*s1*s2*s3 s1*s2*s3*s1 sage: s2*s1*s2*s3 == s1*s2*s3*s1 True sage: (s2*s3)^2==(s3*s2)^2 True sage: (s1*s2*s3*s1).matrix() [ 0 0 -1] [ 0 1 0] [ 1 0 0] :: sage: L = G.domain() sage: fw = L.fundamental_weights(); fw Finite family {1: (1, 1, 0, 0), 2: (2, 1, 1, 0), 3: (3/2, 1/2, 1/2, 1/2), 4: (1, 0, 0, 0)} sage: rho = sum(fw); rho (11/2, 5/2, 3/2, 1/2) sage: w.action(rho) # action of G on weight lattice (5, -1, 3, 2) We can also do the same for arbitrary Cartan matrices:: sage: cm = CartanMatrix([[2,-5,0],[-2,2,-1],[0,-1,2]]) sage: W = WeylGroup(cm) sage: W.gens() ( [-1 5 0] [ 1 0 0] [ 1 0 0] [ 0 1 0] [ 2 -1 1] [ 0 1 0] [ 0 0 1], [ 0 0 1], [ 0 1 -1] ) sage: s0,s1,s2 = W.gens() sage: s1*s2*s1 [ 1 0 0] [ 2 0 -1] [ 2 -1 0] sage: s2*s1*s2 [ 1 0 0] [ 2 0 -1] [ 2 -1 0] sage: s0*s1*s0*s2*s0 [ 9 0 -5] [ 2 0 -1] [ 0 1 -1] Same Cartan matrix, but with a prefix to display using simple reflections:: sage: W = WeylGroup(cm, prefix='s') sage: s0,s1,s2 = W.gens() sage: s0*s2*s1 s2*s0*s1 sage: (s1*s2)^3 1 sage: (s0*s1)^5 s0*s1*s0*s1*s0*s1*s0*s1*s0*s1 sage: s0*s1*s2*s1*s2 s2*s0*s1 sage: s0*s1*s2*s0*s2 s0*s1*s0 TESTS:: sage: TestSuite(WeylGroup(["A",3])).run() sage: TestSuite(WeylGroup(["A",3,1])).run() # long time sage: W = WeylGroup(['A',3,1]) sage: s = W.simple_reflections() sage: w = s[0]*s[1]*s[2] sage: w.reduced_word() [0, 1, 2] sage: w = s[0]*s[2] sage: w.reduced_word() [2, 0] sage: W = groups.misc.WeylGroup(['A',3,1]) """ if implementation == "permutation": return WeylGroup_permutation(x, prefix) elif implementation != "matrix": raise ValueError("invalid implementation") if x in RootLatticeRealizations: return WeylGroup_gens(x, prefix=prefix) try: ct = CartanType(x) except TypeError: ct = CartanMatrix(x) # See if it is a Cartan matrix if ct.is_finite(): return WeylGroup_gens(ct.root_system().ambient_space(), prefix=prefix) return WeylGroup_gens(ct.root_system().root_space(), prefix=prefix)
def CoxeterGroup(cartan_type, implementation=None): """ INPUT: - ``cartan_type`` -- a cartan type (or coercible into; see :class:`CartanType`) - ``implementation`` -- "permutation", "matrix", "coxeter3", or None (default: None) Returns an implementation of the Coxeter group of type ``cartan_type``. EXAMPLES: If ``implementation`` is not specified, a permutation representation is returned whenever possible (finite irreducible Cartan type, with the GAP3 Chevie package available):: sage: W = CoxeterGroup(["A",2]) sage: W # optional - chevie Permutation Group with generators [(1,3)(2,5)(4,6), (1,4)(2,3)(5,6)] Otherwise, a Weyl group is returned:: sage: W = CoxeterGroup(["A",3,1]) sage: W Weyl Group of type ['A', 3, 1] (as a matrix group acting on the root space) We now use the ``implementation`` option:: sage: W = CoxeterGroup(["A",2], implementation = "permutation") # optional - chevie sage: W # optional - chevie Permutation Group with generators [(1,3)(2,5)(4,6), (1,4)(2,3)(5,6)] sage: W.category() # optional - chevie Join of Category of finite permutation groups and Category of finite coxeter groups sage: W = CoxeterGroup(["A",2], implementation = "matrix") sage: W Weyl Group of type ['A', 2] (as a matrix group acting on the ambient space) sage: W = CoxeterGroup(["H",3], implementation = "matrix") Traceback (most recent call last): ... NotImplementedError: Coxeter group of type ['H', 3] as matrix group not implemented sage: W = CoxeterGroup(["A",4,1], implementation = "permutation") Traceback (most recent call last): ... NotImplementedError: Coxeter group of type ['A', 4, 1] as permutation group not implemented """ assert implementation in ["permutation", "matrix", "coxeter3", None] cartan_type = CartanType(cartan_type) if implementation is None: if cartan_type.is_finite() and cartan_type.is_irreducible( ) and is_chevie_available(): implementation = "permutation" else: implementation = "matrix" if implementation == "coxeter3": try: from sage.libs.coxeter3.coxeter_group import CoxeterGroup except ImportError: raise RuntimeError, "coxeter3 must be installed" else: return CoxeterGroup(cartan_type) if implementation == "permutation" and is_chevie_available() and \ cartan_type.is_finite() and cartan_type.is_irreducible(): return CoxeterGroupAsPermutationGroup(cartan_type) elif implementation == "matrix" and cartan_type.is_crystalographic(): return WeylGroup(cartan_type) else: raise NotImplementedError, "Coxeter group of type %s as %s group not implemented " % ( cartan_type, implementation)
class Associahedron(Polyhedron_QQ_ppl): r""" The generalized associahedron is a polytopal complex with vertices in one-to-one correspondence with clusters in the cluster complex, and with edges between two vertices if and only if the associated two clusters intersect in codimension 1. The associahedron of type `A_n` is one way to realize the classical associahedron as defined in http://en.wikipedia.org/wiki/Associahedron. A polytopal realization of the associahedron can be found in [CFZ]. The implementation is based on [CFZ, Theorem 1.5, Remark 1.6, and Corollary 1.9.]. EXAMPLES:: sage: Asso = Associahedron(['A',2]); Asso Generalized associahedron of type ['A', 2] with 5 vertices sage: sorted(Asso.Hrepresentation(), key=repr) [An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0, An inequality (1, 0) x + 1 >= 0, An inequality (1, 1) x + 1 >= 0] sage: Asso.Vrepresentation() (A vertex at (1, -1), A vertex at (1, 1), A vertex at (-1, 1), A vertex at (-1, 0), A vertex at (0, -1)) sage: Associahedron(['B',2]) Generalized associahedron of type ['B', 2] with 6 vertices The two pictures of [CFZ] can be recovered with:: sage: Asso = Associahedron(['A',3]); Asso Generalized associahedron of type ['A', 3] with 14 vertices sage: Asso.plot() sage: Asso = Associahedron(['B',3]); Asso Generalized associahedron of type ['B', 3] with 20 vertices sage: Asso.plot() TESTS:: sage: sorted(Associahedron(['A',3]).vertices()) [[-3/2, 0, -1/2], [-3/2, 0, 3/2], [-3/2, 1, -3/2], [-3/2, 2, -3/2], [-3/2, 2, 3/2], [-1/2, -1, -1/2], [-1/2, 0, -3/2], [1/2, -2, 1/2], [1/2, -2, 3/2], [3/2, -2, 1/2], [3/2, -2, 3/2], [3/2, 0, -3/2], [3/2, 2, -3/2], [3/2, 2, 3/2]] sage: sorted(Associahedron(['B',3]).vertices()) [[-3, 0, 0], [-3, 0, 3], [-3, 2, -2], [-3, 4, -3], [-3, 5, -3], [-3, 5, 3], [-2, 1, -2], [-2, 3, -3], [-1, -2, 0], [-1, -1, -1], [1, -4, 1], [1, -3, 0], [2, -5, 2], [2, -5, 3], [3, -5, 2], [3, -5, 3], [3, -3, 0], [3, 3, -3], [3, 5, -3], [3, 5, 3]] sage: Associahedron(['A',4]).f_vector() (1, 42, 84, 56, 14, 1) sage: Associahedron(['B',4]).f_vector() (1, 70, 140, 90, 20, 1) REFERENCES: - [CFZ] Chapoton, Fomin, Zelevinsky - Polytopal realizations of generalized associahedra, arXiv:0202004. """ def __init__(self, cartan_type): """ TESTS:: sage: Asso = Associahedron(['A',2]); Asso Generalized associahedron of type ['A', 2] with 5 vertices sage: TestSuite(Asso).run() """ self._cartan_type = CartanType(cartan_type) assert self._cartan_type.is_finite() root_space = self._cartan_type.root_system().root_space() # TODO: generalize this as a method of root lattice realization rhocheck = sum(beta.associated_coroot() for beta in root_space.positive_roots()) / 2 I = root_space.index_set() inequalities = [] for orbit in root_space.almost_positive_roots_decomposition(): c = rhocheck.coefficient(orbit[0].leading_support()) for beta in orbit: inequalities.append([c] + [beta.coefficient(i) for i in I]) Polyhedron_QQ_ppl.__init__(self, len(I), None, [inequalities, []]) # check that there are non non trivial facets assert self.n_facets() == len(inequalities) def _repr_(self): r""" Returns a string representation of self. EXAMPLES:: sage: Associahedron(['A',3])._repr_() "Generalized associahedron of type ['A', 3] with 14 vertices" """ return 'Generalized associahedron of type %s with %s vertices' % ( self._cartan_type, self.n_vertices()) def cartan_type(self): r""" Returns the Cartan type of self. EXAMPLES:: sage: Associahedron(['A',3]).cartan_type() ['A', 3] """ return self._cartan_type def vertices_in_root_space(self): r""" Returns the vertices of ``self`` as elements in the root space EXAMPLES:: sage: Asso = Associahedron(['A',2]) sage: Asso.vertices() [[1, -1], [1, 1], [-1, 1], [-1, 0], [0, -1]] sage: Asso.vertices_in_root_space() (alpha[1] - alpha[2], alpha[1] + alpha[2], -alpha[1] + alpha[2], -alpha[1], -alpha[2]) """ root_space = self._cartan_type.root_system().root_space() return tuple( root_space.from_vector(vector(V)) for V in self.vertex_generator())
def CoxeterGroup(data, implementation="reflection", base_ring=None, index_set=None): """ Return an implementation of the Coxeter group given by ``data``. INPUT: - ``data`` -- a Cartan type (or coercible into; see :class:`CartanType`) or a Coxeter matrix or graph - ``implementation`` -- (default: ``'reflection'``) can be one of the following: * ``'permutation'`` - as a permutation representation * ``'matrix'`` - as a Weyl group (as a matrix group acting on the root space); if this is not implemented, this uses the "reflection" implementation * ``'coxeter3'`` - using the coxeter3 package * ``'reflection'`` - as elements in the reflection representation; see :class:`~sage.groups.matrix_gps.coxeter_groups.CoxeterMatrixGroup` - ``base_ring`` -- (optional) the base ring for the ``'reflection'`` implementation - ``index_set`` -- (optional) the index set for the ``'reflection'`` implementation EXAMPLES: Now assume that ``data`` represents a Cartan type. If ``implementation`` is not specified, the reflection representation is returned:: sage: W = CoxeterGroup(["A",2]) sage: W Finite Coxeter group over Universal Cyclotomic Field with Coxeter matrix: [1 3] [3 1] sage: W = CoxeterGroup(["A",3,1]); W Coxeter group over Universal Cyclotomic Field with Coxeter matrix: [1 3 2 3] [3 1 3 2] [2 3 1 3] [3 2 3 1] sage: W = CoxeterGroup(['H',3]); W Finite Coxeter group over Universal Cyclotomic Field with Coxeter matrix: [1 3 2] [3 1 5] [2 5 1] We now use the ``implementation`` option:: sage: W = CoxeterGroup(["A",2], implementation = "permutation") # optional - chevie sage: W # optional - chevie Permutation Group with generators [(1,3)(2,5)(4,6), (1,4)(2,3)(5,6)] sage: W.category() # optional - chevie Join of Category of finite permutation groups and Category of finite coxeter groups sage: W = CoxeterGroup(["A",2], implementation="matrix") sage: W Weyl Group of type ['A', 2] (as a matrix group acting on the ambient space) sage: W = CoxeterGroup(["H",3], implementation="matrix") sage: W Finite Coxeter group over Universal Cyclotomic Field with Coxeter matrix: [1 3 2] [3 1 5] [2 5 1] sage: W = CoxeterGroup(["H",3], implementation="reflection") sage: W Finite Coxeter group over Universal Cyclotomic Field with Coxeter matrix: [1 3 2] [3 1 5] [2 5 1] sage: W = CoxeterGroup(["A",4,1], implementation="permutation") Traceback (most recent call last): ... NotImplementedError: Coxeter group of type ['A', 4, 1] as permutation group not implemented We use the different options for the "reflection" implementation:: sage: W = CoxeterGroup(["H",3], implementation="reflection", base_ring=RR) sage: W Finite Coxeter group over Real Field with 53 bits of precision with Coxeter matrix: [1 3 2] [3 1 5] [2 5 1] sage: W = CoxeterGroup([[1,10],[10,1]], implementation="reflection", index_set=['a','b'], base_ring=SR) sage: W Finite Coxeter group over Symbolic Ring with Coxeter matrix: [ 1 10] [10 1] TESTS:: sage: W = groups.misc.CoxeterGroup(["H",3]) """ if implementation not in ["permutation", "matrix", "coxeter3", "reflection", None]: raise ValueError("invalid type implementation") try: cartan_type = CartanType(data) except (TypeError, ValueError): # If it is not a Cartan type, try to see if we can represent it as a matrix group return CoxeterMatrixGroup(data, base_ring, index_set) if implementation is None: implementation = "matrix" if implementation == "reflection": return CoxeterMatrixGroup(cartan_type, base_ring, index_set) if implementation == "coxeter3": try: from sage.libs.coxeter3.coxeter_group import CoxeterGroup except ImportError: raise RuntimeError("coxeter3 must be installed") else: return CoxeterGroup(cartan_type) if implementation == "permutation" and is_chevie_available() and \ cartan_type.is_finite() and cartan_type.is_irreducible(): return CoxeterGroupAsPermutationGroup(cartan_type) elif implementation == "matrix": if cartan_type.is_crystallographic(): return WeylGroup(cartan_type) return CoxeterMatrixGroup(cartan_type, base_ring, index_set) raise NotImplementedError("Coxeter group of type {} as {} group not implemented".format(cartan_type, implementation))
def CoxeterGroup(data, implementation="reflection", base_ring=None, index_set=None): """ Return an implementation of the Coxeter group given by ``data``. INPUT: - ``data`` -- a Cartan type (or coercible into; see :class:`CartanType`) or a Coxeter matrix or graph - ``implementation`` -- (default: ``'reflection'``) can be one of the following: * ``'permutation'`` - as a permutation representation * ``'matrix'`` - as a Weyl group (as a matrix group acting on the root space); if this is not implemented, this uses the "reflection" implementation * ``'coxeter3'`` - using the coxeter3 package * ``'reflection'`` - as elements in the reflection representation; see :class:`~sage.groups.matrix_gps.coxeter_groups.CoxeterMatrixGroup` - ``base_ring`` -- (optional) the base ring for the ``'reflection'`` implementation - ``index_set`` -- (optional) the index set for the ``'reflection'`` implementation EXAMPLES: Now assume that ``data`` represents a Cartan type. If ``implementation`` is not specified, the reflection representation is returned:: sage: W = CoxeterGroup(["A",2]) sage: W Finite Coxeter group over Universal Cyclotomic Field with Coxeter matrix: [1 3] [3 1] sage: W = CoxeterGroup(["A",3,1]); W Coxeter group over Universal Cyclotomic Field with Coxeter matrix: [1 3 2 3] [3 1 3 2] [2 3 1 3] [3 2 3 1] sage: W = CoxeterGroup(['H',3]); W Finite Coxeter group over Universal Cyclotomic Field with Coxeter matrix: [1 3 2] [3 1 5] [2 5 1] We now use the ``implementation`` option:: sage: W = CoxeterGroup(["A",2], implementation = "permutation") # optional - chevie sage: W # optional - chevie Permutation Group with generators [(1,3)(2,5)(4,6), (1,4)(2,3)(5,6)] sage: W.category() # optional - chevie Join of Category of finite permutation groups and Category of finite coxeter groups sage: W = CoxeterGroup(["A",2], implementation="matrix") sage: W Weyl Group of type ['A', 2] (as a matrix group acting on the ambient space) sage: W = CoxeterGroup(["H",3], implementation="matrix") sage: W Finite Coxeter group over Universal Cyclotomic Field with Coxeter matrix: [1 3 2] [3 1 5] [2 5 1] sage: W = CoxeterGroup(["H",3], implementation="reflection") sage: W Finite Coxeter group over Universal Cyclotomic Field with Coxeter matrix: [1 3 2] [3 1 5] [2 5 1] sage: W = CoxeterGroup(["A",4,1], implementation="permutation") Traceback (most recent call last): ... NotImplementedError: Coxeter group of type ['A', 4, 1] as permutation group not implemented We use the different options for the "reflection" implementation:: sage: W = CoxeterGroup(["H",3], implementation="reflection", base_ring=RR) sage: W Finite Coxeter group over Real Field with 53 bits of precision with Coxeter matrix: [1 3 2] [3 1 5] [2 5 1] sage: W = CoxeterGroup([[1,10],[10,1]], implementation="reflection", index_set=['a','b'], base_ring=SR) sage: W Finite Coxeter group over Symbolic Ring with Coxeter matrix: [ 1 10] [10 1] TESTS:: sage: W = groups.misc.CoxeterGroup(["H",3]) """ if implementation not in [ "permutation", "matrix", "coxeter3", "reflection", None ]: raise ValueError("invalid type implementation") try: cartan_type = CartanType(data) except ( TypeError, ValueError ): # If it is not a Cartan type, try to see if we can represent it as a matrix group return CoxeterMatrixGroup(data, base_ring, index_set) if implementation is None: implementation = "matrix" if implementation == "reflection": return CoxeterMatrixGroup(cartan_type, base_ring, index_set) if implementation == "coxeter3": try: from sage.libs.coxeter3.coxeter_group import CoxeterGroup except ImportError: raise RuntimeError("coxeter3 must be installed") else: return CoxeterGroup(cartan_type) if implementation == "permutation" and is_chevie_available() and \ cartan_type.is_finite() and cartan_type.is_irreducible(): return CoxeterGroupAsPermutationGroup(cartan_type) elif implementation == "matrix": if cartan_type.is_crystallographic(): return WeylGroup(cartan_type) return CoxeterMatrixGroup(cartan_type, base_ring, index_set) raise NotImplementedError( "Coxeter group of type {} as {} group not implemented".format( cartan_type, implementation))
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")