def __init__(self, dominant_weight): """ EXAMPLES:: sage: C=CartanType(['E',6]) sage: La=C.root_system().weight_lattice().fundamental_weights() sage: p2=2*La[2] sage: p1=La[2] sage: p0=0*La[2] sage: T = crystals.HighestWeight(0*La[2]) sage: T.cardinality() 1 sage: T = crystals.HighestWeight(La[2]) sage: T.cardinality() 78 sage: T = crystals.HighestWeight(2*La[2]) sage: T.cardinality() 2430 """ B1 = CrystalOfLetters(['E',6]) B6 = CrystalOfLetters(['E',6], dual = True) self.column_crystal = {1 : B1, 6 : B6, 4 : TensorProductOfCrystals(B1,B1,B1,generators=[[B1([-3,4]),B1([-1,3]),B1([1])]]), 3 : TensorProductOfCrystals(B1,B1,generators=[[B1([-1,3]),B1([1])]]), 5 : TensorProductOfCrystals(B6,B6,generators=[[B6([5,-6]),B6([6])]]), 2 : TensorProductOfCrystals(B6,B1,generators=[[B6([2,-1]),B1([1])]])} FiniteDimensionalHighestWeightCrystal_TypeE.__init__(self, dominant_weight)
def __init__(self, cartan_type, B, biject_class): r""" Construct a tensor product of KR tableaux. INPUT: - ``cartan_type`` -- The crystal type and n value - ``B`` -- An (ordered) list of dimensions - ``biject_class`` -- The class the bijection creates The dimensions (i.e. `B`) is a list whose entries are lists of the form `[r, s]` which correspond to a tableau with `r` rows and `s` columns (or of shape `[r]*s`) and corresponds to a Kirillov-Reshetikhin crystal `B^{r,s}`. TESTS:: sage: HW = HighestWeightTensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[3,1], [2,2]]); HW # indirect doctest Highest weight tensor product of Kirillov-Reshetikhin tableaux of type ['A', 3, 1] and tableau shape(s) [[1, 1, 1], [2, 2]] """ assert cartan_type.is_affine() self.affine_ct = cartan_type self.dims = B self.letters = CrystalOfLetters(cartan_type) self._bijection_class = biject_class tensorProd = [] for rectDims in B: tensorProd.append( KirillovReshetikhinTableaux(self.letters.cartan_type(), rectDims[0], rectDims[1])) FullTensorProductOfCrystals.__init__(self, tuple(tensorProd))
def endpoint6(r): """ Return the endpoint for `B^{r,1}` in type `E_6^{(1)}`. EXAMPLES:: sage: from sage.combinat.rigged_configurations.bij_type_E67 import endpoint6 sage: endpoint6(1) (1,) sage: endpoint6(2) (-3, 2) sage: endpoint6(3) (-1, 3) sage: endpoint6(4) (-3, 4) sage: endpoint6(5) (-2, 5) sage: endpoint6(6) (-1, 6) """ C = CrystalOfLetters(['E', 6]) if r == 1: return C.module_generators[0] # C((1,)) elif r == 2: return C((-3, 2)) elif r == 3: return C((-1, 3)) elif r == 4: return C((-3, 4)) elif r == 5: return C((-2, 5)) elif r == 6: return C((-1, 6))
def __init__(self, cartan_type, B): r""" Initialize ``self``. EXAMPLES:: sage: KRT = crystals.TensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[3,1],[2,2]]); KRT Tensor product of Kirillov-Reshetikhin tableaux of type ['A', 3, 1] and factor(s) ((3, 1), (2, 2)) sage: TestSuite(KRT).run() # long time sage: KRT = crystals.TensorProductOfKirillovReshetikhinTableaux(['D',4,1], [[2,2]]) sage: TestSuite(KRT).run() # long time sage: KRT = crystals.TensorProductOfKirillovReshetikhinTableaux(['D',4,1], [[3,1]]) sage: TestSuite(KRT).run() # long time sage: KRT = crystals.TensorProductOfKirillovReshetikhinTableaux(['D',4,1], [[4,3]]) sage: TestSuite(KRT).run() # long time """ self.dims = B self.letters = CrystalOfLetters(cartan_type.classical()) tensor_prod = tuple( KirillovReshetikhinTableaux(cartan_type, rect_dims[0], rect_dims[1]) for rect_dims in B) FullTensorProductOfRegularCrystals.__init__(self, tensor_prod, cartan_type=cartan_type) # This is needed to override the module_generators set in FullTensorProductOfRegularCrystals self.module_generators = HighestWeightTensorKRT(self) self.rename("Tensor product of Kirillov-Reshetikhin tableaux of type %s and factor(s) %s"%(\ cartan_type, B))
def __init__(self, dominant_weight): """ EXAMPLES:: sage: C=CartanType(['E',7]) sage: La=C.root_system().weight_lattice().fundamental_weights() sage: T = crystals.HighestWeight(0*La[1]) sage: T.cardinality() 1 sage: T = crystals.HighestWeight(La[1]) sage: T.cardinality() 133 sage: T = crystals.HighestWeight(2*La[1]) sage: T.cardinality() 7371 """ B = CrystalOfLetters(['E',7]) self.column_crystal = {7 : B, 1 : TensorProductOfCrystals(B,B,generators=[[B([-7,1]),B([7])]]), 2 : TensorProductOfCrystals(B,B,B,generators=[[B([-1,2]),B([-7,1]),B([7])]]), 3 : TensorProductOfCrystals(B,B,B,B,generators=[[B([-2,3]),B([-1,2]),B([-7,1]),B([7])]]), 4 : TensorProductOfCrystals(B,B,B,B,generators=[[B([-5,4]),B([-6,5]),B([-7,6]),B([7])]]), 5 : TensorProductOfCrystals(B,B,B,generators=[[B([-6,5]),B([-7,6]),B([7])]]), 6 : TensorProductOfCrystals(B,B,generators=[[B([-7,6]),B([7])]])} FiniteDimensionalHighestWeightCrystal_TypeE.__init__(self, dominant_weight)
def __init__(self, cartan_type, B, biject_class): r""" Construct a tensor product of KR tableaux. INPUT: - ``cartan_type`` -- The crystal type and n value - ``B`` -- An (ordered) list of dimensions - ``biject_class`` -- The class the bijection creates The dimensions (i.e. `B`) is a list whose entries are lists of the form `[r, s]` which correspond to a tableau with `r` rows and `s` columns (or of shape `[r]*s`) and corresponds to a Kirillov-Reshetikhin crystal `B^{r,s}`. TESTS:: sage: HW = HighestWeightTensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[3,1], [2,2]]); HW # indirect doctest Highest weight tensor product of Kirillov-Reshetikhin tableaux of type ['A', 3, 1] and tableau shape(s) [[1, 1, 1], [2, 2]] """ assert cartan_type.is_affine() self.affine_ct = cartan_type self.dims = B self.letters = CrystalOfLetters(cartan_type) self._bijection_class = biject_class tensorProd = [] for rectDims in B: tensorProd.append(KirillovReshetikhinTableaux( self.letters.cartan_type(), rectDims[0], rectDims[1])) FullTensorProductOfCrystals.__init__(self, tuple(tensorProd))
def __init__(self, cartan_type, r, s): r""" Initialize the KirillovReshetikhinTableaux class. INPUT: - ``cartan_type`` -- The Cartan type - ``r`` -- The number of rows - ``s`` -- The number of columns EXAMPLES:: sage: KRT = KirillovReshetikhinTableaux(['A', 4, 1], 2, 3); KRT Kirillov-Reshetikhin tableaux of type ['A', 4, 1] and shape (2, 3) sage: TestSuite(KRT).run() # long time (4s on sage.math, 2013) sage: KRT = KirillovReshetikhinTableaux(['D', 4, 1], 2, 3); KRT Kirillov-Reshetikhin tableaux of type ['D', 4, 1] and shape (2, 3) sage: TestSuite(KRT).run() # long time (53s on sage.math, 2013) sage: KRT = KirillovReshetikhinTableaux(['D', 4, 1], 4, 1); KRT Kirillov-Reshetikhin tableaux of type ['D', 4, 1] and shape (4, 1) sage: TestSuite(KRT).run() """ self._r = r self._s = s Parent.__init__(self, category=FiniteCrystals()) self.rename( "Kirillov-Reshetikhin tableaux of type %s and shape (%d, %d)" % (cartan_type, r, s)) self._cartan_type = cartan_type.classical() self.letters = CrystalOfLetters(self._cartan_type) self.module_generators = self._build_module_generators()
def _call_(self, x): r""" Return the image of ``x`` in the tableau model of `B(\infty)`. EXAMPLES:: sage: T = crystals.infinity.Tableaux(['A',3]) sage: RC = crystals.infinity.RiggedConfigurations(['A',3]) sage: phi = T.coerce_map_from(RC) sage: x = RC.an_element().f_string([2,2,1,1,3,2,1,2,1,3]) sage: y = phi(x); y.pp() 1 1 1 1 1 2 2 3 4 2 2 3 4 3 sage: (~phi)(y) == x True """ lam = [sum(nu) + 1 for nu in x] ct = self.domain().cartan_type() I = ct.index_set() if ct.type() == 'D': lam[-2] = max(lam[-2], lam[-1]) lam.pop() l = sum([[[r + 1, 1]] * v for r, v in enumerate(lam[:-1])], []) n = len(I) l = l + sum([[[n, 1], [n - 1, 1]] for k in range(lam[-1])], []) else: if ct.type() == 'B': lam[-1] *= 2 l = sum([[[r, 1]] * lam[i] for i, r in enumerate(I)], []) RC = RiggedConfigurations(ct.affine(), reversed(l)) elt = RC(x) if ct.type() == 'A': bij = RCToKRTBijectionTypeA(elt) elif ct.type() == 'B': bij = RCToMLTBijectionTypeB(elt) elif ct.type() == 'C': bij = RCToKRTBijectionTypeC(elt) elif ct.type() == 'D': bij = RCToMLTBijectionTypeD(elt) else: raise NotImplementedError( "bijection of type {} not yet implemented".format(ct)) y = bij.run() # Now make the result marginally large y = [list(c) for c in y] cur = [] L = CrystalOfLetters(ct) for i in I: cur.insert(0, L(i)) c = y.count(cur) while c > 1: y.remove(cur) c -= 1 return self.codomain()(*flatten(y))
def __init__(self, cartan_type): """ Initialize ``self``. EXAMPLES:: sage: B = crystals.infinity.Tableaux(['A',2]) sage: TestSuite(B).run() # long time """ Parent.__init__( self, category=(HighestWeightCrystals(), InfiniteEnumeratedSets()) ) self._cartan_type = cartan_type self.letters = CrystalOfLetters(cartan_type) self.module_generators = (self.module_generator(),)
def run(self): r""" Run the bijection from rigged configurations to a marginally large tableau. EXAMPLES:: sage: vct = CartanType(['B',4]).as_folding() sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: T = crystals.infinity.Tableaux(['B',4]) sage: Psi = RC.crystal_morphism({RC.module_generators[0]: T.module_generators[0]}) sage: RCS = [x.value for x in RC.subcrystal(max_depth=4)] sage: all(Psi(nu) == T(nu) for nu in RCS) # long time # indirect doctest True """ letters = CrystalOfLetters( self.rigged_con.parent()._cartan_type.classical()) ret_crystal_path = [] while self.cur_dims: dim = self.cur_dims[0] ret_crystal_path.append([]) # Assumption: all factors are single columns if dim[0] == self.n: # Spinor case, since we've done 2\Lambda_n -> \Lambda_{n-1} self.cur_dims.pop(1) while dim[0] > 0: dim[0] -= 1 # This takes care of the indexing b = self.next_state(dim[0]) # Make sure we have a crystal letter ret_crystal_path[-1].append(letters(b)) # Append the rank self.cur_dims.pop(0) # Pop off the leading column return ret_crystal_path
def endpoint7(r): """ Return the endpoint for `B^{r,1}` in type `E_7^{(1)}`. EXAMPLES:: sage: from sage.combinat.rigged_configurations.bij_type_E67 import endpoint7 sage: endpoint7(1) (-7, 1) sage: endpoint7(2) (-1, 2) sage: endpoint7(3) (-2, 3) sage: endpoint7(4) (-5, 4) sage: endpoint7(5) (-6, 5) sage: endpoint7(6) (-7, 6) sage: endpoint7(7) (7,) """ C = CrystalOfLetters(['E', 7]) if r == 1: return C((-7, 1)) elif r == 2: return C((-1, 2)) elif r == 3: return C((-2, 3)) elif r == 4: return C((-5, 4)) elif r == 5: return C((-6, 5)) elif r == 6: return C((-7, 6)) elif r == 7: return C.module_generators[0] # C((7,))
def run(self, verbose=False, build_graph=False): """ Run the bijection from rigged configurations to tensor product of KR tableaux. INPUT: - ``verbose`` -- (default: ``False``) display each step in the bijection - ``build_graph`` -- (default: ``False``) build the graph of each step of the bijection EXAMPLES:: sage: RC = RiggedConfigurations(['A', 4, 1], [[2, 1]]) sage: x = RC(partition_list=[[1],[1],[1],[1]]) sage: from sage.combinat.rigged_configurations.bij_type_A import RCToKRTBijectionTypeA sage: RCToKRTBijectionTypeA(x).run() [[2], [5]] sage: bij = RCToKRTBijectionTypeA(x) sage: bij.run(build_graph=True) [[2], [5]] sage: bij._graph Digraph on 3 vertices """ from sage.combinat.crystals.letters import CrystalOfLetters letters = CrystalOfLetters( self.rigged_con.parent()._cartan_type.classical()) # This is technically bad, but because the first thing we do is append # an empty list to ret_crystal_path, we correct this. We do it this # way so that we do not have to remove an empty list after the # bijection has been performed. ret_crystal_path = [] for dim in self.rigged_con.parent().dims: ret_crystal_path.append([]) # Iterate over each column for dummy_var in range(dim[1]): # Split off a new column if necessary if self.cur_dims[0][1] > 1: if verbose: print("====================") print( repr(self.rigged_con.parent()( *self.cur_partitions, use_vacancy_numbers=True))) print("--------------------") print(ret_crystal_path) print("--------------------\n") print("Applying column split") self.cur_dims[0][1] -= 1 self.cur_dims.insert(0, [dim[0], 1]) # Perform the corresponding splitting map on rigged configurations # All it does is update the vacancy numbers on the RC side for a in range(self.n): self._update_vacancy_numbers(a) if build_graph: y = self.rigged_con.parent()( *[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True) self._graph.append( [self._graph[-1][1], (y, len(self._graph)), 'ls']) while self.cur_dims[0][0] > 0: if verbose: print("====================") print( repr(self.rigged_con.parent()( *self.cur_partitions, use_vacancy_numbers=True))) print("--------------------") print(ret_crystal_path) print("--------------------\n") self.cur_dims[0][0] -= 1 # This takes care of the indexing b = self.next_state(self.cur_dims[0][0]) # Make sure we have a crystal letter ret_crystal_path[-1].append(letters(b)) # Append the rank if build_graph: y = self.rigged_con.parent()( *[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True) self._graph.append([ self._graph[-1][1], (y, len(self._graph)), letters(b) ]) self.cur_dims.pop(0) # Pop off the leading column if build_graph: self._graph.pop(0) # Remove the dummy at the start from sage.graphs.digraph import DiGraph from sage.graphs.dot2tex_utils import have_dot2tex self._graph = DiGraph(self._graph) if have_dot2tex(): self._graph.set_latex_options(format="dot2tex", edge_labels=True) # Basic check to make sure we end with the empty configuration #tot_len = sum([len(rp) for rp in self.cur_partitions]) #if tot_len != 0: # print "Invalid bijection end for:" # print self.rigged_con # print "-----------------------" # print self.cur_partitions # raise ValueError("Invalid bijection end") return self.KRT(pathlist=ret_crystal_path)
def to_tensor_product_of_Kirillov_Reshetikhin_tableaux( self, display_steps=False, **options): r""" Perform the bijection from this rigged configuration to a tensor product of Kirillov-Reshetikhin tableaux given in [RigConBijection]_ for single boxes and with [BijectionLRT]_ and [BijectionDn]_ for multiple columns and rows. INPUT: - ``display_steps`` -- (default: ``False``) Boolean which indicates if we want to output each step in the algorithm OUTPUT: - The tensor product of KR tableaux element corresponding to this rigged configuration. EXAMPLES:: sage: RC = RiggedConfigurations(['A', 4, 1], [[2, 2]]) sage: RC(partition_list=[[2], [2,2], [2], [2]]).to_tensor_product_of_Kirillov_Reshetikhin_tableaux() [[3, 3], [5, 5]] sage: RC = RiggedConfigurations(['D', 4, 1], [[2, 2]]) sage: elt = RC(partition_list=[[2], [2,2], [1], [1]]) sage: tp_krt = elt.to_tensor_product_of_Kirillov_Reshetikhin_tableaux(); tp_krt [[2, 3], [3, -2]] This is invertible by calling :meth:`~sage.combinat.rigged_configurations.tensor_product_kr_tableaux_element.TensorProductOfKirillovReshetikhinTableauxElement.to_rigged_configuration()`:: sage: ret = tp_krt.to_rigged_configuration(); ret <BLANKLINE> 0[ ][ ]0 <BLANKLINE> -2[ ][ ]-2 -2[ ][ ]-2 <BLANKLINE> 0[ ]0 <BLANKLINE> 0[ ]0 <BLANKLINE> sage: elt == ret True """ #Letters = CrystalOfLetters(self.parent()._cartan_type.classical()) Letters = CrystalOfLetters(self.parent()._cartan_type) n = self.parent()._cartan_type.n type = self.parent()._cartan_type.letter # Pass in a copy of our partitions since the bijection is destructive to it. bijection = RCToKRTBijection(self) # This is technically bad, but because the first thing we do is append # an empty list to ret_crystal_path, we correct this. We do it this # way so that we do not have to remove an empty list after the # bijection has been performed. ret_crystal_path = [] for dim in self.parent().dims: ret_crystal_path.append([]) # Iterate over each column for dummy_var in range(dim[1]): # Split off a new column if necessary if bijection.cur_dims[0][1] > 1: bijection.cur_dims[0][1] -= 1 bijection.cur_dims.insert(0, [dim[0], 1]) # Perform the corresponding splitting map on rigged configurations # All it does is update the vacancy numbers on the RC side for a in range(n): bijection._update_vacancy_numbers(a) # Check to see if we are a spinor if type == 'D' and dim[0] >= n - 1: if display_steps: print "====================" print repr(self.parent()(*bijection.cur_partitions)) print "--------------------" print ret_crystal_path print "--------------------\n" print "Applied doubling map" bijection.doubling_map() if dim[0] == n - 1: if display_steps: print "====================" print repr( self.parent()(*bijection.cur_partitions)) print "--------------------" print ret_crystal_path print "--------------------\n" b = bijection.next_state(n) if b == n: b = -n ret_crystal_path[-1].append( Letters(b)) # Append the rank while bijection.cur_dims[0][0] > 0: if display_steps: print "====================" print repr(self.parent()(*bijection.cur_partitions)) print "--------------------" print ret_crystal_path print "--------------------\n" bijection.cur_dims[0][ 0] -= 1 # This takes care of the indexing b = bijection.next_state(bijection.cur_dims[0][0]) # Corrections for spinor if type == 'D' and dim[0] == n and b == -n \ and bijection.cur_dims[0][0] == n - 1: b = -(n - 1) # Make sure we have a crystal letter ret_crystal_path[-1].append(Letters(b)) # Append the rank bijection.cur_dims.pop(0) # Pop off the leading column # Check to see if we were a spinor if type == 'D' and dim[0] >= n - 1: if display_steps: print "====================" print repr(self.parent()(*bijection.cur_partitions)) print "--------------------" print ret_crystal_path print "--------------------\n" print "Applied halving map" bijection.halving_map() # If you're curious about this, see the note in AbstractTensorProductOfKRTableaux._highest_weight_iter(). # You should never call this option. if "KRT_init_hack" in options: return options["KRT_init_hack"](pathlist=ret_crystal_path) #return self.parent()._bijection_class(self.parent()._cartan_type, return self.parent()._bijection_class( self.parent()._affine_ct, self.parent().dims)(pathlist=ret_crystal_path)
def run(self, verbose=False): """ Run the bijection from rigged configurations to tensor product of KR tableaux. INPUT: - ``verbose`` -- (Default: ``False``) Display each step in the bijection EXAMPLES:: sage: RC = RiggedConfigurations(['A', 4, 1], [[2, 1]]) sage: from sage.combinat.rigged_configurations.bij_type_A import RCToKRTBijectionTypeA sage: RCToKRTBijectionTypeA(RC(partition_list=[[1],[1],[1],[1]])).run() [[2], [5]] """ from sage.combinat.crystals.letters import CrystalOfLetters letters = CrystalOfLetters( self.rigged_con.parent()._cartan_type.classical()) # This is technically bad, but because the first thing we do is append # an empty list to ret_crystal_path, we correct this. We do it this # way so that we do not have to remove an empty list after the # bijection has been performed. ret_crystal_path = [] for dim in self.rigged_con.parent().dims: ret_crystal_path.append([]) # Iterate over each column for dummy_var in range(dim[1]): # Split off a new column if necessary if self.cur_dims[0][1] > 1: if verbose: print("====================") print( repr(self.rigged_con.parent()( *self.cur_partitions))) print("--------------------") print(ret_crystal_path) print("--------------------\n") print("Applying column split") self.cur_dims[0][1] -= 1 self.cur_dims.insert(0, [dim[0], 1]) # Perform the corresponding splitting map on rigged configurations # All it does is update the vacancy numbers on the RC side for a in range(self.n): self._update_vacancy_numbers(a) while self.cur_dims[0][0] > 0: if verbose: print("====================") print( repr(self.rigged_con.parent()( *self.cur_partitions))) print("--------------------") print(ret_crystal_path) print("--------------------\n") self.cur_dims[0][0] -= 1 # This takes care of the indexing b = self.next_state(self.cur_dims[0][0]) # Make sure we have a crystal letter ret_crystal_path[-1].append(letters(b)) # Append the rank self.cur_dims.pop(0) # Pop off the leading column # Basic check to make sure we end with the empty configuration #tot_len = sum([len(rp) for rp in self.cur_partitions]) #if tot_len != 0: # print "Invalid bijection end for:" # print self.rigged_con # print "-----------------------" # print self.cur_partitions # raise ValueError("Invalid bijection end") return self.KRT(pathlist=ret_crystal_path)
def run(self, verbose=False): """ Run the bijection from rigged configurations to tensor product of KR tableaux for type `D_{n+1}^{(2)}`. INPUT: - ``verbose`` -- (Default: ``False``) Display each step in the bijection EXAMPLES:: sage: RC = RiggedConfigurations(['D', 4, 2], [[3, 1]]) sage: from sage.combinat.rigged_configurations.bij_type_D_twisted import RCToKRTBijectionTypeDTwisted sage: RCToKRTBijectionTypeDTwisted(RC(partition_list=[[],[1],[1]])).run() [[1], [3], [-2]] """ from sage.combinat.crystals.letters import CrystalOfLetters letters = CrystalOfLetters(self.rigged_con.parent()._cartan_type.classical()) # This is technically bad, but because the first thing we do is append # an empty list to ret_crystal_path, we correct this. We do it this # way so that we do not have to remove an empty list after the # bijection has been performed. ret_crystal_path = [] for dim in self.rigged_con.parent().dims: ret_crystal_path.append([]) # Iterate over each column for dummy_var in range(dim[1]): # Split off a new column if necessary if self.cur_dims[0][1] > 1: self.cur_dims[0][1] -= 1 self.cur_dims.insert(0, [dim[0], 1]) # Perform the corresponding splitting map on rigged configurations # All it does is update the vacancy numbers on the RC side for a in range(self.n): self._update_vacancy_numbers(a) # Check to see if we are a spinor if dim[0] == self.n: if verbose: print("====================") print(repr(self.rigged_con.parent()(*self.cur_partitions))) print("--------------------") print(ret_crystal_path) print("--------------------\n") print("Applying doubling map") self.doubling_map() while self.cur_dims[0][0] > 0: if verbose: print("====================") print(repr(self.rigged_con.parent()(*self.cur_partitions))) print("--------------------") print(ret_crystal_path) print("--------------------\n") self.cur_dims[0][0] -= 1 # This takes care of the indexing b = self.next_state(self.cur_dims[0][0]) # Make sure we have a crystal letter ret_crystal_path[-1].append(letters(b)) # Append the rank self.cur_dims.pop(0) # Pop off the leading column # Check to see if we were a spinor if dim[0] == self.n: if verbose: print("====================") print(repr(self.rigged_con.parent()(*self.cur_partitions))) print("--------------------") print(ret_crystal_path) print("--------------------\n") print("Applying halving map") self.halving_map() return self.KRT(pathlist=ret_crystal_path)
class AbstractTensorProductOfKRTableaux(FullTensorProductOfCrystals): r""" Abstract class for all of tensor product of KR tableaux of a given Cartan type. See :class:`TensorProductOfKirillovReshetikhinTableaux`. This class should never be created directly. """ def __init__(self, cartan_type, B, biject_class): r""" Construct a tensor product of KR tableaux. INPUT: - ``cartan_type`` -- The crystal type and n value - ``B`` -- An (ordered) list of dimensions - ``biject_class`` -- The class the bijection creates The dimensions (i.e. `B`) is a list whose entries are lists of the form `[r, s]` which correspond to a tableau with `r` rows and `s` columns (or of shape `[r]*s`) and corresponds to a Kirillov-Reshetikhin crystal `B^{r,s}`. TESTS:: sage: HW = HighestWeightTensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[3,1], [2,2]]); HW # indirect doctest Highest weight tensor product of Kirillov-Reshetikhin tableaux of type ['A', 3, 1] and tableau shape(s) [[1, 1, 1], [2, 2]] """ assert cartan_type.is_affine() self.affine_ct = cartan_type self.dims = B self.letters = CrystalOfLetters(cartan_type) self._bijection_class = biject_class tensorProd = [] for rectDims in B: tensorProd.append( KirillovReshetikhinTableaux(self.letters.cartan_type(), rectDims[0], rectDims[1])) FullTensorProductOfCrystals.__init__(self, tuple(tensorProd)) def _highest_weight_iter(self): r""" Iterate through all of the highest weight tensor product of Kirillov-Reshetikhin tableaux. EXAMPLES:: sage: HW = HighestWeightTensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[3,1], [2,1]]) sage: list(HW) # indirect doctest [[[1], [2], [3]] (X) [[1], [2]], [[1], [3], [4]] (X) [[1], [2]]] sage: HW = HighestWeightTensorProductOfKirillovReshetikhinTableaux(['D', 4, 1], [[2,1]]) sage: for x in HW: x # indirect doctest ... [[1], [2]] [[1], [-1]] """ # This is a hack solution since during construction, the bijection will # (attempt to) create a new KRT object which hasn't been fully created # and stored in the UniqueRepresentation's cache. So this will be # called again, causing the cycle to repeat. This hack just passes # our self as an optional argument to hide it from the end-user and # so we don't try to create a new KRT object. from sage.combinat.rigged_configurations.rigged_configurations import HighestWeightRiggedConfigurations for x in HighestWeightRiggedConfigurations(self.affine_ct, self.dims): yield x.to_tensor_product_of_Kirillov_Reshetikhin_tableaux( KRT_init_hack=self) def _element_constructor_(self, *path, **options): r""" Construct a TensorProductOfKRTableauxElement. Typically the user will call this with the option **pathlist** which will receive a list and coerce it into a path. EXAMPLES:: sage: KRT = TensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[3,1], [2,1]]) sage: KRT(pathlist=[[4, 2, 1], [2, 1]]) # indirect doctest [[1], [2], [4]] (X) [[1], [2]] """ from sage.combinat.crystals.kirillov_reshetikhin import KirillovReshetikhinGenericCrystalElement if isinstance(path[0], KirillovReshetikhinGenericCrystalElement): return self.element_class( self, *[x.to_Kirillov_Reshetikhin_tableau() for x in path]) from sage.combinat.crystals.tensor_product import TensorProductOfCrystalsElement if isinstance(path[0], TensorProductOfCrystalsElement) and \ isinstance(path[0][0], KirillovReshetikhinGenericCrystalElement): return self.element_class( self, *[x.to_Kirillov_Reshetikhin_tableau() for x in path[0]]) from sage.combinat.rigged_configurations.rigged_configuration_element import RiggedConfigurationElement if isinstance(path[0], RiggedConfigurationElement): if self.rigged_configurations() != path[0].parent(): raise ValueError("Incorrect bijection image.") return path[0].to_tensor_product_of_Kirillov_Reshetikhin_tableaux() return self.element_class(self, *path, **options) def _convert_to_letters(self, index, tableauList): """ Convert the entries of the list to a list of letters. This is a helper function to convert the list of ints to letters since we do not convert an int to an Integer at compile time. TESTS:: sage: KRT = TensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[1,3]]) sage: L = KRT._convert_to_letters(0, [3, 2, 2]); L [3, 2, 2] sage: type(L[0]) <class 'sage.combinat.crystals.letters.ClassicalCrystalOfLetters_with_category.element_class'> sage: L[0].value 3 """ return ([self.letters(x) for x in tableauList]) def rigged_configurations(self): """ Return the corresponding set of rigged configurations. EXAMPLES:: sage: KRT = TensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[1,3], [2,1]]) sage: KRT.rigged_configurations() Rigged configurations of type ['A', 3, 1] and factors ((1, 3), (2, 1)) """ return self._bijection_class(self.affine_ct, self.dims) def list(self): r""" Create a list of the elements by using the iterator. TESTS:: sage: HW = HighestWeightTensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[3,1], [2,1]]) sage: HW.list() [[[1], [2], [3]] (X) [[1], [2]], [[1], [3], [4]] (X) [[1], [2]]] """ # This is needed to overwrite the list method from the FiniteCrystals # category which generates the list via f_a applications. return [x for x in self]
def run(self, verbose=False, build_graph=False): """ Run the bijection from rigged configurations to tensor product of KR tableaux for type `D_n^{(1)}`. INPUT: - ``verbose`` -- (default: ``False``) display each step in the bijection - ``build_graph`` -- (default: ``False``) build the graph of each step of the bijection EXAMPLES:: sage: RC = RiggedConfigurations(['D', 4, 1], [[2, 1]]) sage: x = RC(partition_list=[[1],[1],[1],[1]]) sage: from sage.combinat.rigged_configurations.bij_type_D import RCToKRTBijectionTypeD sage: RCToKRTBijectionTypeD(x).run() [[2], [-3]] sage: bij = RCToKRTBijectionTypeD(x) sage: bij.run(build_graph=True) [[2], [-3]] sage: bij._graph Digraph on 3 vertices """ from sage.combinat.crystals.letters import CrystalOfLetters letters = CrystalOfLetters( self.rigged_con.parent()._cartan_type.classical()) # This is technically bad, but because the first thing we do is append # an empty list to ret_crystal_path, we correct this. We do it this # way so that we do not have to remove an empty list after the # bijection has been performed. ret_crystal_path = [] for dim in self.rigged_con.parent().dims: ret_crystal_path.append([]) # Iterate over each column for dummy_var in range(dim[1]): # Split off a new column if necessary if self.cur_dims[0][1] > 1: self.cur_dims[0][1] -= 1 self.cur_dims.insert(0, [dim[0], 1]) # Perform the corresponding splitting map on rigged configurations # All it does is update the vacancy numbers on the RC side for a in range(self.n): self._update_vacancy_numbers(a) if build_graph: y = self.rigged_con.parent()( *[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True) self._graph.append( [self._graph[-1][1], (y, len(self._graph)), 'ls']) # Check to see if we are a spinor if dim[0] >= self.n - 1: if verbose: print("====================") print( repr(self.rigged_con.parent()( *self.cur_partitions, use_vacancy_numbers=True))) print("--------------------") print(ret_crystal_path) print("--------------------\n") print("Applying doubling map") self.doubling_map() if build_graph: y = self.rigged_con.parent()( *[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True) self._graph.append( [self._graph[-1][1], (y, len(self._graph)), '2x']) if dim[0] == self.n - 1: if verbose: print("====================") print( repr(self.rigged_con.parent()( *self.cur_partitions, use_vacancy_numbers=True))) print("--------------------") print(ret_crystal_path) print("--------------------\n") b = self.next_state(self.n) if b == self.n: b = -self.n ret_crystal_path[-1].append( letters(b)) # Append the rank if build_graph: y = self.rigged_con.parent()( *[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True) self._graph.append([ self._graph[-1][1], (y, len(self._graph)), letters(b) ]) while self.cur_dims[0][0] > 0: if verbose: print("====================") print( repr(self.rigged_con.parent()( *self.cur_partitions, use_vacancy_numbers=True))) print("--------------------") print(ret_crystal_path) print("--------------------\n") self.cur_dims[0][0] -= 1 # This takes care of the indexing b = self.next_state(self.cur_dims[0][0]) # Corrections for spinor if dim[0] == self.n and b == -self.n \ and self.cur_dims[0][0] == self.n - 1: b = -(self.n - 1) # Make sure we have a crystal letter ret_crystal_path[-1].append(letters(b)) # Append the rank if build_graph: y = self.rigged_con.parent()( *[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True) self._graph.append([ self._graph[-1][1], (y, len(self._graph)), letters(b) ]) self.cur_dims.pop(0) # Pop off the leading column # Check to see if we were a spinor if dim[0] >= self.n - 1: if verbose: print("====================") print( repr(self.rigged_con.parent()( *self.cur_partitions, use_vacancy_numbers=True))) print("--------------------") print(ret_crystal_path) print("--------------------\n") print("Applying halving map") self.halving_map() if build_graph: y = self.rigged_con.parent()( *[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True) self._graph.append([ self._graph[-1][1], (y, len(self._graph)), '1/2x' ]) if build_graph: self._graph.pop(0) # Remove the dummy at the start from sage.graphs.digraph import DiGraph from sage.graphs.dot2tex_utils import have_dot2tex self._graph = DiGraph(self._graph, format="list_of_edges") if have_dot2tex(): self._graph.set_latex_options(format="dot2tex", edge_labels=True) return self.KRT(pathlist=ret_crystal_path)
class AbstractTensorProductOfKRTableaux(FullTensorProductOfCrystals): r""" Abstract class for all of tensor product of KR tableaux of a given Cartan type. See :class:`TensorProductOfKirillovReshetikhinTableaux`. This class should never be created directly. """ def __init__(self, cartan_type, B, biject_class): r""" Construct a tensor product of KR tableaux. INPUT: - ``cartan_type`` -- The crystal type and n value - ``B`` -- An (ordered) list of dimensions - ``biject_class`` -- The class the bijection creates The dimensions (i.e. `B`) is a list whose entries are lists of the form `[r, s]` which correspond to a tableau with `r` rows and `s` columns (or of shape `[r]*s`) and corresponds to a Kirillov-Reshetikhin crystal `B^{r,s}`. TESTS:: sage: HW = HighestWeightTensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[3,1], [2,2]]); HW # indirect doctest Highest weight tensor product of Kirillov-Reshetikhin tableaux of type ['A', 3, 1] and tableau shape(s) [[1, 1, 1], [2, 2]] """ assert cartan_type.is_affine() self.affine_ct = cartan_type self.dims = B self.letters = CrystalOfLetters(cartan_type) self._bijection_class = biject_class tensorProd = [] for rectDims in B: tensorProd.append(KirillovReshetikhinTableaux( self.letters.cartan_type(), rectDims[0], rectDims[1])) FullTensorProductOfCrystals.__init__(self, tuple(tensorProd)) def _highest_weight_iter(self): r""" Iterate through all of the highest weight tensor product of Kirillov-Reshetikhin tableaux. EXAMPLES:: sage: HW = HighestWeightTensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[3,1], [2,1]]) sage: list(HW) # indirect doctest [[[1], [2], [3]] (X) [[1], [2]], [[1], [3], [4]] (X) [[1], [2]]] sage: HW = HighestWeightTensorProductOfKirillovReshetikhinTableaux(['D', 4, 1], [[2,1]]) sage: for x in HW: x # indirect doctest ... [[1], [2]] [[1], [-1]] """ # This is a hack solution since during construction, the bijection will # (attempt to) create a new KRT object which hasn't been fully created # and stored in the UniqueRepresentation's cache. So this will be # called again, causing the cycle to repeat. This hack just passes # our self as an optional argument to hide it from the end-user and # so we don't try to create a new KRT object. from sage.combinat.rigged_configurations.rigged_configurations import HighestWeightRiggedConfigurations for x in HighestWeightRiggedConfigurations(self.affine_ct, self.dims): yield x.to_tensor_product_of_Kirillov_Reshetikhin_tableaux(KRT_init_hack=self) def _element_constructor_(self, *path, **options): r""" Construct a TensorProductOfKRTableauxElement. Typically the user will call this with the option **pathlist** which will receive a list and coerce it into a path. EXAMPLES:: sage: KRT = TensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[3,1], [2,1]]) sage: KRT(pathlist=[[4, 2, 1], [2, 1]]) # indirect doctest [[1], [2], [4]] (X) [[1], [2]] """ from sage.combinat.crystals.kirillov_reshetikhin import KirillovReshetikhinGenericCrystalElement if isinstance(path[0], KirillovReshetikhinGenericCrystalElement): return self.element_class(self, *[x.to_Kirillov_Reshetikhin_tableau() for x in path]) from sage.combinat.crystals.tensor_product import TensorProductOfCrystalsElement if isinstance(path[0], TensorProductOfCrystalsElement) and \ isinstance(path[0][0], KirillovReshetikhinGenericCrystalElement): return self.element_class(self, *[x.to_Kirillov_Reshetikhin_tableau() for x in path[0]]) from sage.combinat.rigged_configurations.rigged_configuration_element import RiggedConfigurationElement if isinstance(path[0], RiggedConfigurationElement): if self.rigged_configurations() != path[0].parent(): raise ValueError("Incorrect bijection image.") return path[0].to_tensor_product_of_Kirillov_Reshetikhin_tableaux() return self.element_class(self, *path, **options) def _convert_to_letters(self, index, tableauList): """ Convert the entries of the list to a list of letters. This is a helper function to convert the list of ints to letters since we do not convert an int to an Integer at compile time. TESTS:: sage: KRT = TensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[1,3]]) sage: L = KRT._convert_to_letters(0, [3, 2, 2]); L [3, 2, 2] sage: type(L[0]) <class 'sage.combinat.crystals.letters.ClassicalCrystalOfLetters_with_category.element_class'> sage: L[0].value 3 """ return([self.letters(x) for x in tableauList]) def rigged_configurations(self): """ Return the corresponding set of rigged configurations. EXAMPLES:: sage: KRT = TensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[1,3], [2,1]]) sage: KRT.rigged_configurations() Rigged configurations of type ['A', 3, 1] and factors ((1, 3), (2, 1)) """ return self._bijection_class(self.affine_ct, self.dims) def list(self): r""" Create a list of the elements by using the iterator. TESTS:: sage: HW = HighestWeightTensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[3,1], [2,1]]) sage: HW.list() [[[1], [2], [3]] (X) [[1], [2]], [[1], [3], [4]] (X) [[1], [2]]] """ # This is needed to overwrite the list method from the FiniteCrystals # category which generates the list via f_a applications. return [x for x in self]
def run(self, verbose=False): """ Run the bijection from rigged configurations to tensor product of KR tableaux for type `B_n^{(1)}`. INPUT: - ``verbose`` -- (Default: ``False``) Display each step in the bijection EXAMPLES:: sage: RC = RiggedConfigurations(['B', 3, 1], [[2, 1]]) sage: from sage.combinat.rigged_configurations.bij_type_B import RCToKRTBijectionTypeB sage: RCToKRTBijectionTypeB(RC(partition_list=[[1],[1,1],[1]])).run() [[3], [0]] sage: RC = RiggedConfigurations(['B', 3, 1], [[3, 1]]) sage: from sage.combinat.rigged_configurations.bij_type_B import RCToKRTBijectionTypeB sage: RCToKRTBijectionTypeB(RC(partition_list=[[],[1],[1]])).run() [[1], [3], [-2]] """ from sage.combinat.crystals.letters import CrystalOfLetters letters = CrystalOfLetters( self.rigged_con.parent()._cartan_type.classical()) # This is technically bad, but because the first thing we do is append # an empty list to ret_crystal_path, we correct this. We do it this # way so that we do not have to remove an empty list after the # bijection has been performed. ret_crystal_path = [] for dim in self.rigged_con.parent().dims: ret_crystal_path.append([]) # Check to see if we are a spinor if dim[0] == self.n: # Perform the spinor bijection by converting to type A_{2n-1}^{(2)} # doing the bijection there and pulling back from sage.combinat.rigged_configurations.bij_type_A2_odd import RCToKRTBijectionTypeA2Odd from sage.combinat.rigged_configurations.rigged_configurations import RiggedConfigurations from sage.combinat.rigged_configurations.rigged_partition import RiggedPartition, RiggedPartitionTypeB # Convert to a type A_{2n-1}^{(2)} RC RC = RiggedConfigurations(['A', 2 * self.n - 1, 2], self.cur_dims) if verbose: print("====================") print(repr(RC(*self.cur_partitions))) print("--------------------") print(ret_crystal_path) print("--------------------\n") print("Applying doubling map\n") # Convert the n-th partition into a regular rigged partition self.cur_partitions[-1] = RiggedPartition( self.cur_partitions[-1]._list, self.cur_partitions[-1].rigging, self.cur_partitions[-1].vacancy_numbers) bij = RCToKRTBijectionTypeA2Odd(RC(*self.cur_partitions)) for i in range(len(self.cur_dims)): if bij.cur_dims[i][0] != self.n: bij.cur_dims[i][1] *= 2 for i in range(self.n - 1): for j in range(len(bij.cur_partitions[i])): bij.cur_partitions[i]._list[j] *= 2 bij.cur_partitions[i].rigging[j] *= 2 bij.cur_partitions[i].vacancy_numbers[j] *= 2 # Perform the type A_{2n-1}^{(2)} bijection # Iterate over each column for dummy_var in range(dim[1]): # Split off a new column if necessary if bij.cur_dims[0][1] > 1: bij.cur_dims[0][1] -= 1 bij.cur_dims.insert(0, [dim[0], 1]) # Perform the corresponding splitting map on rigged configurations # All it does is update the vacancy numbers on the RC side for a in range(self.n): bij._update_vacancy_numbers(a) while bij.cur_dims[0][0] > 0: if verbose: print("====================") print(repr(RC(*bij.cur_partitions))) print("--------------------") print(ret_crystal_path) print("--------------------\n") bij.cur_dims[0][ 0] -= 1 # This takes care of the indexing b = bij.next_state(bij.cur_dims[0][0]) # Make sure we have a crystal letter ret_crystal_path[-1].append( letters(b)) # Append the rank bij.cur_dims.pop(0) # Pop off the leading column self.cur_dims.pop(0) # Pop off the spin rectangle self.cur_partitions = bij.cur_partitions # Convert the n-th partition back into the special type B one self.cur_partitions[-1] = RiggedPartitionTypeB( self.cur_partitions[-1]) # Convert back to a type B_n^{(1)} if verbose: print("====================") print(repr(self.rigged_con.parent()(*bij.cur_partitions))) print("--------------------") print(ret_crystal_path) print("--------------------\n") print("Applying halving map\n") for i in range(self.n - 1): for j in range(len(self.cur_partitions[i])): self.cur_partitions[i]._list[j] //= 2 self.cur_partitions[i].rigging[j] //= 2 self.cur_partitions[i].vacancy_numbers[j] //= 2 else: # Perform the regular type B_n^{(1)} bijection # Iterate over each column for dummy_var in range(dim[1]): # Split off a new column if necessary if self.cur_dims[0][1] > 1: if verbose: print("====================") print( repr(self.rigged_con.parent()( *self.cur_partitions))) print("--------------------") print(ret_crystal_path) print("--------------------\n") print("Applying column split") self.cur_dims[0][1] -= 1 self.cur_dims.insert(0, [dim[0], 1]) # Perform the corresponding splitting map on rigged configurations # All it does is update the vacancy numbers on the RC side for a in range(self.n): self._update_vacancy_numbers(a) while self.cur_dims[0][0] > 0: if verbose: print("====================") print( repr(self.rigged_con.parent()( *self.cur_partitions))) print("--------------------") print(ret_crystal_path) print("--------------------\n") self.cur_dims[0][ 0] -= 1 # This takes care of the indexing b = self.next_state(self.cur_dims[0][0]) # Make sure we have a crystal letter ret_crystal_path[-1].append( letters(b)) # Append the rank self.cur_dims.pop(0) # Pop off the leading column return self.KRT(pathlist=ret_crystal_path)