def __classcall_private__(cls, cartan_type, shapes=None, shape=None): """ Normalizes the input arguments to ensure unique representation, and to delegate the construction of spin tableaux. EXAMPLES:: sage: T1 = CrystalOfTableaux(CartanType(['A',3]), shape = [2,2]) sage: T2 = CrystalOfTableaux(['A',3], shape = (2,2)) sage: T3 = CrystalOfTableaux(['A',3], shapes = ([2,2],)) sage: T2 is T1, T3 is T1 (True, True) """ cartan_type = CartanType(cartan_type) n = cartan_type.rank() # standardize shape/shapes input into a tuple of tuples assert operator.xor(shape is not None, shapes is not None) if shape is not None: shapes = (shape, ) spin_shapes = tuple(tuple(shape) for shape in shapes) try: shapes = tuple( tuple(trunc(i) for i in shape) for shape in spin_shapes) except StandardError: raise ValueError( "shapes should all be partitions or half-integer partitions") if spin_shapes == shapes: return super(CrystalOfTableaux, cls).__classcall__(cls, cartan_type, shapes) # Handle the construction of a crystals of spin tableaux # Caveat: this currently only supports all shapes being half # integer partitions of length the rank for type B and D. In # particular, for type D, the spins all have to be plus or all # minus spins assert all(len(sh) == n for sh in shapes), \ "the length of all half-integer partition shapes should be the rank" assert all(2*i % 2 == 1 for shape in spin_shapes for i in shape), \ "shapes should be either all partitions or all half-integer partitions" if cartan_type.type() == 'D': if all(i >= 0 for shape in spin_shapes for i in shape): S = CrystalOfSpinsPlus(cartan_type) elif all(shape[-1] < 0 for shape in spin_shapes): S = CrystalOfSpinsMinus(cartan_type) else: raise ValueError, "In type D spins should all be positive or negative" else: assert all( i >= 0 for shape in spin_shapes for i in shape), \ "shapes should all be partitions" S = CrystalOfSpins(cartan_type) B = CrystalOfTableaux(cartan_type, shapes=shapes) T = TensorProductOfCrystals(S, B, generators=[[S.module_generators[0], x] for x in B.module_generators]) T.rename("The crystal of tableaux of type %s and shape(s) %s" % (cartan_type, list(list(shape) for shape in spin_shapes))) T.shapes = spin_shapes return T
def __classcall_private__(cls, cartan_type): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: B = crystals.infinity.Tableaux(['A',4]) sage: B2 = crystals.infinity.Tableaux(CartanType(['A',4])) sage: B is B2 True """ cartan_type = CartanType(cartan_type) if cartan_type.type() == 'D': return InfinityCrystalOfTableauxTypeD(cartan_type) if cartan_type.type() == 'Q': return DualInfinityQueerCrystalOfTableaux(cartan_type) return super(InfinityCrystalOfTableaux, cls).__classcall__(cls, cartan_type)
def __classcall_private__(cls, cartan_type, shapes = None, shape = None): """ Normalizes the input arguments to ensure unique representation, and to delegate the construction of spin tableaux. EXAMPLES:: sage: T1 = CrystalOfTableaux(CartanType(['A',3]), shape = [2,2]) sage: T2 = CrystalOfTableaux(['A',3], shape = (2,2)) sage: T3 = CrystalOfTableaux(['A',3], shapes = ([2,2],)) sage: T2 is T1, T3 is T1 (True, True) """ cartan_type = CartanType(cartan_type) n = cartan_type.rank() # standardize shape/shapes input into a tuple of tuples assert operator.xor(shape is not None, shapes is not None) if shape is not None: shapes = (shape,) spin_shapes = tuple( tuple(shape) for shape in shapes ) try: shapes = tuple( tuple(trunc(i) for i in shape) for shape in spin_shapes ) except StandardError: raise ValueError("shapes should all be partitions or half-integer partitions") if spin_shapes == shapes: return super(CrystalOfTableaux, cls).__classcall__(cls, cartan_type, shapes) # Handle the construction of a crystals of spin tableaux # Caveat: this currently only supports all shapes being half # integer partitions of length the rank for type B and D. In # particular, for type D, the spins all have to be plus or all # minus spins assert all(len(sh) == n for sh in shapes), \ "the length of all half-integer partition shapes should be the rank" assert all(2*i % 2 == 1 for shape in spin_shapes for i in shape), \ "shapes should be either all partitions or all half-integer partitions" if cartan_type.type() == 'D': if all( i >= 0 for shape in spin_shapes for i in shape): S = CrystalOfSpinsPlus(cartan_type) elif all(shape[-1]<0 for shape in spin_shapes): S = CrystalOfSpinsMinus(cartan_type) else: raise ValueError, "In type D spins should all be positive or negative" else: assert all( i >= 0 for shape in spin_shapes for i in shape), \ "shapes should all be partitions" S = CrystalOfSpins(cartan_type) B = CrystalOfTableaux(cartan_type, shapes = shapes) T = TensorProductOfCrystals(S,B, generators=[[S.module_generators[0],x] for x in B.module_generators]) T.rename("The crystal of tableaux of type %s and shape(s) %s"%(cartan_type, list(list(shape) for shape in spin_shapes))) T.shapes = spin_shapes return T
def __classcall_private__(cls, cartan_type): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: B = crystals.infinity.Tableaux(['A',4]) sage: B2 = crystals.infinity.Tableaux(CartanType(['A',4])) sage: B is B2 True """ cartan_type = CartanType(cartan_type) if cartan_type.type() == 'D': return InfinityCrystalOfTableauxTypeD(cartan_type) return super(InfinityCrystalOfTableaux, cls).__classcall__(cls, cartan_type)
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 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, cartan_type, shapes=None, shape=None): """ Normalizes the input arguments to ensure unique representation, and to delegate the construction of spin tableaux. EXAMPLES:: sage: T1 = crystals.Tableaux(CartanType(['A',3]), shape = [2,2]) sage: T2 = crystals.Tableaux(['A',3], shape = (2,2)) sage: T3 = crystals.Tableaux(['A',3], shapes = ([2,2],)) sage: T2 is T1, T3 is T1 (True, True) sage: T1 = crystals.Tableaux(['A', [1,1]], shape=[3,1,1,1]) sage: T1 Crystal of BKK tableaux of shape [3, 1, 1, 1] of gl(2|2) sage: T2 = crystals.Tableaux(['A', [1,1]], [3,1,1,1]) sage: T1 is T2 True """ cartan_type = CartanType(cartan_type) if cartan_type.letter == 'A' and isinstance(cartan_type, SuperCartanType_standard): if shape is None: shape = shapes shape = _Partitions(shape) from sage.combinat.crystals.bkk_crystals import CrystalOfBKKTableaux return CrystalOfBKKTableaux(cartan_type, shape=shape) if cartan_type.letter == 'Q': if any(shape[i] == shape[i + 1] for i in range(len(shape) - 1)): raise ValueError("not a strict partition") shape = _Partitions(shape) return CrystalOfQueerTableaux(cartan_type, shape=shape) n = cartan_type.rank() # standardize shape/shapes input into a tuple of tuples # of length n, or n+1 in type A assert operator.xor(shape is not None, shapes is not None) if shape is not None: shapes = (shape, ) if cartan_type.type() == "A": n1 = n + 1 else: n1 = n if not all(all(i == 0 for i in shape[n1:]) for shape in shapes): raise ValueError( "shapes should all have length at most equal to the rank or the rank + 1 in type A" ) spin_shapes = tuple((tuple(shape) + (0, ) * (n1 - len(shape)))[:n1] for shape in shapes) try: shapes = tuple( tuple(trunc(i) for i in shape) for shape in spin_shapes) except Exception: raise ValueError( "shapes should all be partitions or half-integer partitions") if spin_shapes == shapes: shapes = tuple( _Partitions(shape) if shape[n1 - 1] in NN else shape for shape in shapes) return super(CrystalOfTableaux, cls).__classcall__(cls, cartan_type, shapes) # Handle the construction of a crystals of spin tableaux # Caveat: this currently only supports all shapes being half # integer partitions of length the rank for type B and D. In # particular, for type D, the spins all have to be plus or all # minus spins if any(len(sh) != n for sh in shapes): raise ValueError( "the length of all half-integer partition shapes should be the rank" ) if any(2 * i % 2 != 1 for shape in spin_shapes for i in shape): raise ValueError( "shapes should be either all partitions or all half-integer partitions" ) if any( any(i < j for i, j in zip(shape, shape[1:-1] + (abs(shape[-1]), ))) for shape in spin_shapes): raise ValueError("entries of each shape must be weakly decreasing") if cartan_type.type() == 'D': if all(i >= 0 for shape in spin_shapes for i in shape): S = CrystalOfSpinsPlus(cartan_type) elif all(shape[-1] < 0 for shape in spin_shapes): S = CrystalOfSpinsMinus(cartan_type) else: raise ValueError( "in type D spins should all be positive or negative") else: if any(i < 0 for shape in spin_shapes for i in shape): raise ValueError("shapes should all be partitions") S = CrystalOfSpins(cartan_type) B = CrystalOfTableaux(cartan_type, shapes=shapes) T = TensorProductOfCrystals(S, B, generators=[[S.module_generators[0], x] for x in B.module_generators]) T.rename("The crystal of tableaux of type %s and shape(s) %s" % (cartan_type, list(list(shape) for shape in spin_shapes))) T.shapes = spin_shapes return T
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)