def cartan_type(self): """ Return the Cartan type of ``self``. EXAMPLES:: sage: FiniteWeylGroups().example().cartan_type() ['A', 3] relabelled by {1: 0, 2: 1, 3: 2} """ from sage.combinat.root_system.cartan_type import CartanType C = CartanType(['A', self.n - 1]) C = C.relabel(lambda i: i - 1) return C
def cartan_type(self): """ Return the Cartan type of ``self``. EXAMPLES:: sage: FiniteWeylGroups().example().cartan_type() ['A', 3] relabelled by {1: 0, 2: 1, 3: 2} """ from sage.combinat.root_system.cartan_type import CartanType C = CartanType(['A',self.n-1]) C = C.relabel(lambda i:i-1) return C
def cartan_type(self): r""" Return the Cartan type of ``self``. EXAMPLES:: sage: W = ReflectionGroup(['A',3]) # optional - gap3 sage: W.cartan_type() # optional - gap3 ['A', 3] sage: W = ReflectionGroup(['A',3], ['B',3]) # optional - gap3 sage: W.cartan_type() # optional - gap3 A3xB3 relabelled by {1: 3, 2: 2, 3: 1} TESTS: Check that dihedral types are handled properly:: sage: W = ReflectionGroup(['I',3]); W # optional - gap3 Irreducible real reflection group of rank 2 and type A2 sage: W = ReflectionGroup(['I',4]); W # optional - gap3 Irreducible real reflection group of rank 2 and type C2 sage: W = ReflectionGroup(['I',5]); W # optional - gap3 Irreducible real reflection group of rank 2 and type I2(5) """ if len(self._type) == 1: ct = self._type[0] if ct['series'] == "I": C = CartanType([ct['series'], ct['bond']]) else: C = CartanType([ct['series'], ct['rank']]) CG = C.coxeter_diagram() G = self.coxeter_diagram() return C.relabel( CG.is_isomorphic(G, edge_labels=True, certificate=True)[1]) else: return CartanType( [W.cartan_type() for W in self.irreducible_components()])
def cartan_type(self): r""" Return the Cartan type of ``self``. EXAMPLES:: sage: W = ReflectionGroup(['A',3]) # optional - gap3 sage: W.cartan_type() # optional - gap3 ['A', 3] sage: W = ReflectionGroup(['A',3], ['B',3]) # optional - gap3 sage: W.cartan_type() # optional - gap3 A3xB3 relabelled by {1: 3, 2: 2, 3: 1} """ if len(self._type) == 1: ct = self._type[0] C = CartanType([ct['series'], ct['rank']]) CG = C.coxeter_diagram() G = self.coxeter_diagram() return C.relabel(CG.is_isomorphic(G, edge_labels=True, certificate=True)[1]) else: return CartanType([W.cartan_type() for W in self.irreducible_components()])
def cartan_type(self): r""" Return the Cartan type of ``self``. EXAMPLES:: sage: W = ReflectionGroup(['A',3]) # optional - gap3 sage: W.cartan_type() # optional - gap3 ['A', 3] sage: W = ReflectionGroup(['A',3], ['B',2]) # optional - gap3 sage: W.cartan_type() # optional - gap3 A3xB2 """ if len(self._type) == 1: ct = self._type[0] C = CartanType([ct['series'], ct['rank']]) return C.relabel( {i + 1: ii for i, ii in enumerate(self.index_set())}) else: return CartanType( [W.cartan_type() for W in self.irreducible_components()])
def find_cartan_type_from_matrix(CM): r""" Find a Cartan type by direct comparison of Dynkin diagrams given from the generalized Cartan matrix ``CM`` and return ``None`` if not found. INPUT: - ``CM`` -- a generalized Cartan matrix EXAMPLES:: sage: from sage.combinat.root_system.cartan_matrix import find_cartan_type_from_matrix sage: CM = CartanMatrix([[2,-1,-1], [-1,2,-1], [-1,-1,2]]) sage: find_cartan_type_from_matrix(CM) ['A', 2, 1] sage: CM = CartanMatrix([[2,-1,0], [-1,2,-2], [0,-1,2]]) sage: find_cartan_type_from_matrix(CM) ['C', 3] relabelled by {1: 0, 2: 1, 3: 2} sage: CM = CartanMatrix([[2,-1,-2], [-1,2,-1], [-2,-1,2]]) sage: find_cartan_type_from_matrix(CM) """ types = [] for S in CM.dynkin_diagram().connected_components_subgraphs(): S = DiGraph(S) # We need a simple digraph here n = S.num_verts() # Build the list to test based upon rank if n == 1: types.append(CartanType(['A', 1])) continue test = [['A', n]] if n >= 2: if n == 2: test += [['G', 2], ['A', 2, 2]] test += [['B', n], ['A', n - 1, 1]] if n >= 3: if n == 3: test.append(['G', 2, 1]) test += [['C', n], ['BC', n - 1, 2], ['C', n - 1, 1]] if n >= 4: if n == 4: test.append(['F', 4]) test += [['D', n], ['B', n - 1, 1]] if n >= 5: if n == 5: test.append(['F', 4, 1]) test.append(['D', n - 1, 1]) if n == 6: test.append(['E', 6]) elif n == 7: test += [['E', 7], ['E', 6, 1]] elif n == 8: test += [['E', 8], ['E', 7, 1]] elif n == 9: test.append(['E', 8, 1]) # Test every possible Cartan type and its dual found = False for x in test: ct = CartanType(x) T = DiGraph(ct.dynkin_diagram()) # We need a simple digraph here iso, match = T.is_isomorphic(S, certificate=True, edge_labels=True) if iso: types.append(ct.relabel(match)) found = True break if ct == ct.dual(): continue # self-dual, so nothing more to test ct = ct.dual() T = DiGraph(ct.dynkin_diagram()) # We need a simple digraph here iso, match = T.is_isomorphic(S, certificate=True, edge_labels=True) if iso: types.append(ct.relabel(match)) found = True break if not found: return None return CartanType(types)
def __classcall_private__(cls, data=None, index_set=None, cartan_type=None, cartan_type_check=True): """ Normalize input so we can inherit from sparse integer matrix. .. NOTE:: To disable the Cartan type check, use the optional argument ``cartan_type_check = False``. EXAMPLES:: sage: C = CartanMatrix(['A',1,1]) sage: C2 = CartanMatrix([[2, -2], [-2, 2]]) sage: C3 = CartanMatrix(matrix([[2, -2], [-2, 2]]), [0, 1]) sage: C == C2 and C == C3 True TESTS: Check that :trac:`15740` is fixed:: sage: d = DynkinDiagram() sage: d.add_edge('a', 'b', 2) sage: d.index_set() ('a', 'b') sage: cm = CartanMatrix(d) sage: cm.index_set() ('a', 'b') """ # Special case with 0 args and kwds has Cartan type if cartan_type is not None and data is None: data = CartanType(cartan_type) if data is None: data = [] n = 0 index_set = tuple() cartan_type = None subdivisions = None elif isinstance(data, CartanMatrix): if index_set is not None: d = {a: index_set[i] for i, a in enumerate(data.index_set())} return data.relabel(d) return data else: dynkin_diagram = None subdivisions = None from sage.combinat.root_system.dynkin_diagram import DynkinDiagram_class if isinstance(data, DynkinDiagram_class): dynkin_diagram = data cartan_type = data._cartan_type else: try: cartan_type = CartanType(data) dynkin_diagram = cartan_type.dynkin_diagram() except (TypeError, ValueError): pass if dynkin_diagram is not None: n = dynkin_diagram.rank() index_set = dynkin_diagram.index_set() oir = dynkin_diagram.odd_isotropic_roots() reverse = {a: i for i, a in enumerate(index_set)} data = {(i, i): 2 if index_set[i] not in oir else 0 for i in range(n)} for (i, j, l) in dynkin_diagram.edge_iterator(): data[(reverse[j], reverse[i])] = -l else: M = matrix(data) if not is_generalized_cartan_matrix(M): raise ValueError( "the input matrix is not a generalized Cartan matrix") n = M.ncols() data = M.dict() subdivisions = M._subdivisions if index_set is None: index_set = tuple(range(n)) else: index_set = tuple(index_set) if len(index_set) != n and len(set(index_set)) != n: raise ValueError("the given index set is not valid") # We can do the Cartan type initialization later as this is not # a unique representation mat = typecall(cls, MatrixSpace(ZZ, n, sparse=True), data, False, True) # FIXME: We have to initialize the CartanMatrix part separately because # of the __cinit__ of the matrix. We should get rid of this workaround mat._CM_init(cartan_type, index_set, cartan_type_check) mat._subdivisions = subdivisions return mat
def __classcall_private__(cls, data=None, index_set=None, cartan_type=None, cartan_type_check=True, borcherds=None): """ Normalize input so we can inherit from sparse integer matrix. .. NOTE:: To disable the Cartan type check, use the optional argument ``cartan_type_check = False``. EXAMPLES:: sage: C = CartanMatrix(['A',1,1]) sage: C2 = CartanMatrix([[2, -2], [-2, 2]]) sage: C3 = CartanMatrix(matrix([[2, -2], [-2, 2]]), [0, 1]) sage: C == C2 and C == C3 True TESTS: Check that :trac:`15740` is fixed:: sage: d = DynkinDiagram() sage: d.add_edge('a', 'b', 2) sage: d.index_set() ('a', 'b') sage: cm = CartanMatrix(d) sage: cm.index_set() ('a', 'b') """ # Special case with 0 args and kwds has Cartan type if cartan_type is not None and data is None: data = CartanType(cartan_type) if data is None: data = [] n = 0 index_set = tuple() cartan_type = None subdivisions = None elif isinstance(data, CartanMatrix): if index_set is not None: d = {a: index_set[i] for i,a in enumerate(data.index_set())} return data.relabel(d) return data else: dynkin_diagram = None subdivisions = None from sage.combinat.root_system.dynkin_diagram import DynkinDiagram_class if isinstance(data, DynkinDiagram_class): dynkin_diagram = data cartan_type = data._cartan_type else: try: cartan_type = CartanType(data) dynkin_diagram = cartan_type.dynkin_diagram() except (TypeError, ValueError): pass if dynkin_diagram is not None: n = dynkin_diagram.rank() index_set = dynkin_diagram.index_set() oir = dynkin_diagram.odd_isotropic_roots() reverse = {a: i for i,a in enumerate(index_set)} if isinstance(borcherds, (list, tuple)): if (len(borcherds) != len(index_set) and not all(val in ZZ and (val == 2 or (val % 2 == 0 and val < 0)) for val in borcherds)): raise ValueError("the input data is not a Borcherds-Cartan matrix") data = {(i, i): val if index_set[i] not in oir else 0 for i,val in enumerate(borcherds)} else: data = {(i, i): 2 if index_set[i] not in oir else 0 for i in range(n)} for (i,j,l) in dynkin_diagram.edge_iterator(): data[(reverse[j], reverse[i])] = -l else: M = matrix(data) if borcherds: if not is_borcherds_cartan_matrix(M): raise ValueError("the input matrix is not a Borcherds-Cartan matrix") else: if not is_generalized_cartan_matrix(M): raise ValueError("the input matrix is not a generalized Cartan matrix") n = M.ncols() data = M.dict() subdivisions = M._subdivisions if index_set is None: index_set = tuple(range(n)) else: index_set = tuple(index_set) if len(index_set) != n and len(set(index_set)) != n: raise ValueError("the given index set is not valid") # We can do the Cartan type initialization later as this is not # a unique representation mat = typecall(cls, MatrixSpace(ZZ, n, sparse=True), data, False, True) # FIXME: We have to initialize the CartanMatrix part separately because # of the __cinit__ of the matrix. We should get rid of this workaround mat._CM_init(cartan_type, index_set, cartan_type_check) mat._subdivisions = subdivisions return mat
def find_cartan_type_from_matrix(CM): r""" Find a Cartan type by direct comparison of Dynkin diagrams given from the generalized Cartan matrix ``CM`` and return ``None`` if not found. INPUT: - ``CM`` -- a generalized Cartan matrix EXAMPLES:: sage: from sage.combinat.root_system.cartan_matrix import find_cartan_type_from_matrix sage: CM = CartanMatrix([[2,-1,-1], [-1,2,-1], [-1,-1,2]]) sage: find_cartan_type_from_matrix(CM) ['A', 2, 1] sage: CM = CartanMatrix([[2,-1,0], [-1,2,-2], [0,-1,2]]) sage: find_cartan_type_from_matrix(CM) ['C', 3] relabelled by {1: 0, 2: 1, 3: 2} sage: CM = CartanMatrix([[2,-1,-2], [-1,2,-1], [-2,-1,2]]) sage: find_cartan_type_from_matrix(CM) """ types = [] for S in CM.dynkin_diagram().connected_components_subgraphs(): S = DiGraph(S) # We need a simple digraph here n = S.num_verts() # Build the list to test based upon rank if n == 1: types.append(CartanType(['A', 1])) continue test = [['A', n]] if n >= 2: if n == 2: test += [['G',2], ['A',2,2]] test += [['B',n], ['A',n-1,1]] if n >= 3: if n == 3: test.append(['G',2,1]) test += [['C',n], ['BC',n-1,2], ['C',n-1,1]] if n >= 4: if n == 4: test.append(['F',4]) test += [['D',n], ['B',n-1,1]] if n >= 5: if n == 5: test.append(['F',4,1]) test.append(['D',n-1,1]) if n == 6: test.append(['E',6]) elif n == 7: test += [['E',7], ['E',6,1]] elif n == 8: test += [['E',8], ['E',7,1]] elif n == 9: test.append(['E',8,1]) # Test every possible Cartan type and its dual found = False for x in test: ct = CartanType(x) T = DiGraph(ct.dynkin_diagram()) # We need a simple digraph here iso, match = T.is_isomorphic(S, certificate=True, edge_labels=True) if iso: types.append(ct.relabel(match)) found = True break if ct == ct.dual(): continue # self-dual, so nothing more to test ct = ct.dual() T = DiGraph(ct.dynkin_diagram()) # We need a simple digraph here iso, match = T.is_isomorphic(S, certificate=True, edge_labels=True) if iso: types.append(ct.relabel(match)) found = True break if not found: return None return CartanType(types)
def cartan_type(self): r""" Returns the Cartan type of the Cartan companion of self.b_matrix() Only crystallographic types are implemented Warning: this function is redundant but the corresonding method in CartanType does not recognize all the types """ A = self.cartan_companion() n = self.rk degrees_dict = dict(zip(range(n),map(sum,2-A))) degrees_set = Set(degrees_dict.values()) types_to_check = [ ["A",n] ] if n > 1: types_to_check.append(["B",n]) if n > 2: types_to_check.append(["C",n]) if n > 3: types_to_check.append(["D",n]) if n >=6 and n <= 8: types_to_check.append(["E",n]) if n == 4: types_to_check.append(["F",n]) if n == 2: types_to_check.append(["G",n]) if n >1: types_to_check.append(["A", n-1,1]) types_to_check.append(["B", n-1,1]) types_to_check.append(["BC",n-1,2]) types_to_check.append(["A", 2*n-2,2]) types_to_check.append(["A", 2*n-3,2]) if n>2: types_to_check.append(["C", n-1,1]) types_to_check.append(["D", n,2]) if n>3: types_to_check.append(["D", n-1,1]) if n >=7 and n <= 9: types_to_check.append(["E",n-1,1]) if n == 5: types_to_check.append(["F",4,1]) if n == 3: types_to_check.append(["G",n-1,1]) types_to_check.append(["D",4,3]) if n == 5: types_to_check.append(["E",6,2]) for ct_name in types_to_check: ct = CartanType(ct_name) if 0 not in ct.index_set(): ct = ct.relabel(dict(zip(range(1,n+1),range(n)))) ct_matrix = ct.cartan_matrix() ct_degrees_dict = dict(zip(range(n),map(sum,2-ct_matrix))) if Set(ct_degrees_dict.values()) != degrees_set: continue for p in Permutations(range(n)): relabeling = dict(zip(range(n),p)) ct_new = ct.relabel(relabeling) if ct_new.cartan_matrix() == A: return copy(ct_new) raise ValueError("Type not recognized")
def cartan_type(self): r""" Returns the Cartan type of the Cartan companion of self.b_matrix() Only crystallographic types are implemented Warning: this function is redundant but the corresonding method in CartanType does not recognize all the types """ A = self.cartan_companion() n = self.rk degrees_dict = dict(zip(range(n), map(sum, 2 - A))) degrees_set = Set(degrees_dict.values()) types_to_check = [["A", n]] if n > 1: types_to_check.append(["B", n]) if n > 2: types_to_check.append(["C", n]) if n > 3: types_to_check.append(["D", n]) if n >= 6 and n <= 8: types_to_check.append(["E", n]) if n == 4: types_to_check.append(["F", n]) if n == 2: types_to_check.append(["G", n]) if n > 1: types_to_check.append(["A", n - 1, 1]) types_to_check.append(["B", n - 1, 1]) types_to_check.append(["BC", n - 1, 2]) types_to_check.append(["A", 2 * n - 2, 2]) types_to_check.append(["A", 2 * n - 3, 2]) if n > 2: types_to_check.append(["C", n - 1, 1]) types_to_check.append(["D", n, 2]) if n > 3: types_to_check.append(["D", n - 1, 1]) if n >= 7 and n <= 9: types_to_check.append(["E", n - 1, 1]) if n == 5: types_to_check.append(["F", 4, 1]) if n == 3: types_to_check.append(["G", n - 1, 1]) types_to_check.append(["D", 4, 3]) if n == 5: types_to_check.append(["E", 6, 2]) for ct_name in types_to_check: ct = CartanType(ct_name) if 0 not in ct.index_set(): ct = ct.relabel(dict(zip(range(1, n + 1), range(n)))) ct_matrix = ct.cartan_matrix() ct_degrees_dict = dict(zip(range(n), map(sum, 2 - ct_matrix))) if Set(ct_degrees_dict.values()) != degrees_set: continue for p in Permutations(range(n)): relabeling = dict(zip(range(n), p)) ct_new = ct.relabel(relabeling) if ct_new.cartan_matrix() == A: return copy(ct_new) raise ValueError("Type not recognized")