def _call_(self, x): r""" Return the image of ``x`` in the rigged configuration model of `B(\infty)`. EXAMPLES:: sage: RC = crystals.infinity.RiggedConfigurations(['A',3]) sage: T = crystals.infinity.Tableaux(['A',3]) sage: phi = RC.coerce_map_from(T) sage: x = T.an_element().f_string([2,2,1,1,3,2,1,2,1,3]) sage: y = phi(x); ascii_art(y) -4[ ][ ][ ][ ]-2 -3[ ][ ][ ]-1 -1[ ][ ]-1 -2[ ]-1 sage: (~phi)(y) == x True """ conj = x.to_tableau().conjugate() ct = self.domain().cartan_type() act = ct.affine() TP = TensorProductOfKirillovReshetikhinTableaux(act, [[r,1] for r in conj.shape()]) elt = TP(pathlist=[reversed(row) for row in conj]) if ct.type() == 'A': bij = KRTToRCBijectionTypeA(elt) elif ct.type() == 'B': bij = MLTToRCBijectionTypeB(elt) elif ct.type() == 'C': bij = KRTToRCBijectionTypeC(elt) elif ct.type() == 'D': bij = MLTToRCBijectionTypeD(elt) else: raise NotImplementedError("bijection of type {} not yet implemented".format(ct)) return self.codomain()(bij.run())
def left_split(self): r""" Return the image of ``self`` under the left column splitting map. EXAMPLES:: sage: KRT = crystals.TensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[2,2],[1,3]]) sage: elt = KRT(pathlist=[[2,1,3,2],[1,4,4]]); elt.pp() 1 2 (X) 1 4 4 2 3 sage: elt.left_split().pp() 1 (X) 2 (X) 1 4 4 2 3 """ P = self.parent() if P.dims[0][1] == 1: raise ValueError("cannot split a single column") r, s = P.dims[0] B = [[r, 1], [r, s - 1]] B.extend(P.dims[1:]) from sage.combinat.rigged_configurations.tensor_product_kr_tableaux \ import TensorProductOfKirillovReshetikhinTableaux TP = TensorProductOfKirillovReshetikhinTableaux(P._cartan_type, B) x = self[0].left_split() return TP(*(list(x) + self[1:]))
def right_split(self): r""" Return the image of ``self`` under the right column splitting map. EXAMPLES:: sage: KRT = crystals.TensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[2,2],[1,3]]) sage: elt = KRT(pathlist=[[2,1,3,2],[1,4,4]]); elt.pp() 1 2 (X) 1 4 4 2 3 sage: elt.right_split().pp() 1 2 (X) 1 4 (X) 4 2 3 Let `\ast` denote the :meth:`Lusztig involution<lusztig_involution>`, we check that `\ast \circ \mathrm{ls} \circ \ast = \mathrm{rs}`:: sage: all(x.lusztig_involution().left_split().lusztig_involution() == x.right_split() for x in KRT) True """ P = self.parent() if P.dims[-1][1] == 1: raise ValueError("cannot split a single column") r, s = P.dims[-1] B = list(P.dims[:-1]) B.append([r, s - 1]) B.append([r, 1]) from sage.combinat.rigged_configurations.tensor_product_kr_tableaux \ import TensorProductOfKirillovReshetikhinTableaux TP = TensorProductOfKirillovReshetikhinTableaux(P._cartan_type, B) x = self[-1].right_split() return TP(*(self[:-1] + list(x)))
def __init__(self, initial_state, cartan_type=2, vacuum=1): """ Initialize ``self``. EXAMPLES:: sage: B = SolitonCellularAutomata('3411111122411112223', 4) sage: TestSuite(B).run() """ if cartan_type in ZZ: cartan_type = CartanType(['A', cartan_type - 1, 1]) else: cartan_type = CartanType(cartan_type) self._cartan_type = cartan_type self._vacuum = vacuum K = KirillovReshetikhinTableaux(self._cartan_type, self._vacuum, 1) try: # FIXME: the maximal_vector() does not work in type E and F self._vacuum_elt = K.maximal_vector() except (ValueError, TypeError, AttributeError): self._vacuum_elt = K.module_generators[0] if isinstance(initial_state, str): # We consider things 1-9 initial_state = [[ZZ(x) if x != '.' else ZZ.one()] for x in initial_state] try: KRT = TensorProductOfKirillovReshetikhinTableaux( self._cartan_type, [[vacuum, len(st) // vacuum] for st in initial_state]) self._states = [KRT(pathlist=initial_state)] except TypeError: KRT = TensorProductOfKirillovReshetikhinTableaux( self._cartan_type, [[vacuum, 1] for st in initial_state]) self._states = [KRT(*initial_state)] self._evolutions = [] self._nballs = len(self._states[0])
def lusztig_involution(self): r""" Return the result of the classical Lusztig involution on ``self``. EXAMPLES:: sage: KRT = crystals.TensorProductOfKirillovReshetikhinTableaux(['A',3,1], [[2,2],[1,3]]) sage: elt = KRT(pathlist=[[2,1,3,2],[1,4,4]]) sage: li = elt.lusztig_involution(); li [[1, 1, 4]] (X) [[2, 3], [3, 4]] sage: li.parent() Tensor product of Kirillov-Reshetikhin tableaux of type ['A', 3, 1] and factor(s) ((1, 3), (2, 2)) """ from sage.combinat.rigged_configurations.tensor_product_kr_tableaux \ import TensorProductOfKirillovReshetikhinTableaux P = self.parent() P = TensorProductOfKirillovReshetikhinTableaux(P._cartan_type, reversed(P.dims)) return P(*[x.lusztig_involution() for x in reversed(self)])
def run(self, verbose=False): """ Run the bijection from a tensor product of KR tableaux to a rigged configuration. INPUT: - ``tp_krt`` -- A tensor product of KR tableaux - ``verbose`` -- (Default: ``False``) Display each step in the bijection EXAMPLES:: sage: from sage.combinat.rigged_configurations.bij_type_B import KRTToRCBijectionTypeB sage: KRT = TensorProductOfKirillovReshetikhinTableaux(['B', 3, 1], [[2, 1]]) sage: KRTToRCBijectionTypeB(KRT(pathlist=[[0,3]])).run() <BLANKLINE> 0[ ]0 <BLANKLINE> -1[ ]-1 -1[ ]-1 <BLANKLINE> 0[]0 <BLANKLINE> sage: KRT = TensorProductOfKirillovReshetikhinTableaux(['B', 3, 1], [[3, 1]]) sage: KRTToRCBijectionTypeB(KRT(pathlist=[[-2,3,1]])).run() <BLANKLINE> (/) <BLANKLINE> -1[ ]-1 <BLANKLINE> 0[]0 <BLANKLINE> """ if verbose: from sage.combinat.rigged_configurations.tensor_product_kr_tableaux_element \ import TensorProductOfKirillovReshetikhinTableauxElement for cur_crystal in reversed(self.tp_krt): r = cur_crystal.parent().r() # Check if it is a spinor if r == 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 KRTToRCBijectionTypeA2Odd from sage.combinat.rigged_configurations.tensor_product_kr_tableaux import TensorProductOfKirillovReshetikhinTableaux from sage.combinat.rigged_configurations.rigged_partition import RiggedPartition if verbose: print "====================" if len(self.cur_path) == 0: print(repr([])) # Special case for displaying when the rightmost factor is a spinor else: print(repr(TensorProductOfKirillovReshetikhinTableauxElement(self.tp_krt.parent(), self.cur_path))) print("--------------------") print(repr(self.ret_rig_con)) print("--------------------\n") print("Applying doubling map") # Convert to a type A_{2n-1}^{(2)} RC dims = self.cur_dims[:] dims.insert(0, [r, cur_crystal.parent().s()]) KRT = TensorProductOfKirillovReshetikhinTableaux(['A', 2*self.n-1, 2], dims) # Convert the n-th partition into a regular rigged partition self.ret_rig_con[-1] = RiggedPartition(self.ret_rig_con[-1]._list, self.ret_rig_con[-1].rigging, self.ret_rig_con[-1].vacancy_numbers) bij = KRTToRCBijectionTypeA2Odd(KRT.module_generators[0]) # Placeholder element bij.ret_rig_con = KRT.rigged_configurations()(*self.ret_rig_con) bij.cur_path = self.cur_path bij.cur_dims = self.cur_dims 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.ret_rig_con[i])): bij.ret_rig_con[i]._list[j] *= 2 bij.ret_rig_con[i].rigging[j] *= 2 bij.ret_rig_con[i].vacancy_numbers[j] *= 2 # Perform the type A_{2n-1}^{(2)} bijection r = cur_crystal.parent().r() # Iterate through the columns for col_number, cur_column in enumerate(reversed(cur_crystal.to_array(False))): bij.cur_path.insert(0, []) # Prepend an empty list bij.cur_dims.insert(0, [0, 1]) # Note that we do not need to worry about iterating over columns # (see previous note about the data structure). for letter in reversed(cur_column): bij.cur_dims[0][0] += 1 val = letter.value # Convert from a CrystalOfLetter to an Integer if verbose: print("====================") print(repr(TensorProductOfKirillovReshetikhinTableauxElement(self.tp_krt.parent(), bij.cur_path))) print("--------------------") print(repr(bij.ret_rig_con)) print("--------------------\n") # Build the next state bij.cur_path[0].insert(0, [letter]) # Prepend the value bij.next_state(val) # If we've split off a column, we need to merge the current column # to the current crystal tableau if col_number > 0: for i, letter_singleton in enumerate(self.cur_path[0]): bij.cur_path[1][i].insert(0, letter_singleton[0]) bij.cur_dims[1][1] += 1 bij.cur_path.pop(0) bij.cur_dims.pop(0) # And perform the inverse column splitting map on the RC for a in range(self.n): bij._update_vacancy_nums(a) if verbose: print("====================") print(repr(TensorProductOfKirillovReshetikhinTableauxElement(self.tp_krt.parent(), bij.cur_path))) print("--------------------") print(repr(bij.ret_rig_con)) print("--------------------\n") print("Applying halving map") # Convert back to a type B_n^{(1)} 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.ret_rig_con[i])): bij.ret_rig_con[i]._list[j] //= 2 bij.ret_rig_con[i].rigging[j] //= 2 bij.ret_rig_con[i].vacancy_numbers[j] //= 2 self.ret_rig_con = self.tp_krt.parent().rigged_configurations()(*bij.ret_rig_con) # Make it mutable so we don't have to keep making copies, at the # end of the bijection, we will make it immutable again self.ret_rig_con._set_mutable() else: # Perform the regular type B_n^{(1)} bijection # Iterate through the columns for col_number, cur_column in enumerate(reversed(cur_crystal.to_array(False))): self.cur_path.insert(0, []) # Prepend an empty list self.cur_dims.insert(0, [0, 1]) # Note that we do not need to worry about iterating over columns # (see previous note about the data structure). for letter in reversed(cur_column): self.cur_dims[0][0] += 1 val = letter.value # Convert from a CrystalOfLetter to an Integer if verbose: print("====================") print(repr(TensorProductOfKirillovReshetikhinTableauxElement(self.tp_krt.parent(), self.cur_path))) print("--------------------") print(repr(self.ret_rig_con)) print("--------------------\n") # Build the next state self.cur_path[0].insert(0, [letter]) # Prepend the value self.next_state(val) # If we've split off a column, we need to merge the current column # to the current crystal tableau if col_number > 0: if verbose: print("====================") print(repr(TensorProductOfKirillovReshetikhinTableauxElement(self.tp_krt.parent(), self.cur_path))) print("--------------------") print(repr(self.ret_rig_con)) print("--------------------\n") print("Applying column merge") for i, letter_singleton in enumerate(self.cur_path[0]): self.cur_path[1][i].insert(0, letter_singleton[0]) self.cur_dims[1][1] += 1 self.cur_path.pop(0) self.cur_dims.pop(0) # And perform the inverse column splitting map on the RC for a in range(self.n): self._update_vacancy_nums(a) self.ret_rig_con.set_immutable() # Return it to immutable return self.ret_rig_con
def run(self, verbose=False): """ Run the bijection from a tensor product of KR tableaux to a rigged configuration. INPUT: - ``tp_krt`` -- A tensor product of KR tableaux - ``verbose`` -- (Default: ``False``) Display each step in the bijection EXAMPLES:: sage: from sage.combinat.rigged_configurations.bij_type_B import KRTToRCBijectionTypeB sage: KRT = TensorProductOfKirillovReshetikhinTableaux(['B', 3, 1], [[2, 1]]) sage: KRTToRCBijectionTypeB(KRT(pathlist=[[0,3]])).run() <BLANKLINE> 0[ ]0 <BLANKLINE> -1[ ]-1 -1[ ]-1 <BLANKLINE> 0[]0 <BLANKLINE> sage: KRT = TensorProductOfKirillovReshetikhinTableaux(['B', 3, 1], [[3, 1]]) sage: KRTToRCBijectionTypeB(KRT(pathlist=[[-2,3,1]])).run() <BLANKLINE> (/) <BLANKLINE> -1[ ]-1 <BLANKLINE> 0[]0 <BLANKLINE> """ if verbose: from sage.combinat.rigged_configurations.tensor_product_kr_tableaux_element \ import TensorProductOfKirillovReshetikhinTableauxElement for cur_crystal in reversed(self.tp_krt): r = cur_crystal.parent().r() # Check if it is a spinor if r == 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 KRTToRCBijectionTypeA2Odd from sage.combinat.rigged_configurations.tensor_product_kr_tableaux import TensorProductOfKirillovReshetikhinTableaux from sage.combinat.rigged_configurations.rigged_partition import RiggedPartition if verbose: print "====================" if len(self.cur_path) == 0: print( repr([]) ) # Special case for displaying when the rightmost factor is a spinor else: print( repr( TensorProductOfKirillovReshetikhinTableauxElement( self.tp_krt.parent(), self.cur_path))) print("--------------------") print(repr(self.ret_rig_con)) print("--------------------\n") print("Applying doubling map") # Convert to a type A_{2n-1}^{(2)} RC dims = self.cur_dims[:] dims.insert(0, [r, cur_crystal.parent().s()]) KRT = TensorProductOfKirillovReshetikhinTableaux( ['A', 2 * self.n - 1, 2], dims) # Convert the n-th partition into a regular rigged partition self.ret_rig_con[-1] = RiggedPartition( self.ret_rig_con[-1]._list, self.ret_rig_con[-1].rigging, self.ret_rig_con[-1].vacancy_numbers) bij = KRTToRCBijectionTypeA2Odd( KRT.module_generators[0]) # Placeholder element bij.ret_rig_con = KRT.rigged_configurations()( *self.ret_rig_con) bij.cur_path = self.cur_path bij.cur_dims = self.cur_dims 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.ret_rig_con[i])): bij.ret_rig_con[i]._list[j] *= 2 bij.ret_rig_con[i].rigging[j] *= 2 bij.ret_rig_con[i].vacancy_numbers[j] *= 2 # Perform the type A_{2n-1}^{(2)} bijection r = cur_crystal.parent().r() # Iterate through the columns for col_number, cur_column in enumerate( reversed(cur_crystal.to_array(False))): bij.cur_path.insert(0, []) # Prepend an empty list bij.cur_dims.insert(0, [0, 1]) # Note that we do not need to worry about iterating over columns # (see previous note about the data structure). for letter in reversed(cur_column): bij.cur_dims[0][0] += 1 val = letter.value # Convert from a CrystalOfLetter to an Integer if verbose: print("====================") print( repr( TensorProductOfKirillovReshetikhinTableauxElement( self.tp_krt.parent(), bij.cur_path))) print("--------------------") print(repr(bij.ret_rig_con)) print("--------------------\n") # Build the next state bij.cur_path[0].insert(0, [letter]) # Prepend the value bij.next_state(val) # If we've split off a column, we need to merge the current column # to the current crystal tableau if col_number > 0: for i, letter_singleton in enumerate(self.cur_path[0]): bij.cur_path[1][i].insert(0, letter_singleton[0]) bij.cur_dims[1][1] += 1 bij.cur_path.pop(0) bij.cur_dims.pop(0) # And perform the inverse column splitting map on the RC for a in range(self.n): bij._update_vacancy_nums(a) if verbose: print("====================") print( repr( TensorProductOfKirillovReshetikhinTableauxElement( self.tp_krt.parent(), bij.cur_path))) print("--------------------") print(repr(bij.ret_rig_con)) print("--------------------\n") print("Applying halving map") # Convert back to a type B_n^{(1)} 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.ret_rig_con[i])): bij.ret_rig_con[i]._list[j] //= 2 bij.ret_rig_con[i].rigging[j] //= 2 bij.ret_rig_con[i].vacancy_numbers[j] //= 2 self.ret_rig_con = self.tp_krt.parent().rigged_configurations( )(*bij.ret_rig_con) # Make it mutable so we don't have to keep making copies, at the # end of the bijection, we will make it immutable again self.ret_rig_con._set_mutable() else: # Perform the regular type B_n^{(1)} bijection # Iterate through the columns for col_number, cur_column in enumerate( reversed(cur_crystal.to_array(False))): self.cur_path.insert(0, []) # Prepend an empty list self.cur_dims.insert(0, [0, 1]) # Note that we do not need to worry about iterating over columns # (see previous note about the data structure). for letter in reversed(cur_column): self.cur_dims[0][0] += 1 val = letter.value # Convert from a CrystalOfLetter to an Integer if verbose: print("====================") print( repr( TensorProductOfKirillovReshetikhinTableauxElement( self.tp_krt.parent(), self.cur_path))) print("--------------------") print(repr(self.ret_rig_con)) print("--------------------\n") # Build the next state self.cur_path[0].insert(0, [letter]) # Prepend the value self.next_state(val) # If we've split off a column, we need to merge the current column # to the current crystal tableau if col_number > 0: if verbose: print("====================") print( repr( TensorProductOfKirillovReshetikhinTableauxElement( self.tp_krt.parent(), self.cur_path))) print("--------------------") print(repr(self.ret_rig_con)) print("--------------------\n") print("Applying column merge") for i, letter_singleton in enumerate(self.cur_path[0]): self.cur_path[1][i].insert(0, letter_singleton[0]) self.cur_dims[1][1] += 1 self.cur_path.pop(0) self.cur_dims.pop(0) # And perform the inverse column splitting map on the RC for a in range(self.n): self._update_vacancy_nums(a) self.ret_rig_con.set_immutable() # Return it to immutable return self.ret_rig_con
def evolve(self, carrier_capacity=None, carrier_index=None, number=None): """ Evolve ``self``. Time evolution `T_s` of a SCA state `p` is determined by .. MATH:: u_{r,s} \otimes T_s(p) = R(p \otimes u_{r,s}), where `u_{r,s}` is the maximal element of `B^{r,s}`. INPUT: - ``carrier_capacity`` -- (default: the number of balls in the system) the size `s` of carrier - ``carrier_index`` -- (default: the vacuum index) the index `r` of the carrier - ``number`` -- (optional) the number of times to perform the evolutions To perform multiple evolutions of the SCA, ``carrier_capacity`` and ``carrier_index`` may be lists of the same length. EXAMPLES:: sage: B = SolitonCellularAutomata('3411111122411112223', 4) sage: for k in range(10): ....: B.evolve() sage: B Soliton cellular automata of type ['A', 3, 1] and vacuum = 1 initial state: 34......224....2223 evoltuions: [(1, 19), (1, 19), (1, 19), (1, 19), (1, 19), (1, 19), (1, 19), (1, 19), (1, 19), (1, 19)] current state: ......2344.......222....23............................... sage: B.reset() sage: B.evolve(number=10); B Soliton cellular automata of type ['A', 3, 1] and vacuum = 1 initial state: 34......224....2223 evoltuions: [(1, 19), (1, 19), (1, 19), (1, 19), (1, 19), (1, 19), (1, 19), (1, 19), (1, 19), (1, 19)] current state: ......2344.......222....23............................... sage: B.reset() sage: B.evolve(carrier_capacity=[1,2,3,4,5,6,7,8,9,10]); B Soliton cellular automata of type ['A', 3, 1] and vacuum = 1 initial state: 34......224....2223 evoltuions: [(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (1, 10)] current state: ........2344....222..23.............................. sage: B.reset() sage: B.evolve(carrier_index=[1,2,3]) Last carrier: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 4 4 sage: B Soliton cellular automata of type ['A', 3, 1] and vacuum = 1 initial state: 34......224....2223 evoltuions: [(1, 19), (2, 19), (3, 19)] current state: ..................................22......223...2222..... sage: B.reset() sage: B.evolve(carrier_capacity=[1,2,3], carrier_index=[1,2,3]) Last carrier: 1 1 3 4 Last carrier: 1 1 1 2 2 3 3 3 4 sage: B Soliton cellular automata of type ['A', 3, 1] and vacuum = 1 initial state: 34......224....2223 evoltuions: [(1, 1), (2, 2), (3, 3)] current state: .....22.......223....2222.. sage: B.reset() sage: B.evolve(1, 2, number=3) Last carrier: 1 3 Last carrier: 1 4 Last carrier: 1 3 sage: B Soliton cellular automata of type ['A', 3, 1] and vacuum = 1 initial state: 34......224....2223 evoltuions: [(2, 1), (2, 1), (2, 1)] current state: .24......222.....2222. """ if isinstance(carrier_capacity, (list, tuple)): if not isinstance(carrier_index, (list, tuple)): carrier_index = [carrier_index] * len(carrier_capacity) if len(carrier_index) != len(carrier_capacity): raise ValueError("carrier_index and carrier_capacity" " must have the same length") for i, r in zip(carrier_capacity, carrier_index): self.evolve(i, r) return if isinstance(carrier_index, (list, tuple)): # carrier_capacity must be not be a list/tuple if given for r in carrier_index: self.evolve(carrier_capacity, r) return if carrier_capacity is None: carrier_capacity = self._nballs if carrier_index is None: carrier_index = self._vacuum if number is not None: for k in range(number): self.evolve(carrier_capacity, carrier_index) return passed = False K = KirillovReshetikhinTableaux(self._cartan_type, carrier_index, carrier_capacity) try: # FIXME: the maximal_vector() does not work in type E and F empty_carrier = K.maximal_vector() except (ValueError, TypeError, AttributeError): empty_carrier = K.module_generators[0] carrier_factor = (carrier_index, carrier_capacity) last_final_carrier = empty_carrier state = self._states[-1] dims = state.parent().dims while not passed: KRT = TensorProductOfKirillovReshetikhinTableaux( self._cartan_type, dims + (carrier_factor, )) elt = KRT(*(list(state) + [empty_carrier])) RC = RiggedConfigurations(self._cartan_type, (carrier_factor, ) + dims) elt2 = RC(*elt.to_rigged_configuration() ).to_tensor_product_of_kirillov_reshetikhin_tableaux() # Back to an empty carrier or we are not getting any better if elt2[0] == empty_carrier or elt2[0] == last_final_carrier: passed = True KRT = TensorProductOfKirillovReshetikhinTableaux( self._cartan_type, dims) self._states.append(KRT(*elt2[1:])) self._evolutions.append(carrier_factor) if elt2[0] != empty_carrier: print("Last carrier:") print(ascii_art(last_final_carrier)) else: # We need to add more vacuum states last_final_carrier = elt2[0] dims = tuple([(self._vacuum, 1)] * carrier_capacity) + dims