def __classcall_private__(cls, ambient, contained=None, generators=None, virtualization=None, scaling_factors=None, cartan_type=None, index_set=None, category=None): """ Normalize arguments to ensure a (relatively) unique representation. EXAMPLES:: sage: B = crystals.Tableaux(['A',4], shape=[2,1]) sage: S1 = B.subcrystal(generators=(B(2,1,1), B(5,2,4)), index_set=[1,2]) sage: S2 = B.subcrystal(generators=[B(2,1,1), B(5,2,4)], cartan_type=['A',4], index_set=(1,2)) sage: S1 is S2 True """ if isinstance(contained, (list, tuple, set, frozenset)): contained = frozenset(contained) #elif contained in Sets(): if cartan_type is None: cartan_type = ambient.cartan_type() else: cartan_type = CartanType(cartan_type) if index_set is None: index_set = cartan_type.index_set if generators is None: generators = ambient.module_generators category = Crystals().or_subcategory(category) if ambient in FiniteCrystals() or isinstance(contained, frozenset): category = category.Finite() if virtualization is not None: if scaling_factors is None: scaling_factors = {i: 1 for i in index_set} from sage.combinat.crystals.virtual_crystal import VirtualCrystal return VirtualCrystal(ambient, virtualization, scaling_factors, contained, generators, cartan_type, index_set, category) if scaling_factors is not None: # virtualization must be None virtualization = {i: (i, ) for i in index_set} from sage.combinat.crystals.virtual_crystal import VirtualCrystal return VirtualCrystal(ambient, virtualization, scaling_factors, contained, generators, cartan_type, index_set, category) # We need to give these as optional arguments so it unpickles correctly return super(Subcrystal, cls).__classcall__(cls, ambient, contained, tuple(generators), cartan_type=cartan_type, index_set=tuple(index_set), category=category)
def digraph(self, subset=None, index_set=None): r""" Return the :class:`DiGraph` associated to ``self``. INPUT: - ``subset`` -- (optional) a subset of vertices for which the digraph should be constructed - ``index_set`` -- (optional) the index set to draw arrows .. SEEALSO:: :meth:`sage.categories.crystals.Crystals.ParentMethods.digraph` EXAMPLES:: sage: C = crystals.KirillovReshetikhin(['D',4,1], 2, 1) sage: G = C.digraph() sage: G.latex_options() # optional - dot2tex LaTeX options for Digraph on 29 vertices: {...'edge_options': <function <lambda> at 0x...>,...} sage: view(G, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window) """ G = Crystals().parent_class.digraph(self, subset, index_set) if have_dot2tex(): f = lambda u_v_label: ({"backward": u_v_label[2] == 0}) G.set_latex_options(edge_options=f) return G
def digraph(self, subset=None, index_set=None): r""" Return the :class:`DiGraph` associated to ``self``. INPUT: - ``subset`` -- (optional) a subset of vertices for which the digraph should be constructed - ``index_set`` -- (optional) the index set to draw arrows .. SEEALSO:: :meth:`sage.categories.crystals.Crystals.ParentMethods.digraph` EXAMPLES:: sage: C = crystals.KirillovReshetikhin(['D',4,1], 2, 1) sage: G = C.digraph() sage: G.latex_options() # optional - dot2tex LaTeX options for Digraph on 29 vertices: {...'edge_options': <function ... at ...>...} sage: view(G, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window) """ G = Crystals().parent_class.digraph(self, subset, index_set) if have_dot2tex(): f = lambda u_v_label: ({"backward": u_v_label[2] == 0}) G.set_latex_options(edge_options=f) return G
def __classcall_private__(cls, ambient, virtualization, scaling_factors, contained=None, generators=None, cartan_type=None, index_set=None, category=None): """ Normalize arguments to ensure a unique representation. EXAMPLES:: sage: B = crystals.Tableaux(['B',3], shape=[1]) sage: C = crystals.Tableaux(['D',4], shape=[2]) sage: psi1 = B.crystal_morphism(C.module_generators) sage: V1 = psi1.image() sage: psi2 = B.crystal_morphism(C.module_generators, index_set=[1,2,3]) sage: V2 = psi2.image() sage: V1 is V2 True TESTS: Check that :trac:`19481` is fixed:: sage: from sage.combinat.crystals.virtual_crystal import VirtualCrystal sage: A = crystals.Tableaux(['A',3], shape=[2,1,1]) sage: V = VirtualCrystal(A, {1:(1,3), 2:(2,)}, {1:1, 2:2}, cartan_type=['C',2]) sage: V.category() Category of finite crystals """ if cartan_type is None: cartan_type = ambient.cartan_type() else: cartan_type = CartanType(cartan_type) if index_set is None: index_set = cartan_type.index_set() if generators is None: generators = ambient.module_generators virtualization = Family(virtualization) scaling_factors = Family(scaling_factors) category = Crystals().or_subcategory(category) if ambient in FiniteCrystals() or isinstance(contained, frozenset): category = category.Finite() return super(Subcrystal, cls).__classcall__(cls, ambient, virtualization, scaling_factors, contained, tuple(generators), cartan_type, tuple(index_set), category)
def _Hom_(self, Y, category=None, **options): r""" Return the homset from ``self`` to ``Y`` in the category ``category``. INPUT: - ``Y`` -- a crystal - ``category`` -- a subcategory of :class:`HighestWeightCrysals`() or ``None`` The sole purpose of this method is to construct the homset as a :class:`~sage.categories.highest_weight_crystals.HighestWeightCrystalHomset`. If ``category`` is specified and is not a subcategory of :class:`HighestWeightCrystals`, a ``TypeError`` is raised instead This method is not meant to be called directly. Please use :func:`sage.categories.homset.Hom` instead. EXAMPLES:: sage: B = crystals.Tableaux(['A',2], shape=[2,1]) sage: H = B._Hom_(B) sage: H Set of Crystal Morphisms from The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]] to The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]] sage: type(H) <class 'sage.categories.highest_weight_crystals.HighestWeightCrystalHomset_with_category'> TESTS: Check that we fallback first to trying a crystal homset (:trac:`19458`):: sage: Binf = crystals.infinity.Tableaux(['A',2]) sage: Bi = crystals.elementary.Elementary(Binf.cartan_type(), 1) sage: tens = Bi.tensor(Binf) sage: Hom(Binf, tens) Set of Crystal Morphisms from ... """ if category is None: category = self.category() elif not category.is_subcategory(Crystals()): raise TypeError( "{} is not a subcategory of Crystals()".format(category)) if Y not in Crystals(): raise TypeError("{} is not a crystal".format(Y)) return HighestWeightCrystalHomset(self, Y, category=category, **options)
def super_categories(self): r""" EXAMPLES:: sage: HighestWeightCrystals().super_categories() [Category of crystals] """ return [Crystals()]
def super_categories(self): r""" EXAMPLES:: sage: FiniteCrystals().super_categories() [Category of crystals, Category of finite enumerated sets] """ return [Crystals(), FiniteEnumeratedSets()]
def super_categories(self): r""" EXAMPLES:: sage: RegularCrystals().super_categories() [Category of crystals] """ return [Crystals()]
def super_categories(self): r""" EXAMPLES:: sage: from sage.categories.loop_crystals import LoopCrystals sage: LoopCrystals().super_categories() [Category of crystals] """ return [Crystals()]
def super_categories(self): r""" EXAMPLES:: sage: from sage.categories.regular_supercrystals import RegularSuperCrystals sage: C = RegularSuperCrystals() sage: C.super_categories() [Category of finite crystals] """ return [Crystals().Finite()]
def super_categories(self): r""" EXAMPLES:: sage: from sage.categories.supercrystals import SuperCrystals sage: C = SuperCrystals() sage: C.super_categories() [Category of crystals] """ return [Crystals()]
def example(self, n=3): """ Returns an example of highest weight crystals, as per :meth:`Category.example`. EXAMPLES:: sage: B = ClassicalCrystals().example(); B Highest weight crystal of type A_3 of highest weight omega_1 """ return Crystals().example(n)
def example(self, n=3): """ Returns an example of highest weight crystals, as per :meth:`Category.example`. EXAMPLES:: sage: B = FiniteCrystals().example(); B Highest weight crystal of type A_3 of highest weight omega_1 """ from sage.categories.crystals import Crystals return Crystals().example(n)
def __init__(self, cartan_type, i): r""" Initialize ``self``. EXAMPLES:: sage: B = crystals.elementary.Elementary("D4",3) sage: TestSuite(B).run() """ Parent.__init__(self, category=(Crystals(), InfiniteEnumeratedSets())) self._i = i self._cartan_type = cartan_type self.module_generators = (self.element_class(self, 0), )
def _test_fast_iter(self, **options): r""" Tests whether the elements returned by :meth:`.__iter__` and ``Crystal.list(self)`` are the same (the two algorithms are different). EXAMPLES:: sage: C = crystals.Letters(['A', 5]) sage: C._test_fast_iter() """ tester = self._tester(**options) S = list(self) SS = list(Crystals().parent_class.__iter__(self)) tester.assert_(len(S) == len(SS)) tester.assert_(len(S) == len(set(S))) tester.assert_(set(S) == set(SS))
def __init__(self, cartan_type, starting_weight): """ EXAMPLES:: sage: C = CrystalOfLSPaths(['A',2,1],[-1,0,1]); C The crystal of LS paths of type ['A', 2, 1] and weight (-1, 0, 1) sage: C.R Root system of type ['A', 2, 1] sage: C.weight -Lambda[0] + Lambda[2] sage: C.weight.parent() Extended weight space over the Rational Field of the Root system of type ['A', 2, 1] sage: C.module_generators [(-Lambda[0] + Lambda[2],)] """ self._cartan_type = CartanType(cartan_type) self.R = RootSystem(cartan_type) self._name = "The crystal of LS paths of type %s and weight %s" % ( cartan_type, starting_weight) if self._cartan_type.is_affine(): self.extended = True if all(i >= 0 for i in starting_weight): Parent.__init__(self, category=HighestWeightCrystals()) else: Parent.__init__(self, category=Crystals()) else: self.extended = False Parent.__init__(self, category=FiniteCrystals()) Lambda = self.R.weight_space(extended=self.extended).basis() offset = self.R.index_set()[Integer(0)] zero_weight = self.R.weight_space(extended=self.extended).zero() self.weight = sum([zero_weight] + [ starting_weight[j - offset] * Lambda[j] for j in self.R.index_set() ]) if self.weight == zero_weight: initial_element = self(tuple([])) else: initial_element = self(tuple([self.weight])) self.module_generators = [initial_element]
def __init__(self, R, C, q): """ Initialize ``self``. EXAMPLES:: sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation sage: C = crystals.Tableaux(['A',3], shape=[1,1]) sage: R = ZZ['q'].fraction_field() sage: V = MinusculeRepresentation(R, C) sage: TestSuite(V).run() """ self._q = q self._d = C.cartan_type().symmetrizer() cat = QuantumGroupRepresentations(R).WithBasis() if C in Crystals().Finite(): cat = cat.FiniteDimensional() CombinatorialFreeModule.__init__(self, R, C, category=cat)
def __classcall_private__(cls, ambient, virtualization, scaling_factors, contained=None, generators=None, cartan_type=None, index_set=None, category=None): """ Normalize arguments to ensure a unique representation. EXAMPLES:: sage: B = crystals.Tableaux(['B',3], shape=[1]) sage: C = crystals.Tableaux(['D',4], shape=[2]) sage: psi1 = B.crystal_morphism(C.module_generators) sage: V1 = psi1.image() sage: psi2 = B.crystal_morphism(C.module_generators, index_set=[1,2,3]) sage: V2 = psi2.image() sage: V1 is V2 True """ if cartan_type is None: cartan_type = ambient.cartan_type() else: cartan_type = CartanType(cartan_type) if index_set is None: index_set = cartan_type.index_set() if generators is None: generators = ambient.module_generators virtualization = Family(virtualization) scaling_factors = Family(scaling_factors) category = Crystals().or_subcategory(category) return super(Subcrystal, cls).__classcall__(cls, ambient, virtualization, scaling_factors, contained, tuple(generators), cartan_type, tuple(index_set), category)
def _Hom_(self, Y, category=None, **options): r""" Return the homset from ``self`` to ``Y`` in the category ``category``. INPUT: - ``Y`` -- a crystal - ``category`` -- a subcategory of :class:`HighestWeightCrysals`() or ``None`` The sole purpose of this method is to construct the homset as a :class:`~sage.categories.highest_weight_crystals.HighestWeightCrystalHomset`. If ``category`` is specified and is not a subcategory of :class:`HighestWeightCrystals`, a ``TypeError`` is raised instead This method is not meant to be called directly. Please use :func:`sage.categories.homset.Hom` instead. EXAMPLES:: sage: B = crystals.Tableaux(['A',2], shape=[2,1]) sage: H = B._Hom_(B) sage: H Set of Crystal Morphisms from The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]] to The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]] sage: type(H) <class 'sage.categories.highest_weight_crystals.HighestWeightCrystalHomset_with_category'> """ if category is None: category = self.category() elif not category.is_subcategory(HighestWeightCrystals()): raise TypeError( "{} is not a subcategory of HighestWeightCrystals()". format(category)) if Y not in Crystals(): raise TypeError("{} is not a crystal".format(Y)) return HighestWeightCrystalHomset(self, Y, category=category, **options)
def digraph(self, subset=None, index_set=None, depth=None): """ Return the DiGraph associated to ``self``. INPUT: - ``subset`` -- (optional) a subset of vertices for which the digraph should be constructed - ``index_set`` -- (optional) the index set to draw arrows - ``depth`` -- the depth to draw; optional only for finite crystals EXAMPLES:: sage: T = crystals.Tableaux(['A',2], shape=[2,1]) sage: T.digraph() Digraph on 8 vertices sage: S = T.subcrystal(max_depth=2) sage: len(S) 5 sage: G = T.digraph(subset=list(S)) sage: G.is_isomorphic(T.digraph(depth=2), edge_labels=True) True TESTS: The following example demonstrates the speed improvement. The speedup in non-affine types is small however:: sage: depth = 5 sage: C = crystals.AlcovePaths(['A',2,1], [1,1,0]) sage: general_digraph = Crystals().parent_class.digraph sage: S = C.subcrystal(max_depth=depth, direction='lower') sage: %timeit C.digraph(depth=depth) # not tested 10 loops, best of 3: 48.9 ms per loop sage: %timeit general_digraph(C, subset=S) # not tested 10 loops, best of 3: 96.5 ms per loop sage: G1 = C.digraph(depth=depth) sage: G2 = general_digraph(C, subset=S) sage: G1.is_isomorphic(G2, edge_labels=True) True """ if subset is not None: return Crystals().parent_class.digraph(self, subset, index_set) if self not in Crystals().Finite() and depth is None: raise NotImplementedError( "crystals not known to be finite must" " specify either the subset or depth") from sage.graphs.all import DiGraph if index_set is None: index_set = self.index_set() rank = 0 d = {g: {} for g in self.module_generators} visited = set(d.keys()) while depth is None or rank < depth: recently_visited = set() for x in visited: d.setdefault(x, {}) # does nothing if there's a default for i in index_set: xfi = x.f(i) if xfi is not None: d[x][xfi] = i recently_visited.add(xfi) if not recently_visited: # No new nodes, nothing more to do break rank += 1 visited = recently_visited G = DiGraph(d) if have_dot2tex(): G.set_latex_options( format="dot2tex", edge_labels=True, color_by_label=self.cartan_type()._index_set_coloring) return G