Exemplo n.º 1
0
    def _from_matrix(cls, data, coxeter_type, index_set, coxeter_type_check):
        """
        Initiate the Coxeter matrix from a matrix.

        TESTS::

            sage: CM = CoxeterMatrix([[1,2],[2,1]]); CM
            [1 2]
            [2 1]
            sage: CM = CoxeterMatrix([[1,-1],[-1,1]]); CM
            [ 1 -1]
            [-1  1]
            sage: CM = CoxeterMatrix([[1,-1.5],[-1.5,1]]); CM
            [ 1.00000000000000 -1.50000000000000]
            [-1.50000000000000  1.00000000000000]
            sage: CM = CoxeterMatrix([[1,-3/2],[-3/2,1]]); CM
            [   1 -3/2]
            [-3/2    1]
            sage: CM = CoxeterMatrix([[1,-3/2,5],[-3/2,1,-1],[5,-1,1]]); CM
            [   1 -3/2    5]
            [-3/2    1   -1]
            [   5   -1    1]
            sage: CM = CoxeterMatrix([[1,-3/2,5],[-3/2,1,oo],[5,oo,1]]); CM
            [   1 -3/2    5]
            [-3/2    1   -1]
            [   5   -1    1]
        """
        # Check that the data is valid
        check_coxeter_matrix(data)

        M = matrix(data)
        n = M.ncols()

        base_ring = M.base_ring()

        if not coxeter_type:
            if n == 1:
                coxeter_type = CoxeterType(['A', 1])
            elif coxeter_type_check:
                coxeter_type = recognize_coxeter_type_from_matrix(M, index_set)
            else:
                coxeter_type = None

        raw_data = M.list()

        mat = typecall(cls, MatrixSpace(base_ring, n, sparse=False), raw_data,
                       coxeter_type, index_set)
        mat._subdivisions = M._subdivisions

        return mat
Exemplo n.º 2
0
def recognize_coxeter_type_from_matrix(coxeter_matrix, index_set):
    """
    Return the Coxeter type of ``coxeter_matrix`` if known,
    otherwise return ``None``.

    EXAMPLES:

    Some infinite ones::

        sage: C = CoxeterMatrix([[1,3,2],[3,1,-1],[2,-1,1]])
        sage: C.is_finite()  # indirect doctest
        False
        sage: C = CoxeterMatrix([[1,-1,-1],[-1,1,-1],[-1,-1,1]])
        sage: C.is_finite()  # indirect doctest
        False

    Some finite ones::

        sage: m = matrix(CoxeterMatrix(['D', 4]))
        sage: CoxeterMatrix(m).is_finite()  # indirect doctest
        True
        sage: m = matrix(CoxeterMatrix(['H', 4]))
        sage: CoxeterMatrix(m).is_finite()  # indirect doctest
        True

        sage: CoxeterMatrix(CoxeterType(['A',10]).coxeter_graph()).coxeter_type()
        Coxeter type of ['A', 10]
        sage: CoxeterMatrix(CoxeterType(['B',10]).coxeter_graph()).coxeter_type()
        Coxeter type of ['B', 10]
        sage: CoxeterMatrix(CoxeterType(['C',10]).coxeter_graph()).coxeter_type()
        Coxeter type of ['B', 10]
        sage: CoxeterMatrix(CoxeterType(['D',10]).coxeter_graph()).coxeter_type()
        Coxeter type of ['D', 10]
        sage: CoxeterMatrix(CoxeterType(['E',6]).coxeter_graph()).coxeter_type()
        Coxeter type of ['E', 6]
        sage: CoxeterMatrix(CoxeterType(['E',7]).coxeter_graph()).coxeter_type()
        Coxeter type of ['E', 7]
        sage: CoxeterMatrix(CoxeterType(['E',8]).coxeter_graph()).coxeter_type()
        Coxeter type of ['E', 8]
        sage: CoxeterMatrix(CoxeterType(['F',4]).coxeter_graph()).coxeter_type()
        Coxeter type of ['F', 4]
        sage: CoxeterMatrix(CoxeterType(['G',2]).coxeter_graph()).coxeter_type()
        Coxeter type of ['G', 2]
        sage: CoxeterMatrix(CoxeterType(['H',3]).coxeter_graph()).coxeter_type()
        Coxeter type of ['H', 3]
        sage: CoxeterMatrix(CoxeterType(['H',4]).coxeter_graph()).coxeter_type()
        Coxeter type of ['H', 4]
        sage: CoxeterMatrix(CoxeterType(['I',100]).coxeter_graph()).coxeter_type()
        Coxeter type of ['I', 100]

    Some affine graphs::

        sage: CoxeterMatrix(CoxeterType(['A',1,1]).coxeter_graph()).coxeter_type()
        Coxeter type of ['A', 1, 1]
        sage: CoxeterMatrix(CoxeterType(['A',10,1]).coxeter_graph()).coxeter_type()
        Coxeter type of ['A', 10, 1]
        sage: CoxeterMatrix(CoxeterType(['B',10,1]).coxeter_graph()).coxeter_type()
        Coxeter type of ['B', 10, 1]
        sage: CoxeterMatrix(CoxeterType(['C',10,1]).coxeter_graph()).coxeter_type()
        Coxeter type of ['C', 10, 1]
        sage: CoxeterMatrix(CoxeterType(['D',10,1]).coxeter_graph()).coxeter_type()
        Coxeter type of ['D', 10, 1]
        sage: CoxeterMatrix(CoxeterType(['E',6,1]).coxeter_graph()).coxeter_type()
        Coxeter type of ['E', 6, 1]
        sage: CoxeterMatrix(CoxeterType(['E',7,1]).coxeter_graph()).coxeter_type()
        Coxeter type of ['E', 7, 1]
        sage: CoxeterMatrix(CoxeterType(['E',8,1]).coxeter_graph()).coxeter_type()
        Coxeter type of ['E', 8, 1]
        sage: CoxeterMatrix(CoxeterType(['F',4,1]).coxeter_graph()).coxeter_type()
        Coxeter type of ['F', 4, 1]
        sage: CoxeterMatrix(CoxeterType(['G',2,1]).coxeter_graph()).coxeter_type()
        Coxeter type of ['G', 2, 1]

    TESTS:

    Check that we detect relabellings::

        sage: M = CoxeterMatrix([[1,2,3],[2,1,6],[3,6,1]], index_set=['a', 'b', 'c'])
        sage: M.coxeter_type()
        Coxeter type of ['G', 2, 1] relabelled by {0: 'a', 1: 'b', 2: 'c'}

        sage: from sage.combinat.root_system.coxeter_matrix import recognize_coxeter_type_from_matrix
        sage: for C in CoxeterMatrix.samples():
        ....:     relabelling_perm = Permutations(C.index_set()).random_element()
        ....:     relabelling_dict = {C.index_set()[i]: relabelling_perm[i] for i in range(C.rank())}
        ....:     relabeled_matrix = C.relabel(relabelling_dict)._matrix
        ....:     recognized_type = recognize_coxeter_type_from_matrix(relabeled_matrix, relabelling_perm)
        ....:     if C.is_finite() or C.is_affine():
        ....:         assert recognized_type == C.coxeter_type()

    We check the rank 2 cases (:trac:`20419`)::

        sage: for i in range(2, 10):
        ....:     M = matrix([[1,i],[i,1]])
        ....:     CoxeterMatrix(M).coxeter_type()
        Coxeter type of A1xA1 relabelled by {1: 2}
        Coxeter type of ['A', 2]
        Coxeter type of ['B', 2]
        Coxeter type of ['I', 5]
        Coxeter type of ['G', 2]
        Coxeter type of ['I', 7]
        Coxeter type of ['I', 8]
        Coxeter type of ['I', 9]
        sage: CoxeterMatrix(matrix([[1,-1],[-1,1]]), index_set=[0,1]).coxeter_type()
        Coxeter type of ['A', 1, 1]
    """
    # First, we build the Coxeter graph of the group without the edge labels
    n = ZZ(coxeter_matrix.nrows())
    G = Graph([[index_set[i], index_set[j], coxeter_matrix[i, j]]
               for i in range(n) for j in range(i, n)
               if coxeter_matrix[i, j] not in [1, 2]])
    G.add_vertices(index_set)

    types = []
    for S in G.connected_components_subgraphs():
        r = S.num_verts()
        # Handle the special cases first
        if r == 1:
            types.append(CoxeterType(['A', 1]).relabel({1: S.vertices()[0]}))
            continue
        if r == 2:  # Type B2, G2, or I_2(p)
            e = S.edge_labels()[0]
            if e == 3:  # Can't be 2 because it is connected
                ct = CoxeterType(['A', 2])
            elif e == 4:
                ct = CoxeterType(['B', 2])
            elif e == 6:
                ct = CoxeterType(['G', 2])
            elif e > 0 and e < float('inf'):  # Remaining non-affine types
                ct = CoxeterType(['I', e])
            else:  # Otherwise it is infinite dihedral group Z_2 \ast Z_2
                ct = CoxeterType(['A', 1, 1])
            if not ct.is_affine():
                types.append(
                    ct.relabel({
                        1: S.vertices()[0],
                        2: S.vertices()[1]
                    }))
            else:
                types.append(
                    ct.relabel({
                        0: S.vertices()[0],
                        1: S.vertices()[1]
                    }))
            continue

        test = [['A', r], ['B', r], ['A', r - 1, 1]]
        if r >= 3:
            if r == 3:
                test += [['G', 2, 1], ['H', 3]]
            test.append(['C', r - 1, 1])
        if r >= 4:
            if r == 4:
                test += [['F', 4], ['H', 4]]
            test += [['D', r], ['B', r - 1, 1]]
        if r >= 5:
            if r == 5:
                test.append(['F', 4, 1])
            test.append(['D', r - 1, 1])
        if r == 6:
            test.append(['E', 6])
        elif r == 7:
            test += [['E', 7], ['E', 6, 1]]
        elif r == 8:
            test += [['E', 8], ['E', 7, 1]]
        elif r == 9:
            test.append(['E', 8, 1])

        found = False
        for ct in test:
            ct = CoxeterType(ct)
            T = ct.coxeter_graph()
            iso, match = T.is_isomorphic(S, certify=True, edge_labels=True)
            if iso:
                types.append(ct.relabel(match))
                found = True
                break
        if not found:
            return None

    return CoxeterType(types)
Exemplo n.º 3
0
    def __classcall_private__(cls,
                              data=None,
                              index_set=None,
                              coxeter_type=None,
                              cartan_type=None,
                              coxeter_type_check=True):
        r"""
        A Coxeter matrix can we created via a graph, a Coxeter type, or
        a matrix.

        .. NOTE::

            To disable the Coxeter type check, use the optional argument
            ``coxeter_type_check = False``.

        EXAMPLES::

            sage: C = CoxeterMatrix(['A',1,1],['a','b'])
            sage: C2 = CoxeterMatrix([[1, -1], [-1, 1]])
            sage: C3 = CoxeterMatrix(matrix([[1, -1], [-1, 1]]), [0, 1])
            sage: C == C2 and C == C3
            True

        Check with `\infty` because of the hack of using `-1` to represent
        `\infty` in the Coxeter matrix::

            sage: G = Graph([(0, 1, 3), (1, 2, oo)])
            sage: W1 = CoxeterMatrix([[1, 3, 2], [3, 1, -1], [2, -1, 1]])
            sage: W2 = CoxeterMatrix(G)
            sage: W1 == W2
            True
            sage: CoxeterMatrix(W1.coxeter_graph()) == W1
            True

        The base ring of the matrix depends on the entries given::

            sage: CoxeterMatrix([[1,-1],[-1,1]])._matrix.base_ring()
            Integer Ring
            sage: CoxeterMatrix([[1,-3/2],[-3/2,1]])._matrix.base_ring()
            Rational Field
            sage: CoxeterMatrix([[1,-1.5],[-1.5,1]])._matrix.base_ring()
            Real Field with 53 bits of precision
        """
        if not data:
            if coxeter_type:
                data = CoxeterType(coxeter_type)
            elif cartan_type:
                data = CoxeterType(CartanType(cartan_type))

        # Special cases with no arguments passed
        if not data:
            data = []
            n = 0
            index_set = tuple()
            coxeter_type = None
            base_ring = ZZ
            mat = typecall(cls, MatrixSpace(base_ring, n, sparse=False), data,
                           coxeter_type, index_set)
            mat._subdivisions = None

            return mat

        if isinstance(data, CoxeterMatrix):  # Initiate from itself
            return data

        # Initiate from a graph:
        # TODO: Check if a CoxeterDiagram once implemented
        if isinstance(data, Graph):
            return cls._from_graph(data, coxeter_type_check)

        # Get the Coxeter type
        coxeter_type = None
        from sage.combinat.root_system.cartan_type import CartanType_abstract
        if isinstance(data, CartanType_abstract):
            coxeter_type = data.coxeter_type()
        else:
            try:
                coxeter_type = CoxeterType(data)
            except (TypeError, ValueError, NotImplementedError):
                pass

        # Initiate from a Coxeter type
        if coxeter_type:
            return cls._from_coxetertype(coxeter_type)

        # TODO:: remove when oo is possible in matrices.
        n = len(data[0])
        data = [x if x != infinity else -1 for r in data for x in r]
        data = matrix(n, n, data)
        # until here

        # Get the index set
        if index_set:
            index_set = tuple(index_set)
        else:
            index_set = tuple(range(1, n + 1))
        if len(set(index_set)) != n:
            raise ValueError("the given index set is not valid")

        return cls._from_matrix(data, coxeter_type, index_set,
                                coxeter_type_check)