Пример #1
0
    def __classcall_private__(cls, cartan_type, shapes=None, shape=None):
        """
        Normalizes the input arguments to ensure unique representation,
        and to delegate the construction of spin tableaux.

        EXAMPLES::

            sage: T1 = CrystalOfTableaux(CartanType(['A',3]), shape  = [2,2])
            sage: T2 = CrystalOfTableaux(['A',3],             shape  = (2,2))
            sage: T3 = CrystalOfTableaux(['A',3],             shapes = ([2,2],))
            sage: T2 is T1, T3 is T1
            (True, True)
        """
        cartan_type = CartanType(cartan_type)
        n = cartan_type.rank()
        # standardize shape/shapes input into a tuple of tuples
        assert operator.xor(shape is not None, shapes is not None)
        if shape is not None:
            shapes = (shape, )
        spin_shapes = tuple(tuple(shape) for shape in shapes)
        try:
            shapes = tuple(
                tuple(trunc(i) for i in shape) for shape in spin_shapes)
        except StandardError:
            raise ValueError(
                "shapes should all be partitions or half-integer partitions")
        if spin_shapes == shapes:
            return super(CrystalOfTableaux,
                         cls).__classcall__(cls, cartan_type, shapes)

        # Handle the construction of a crystals of spin tableaux
        # Caveat: this currently only supports all shapes being half
        # integer partitions of length the rank for type B and D. In
        # particular, for type D, the spins all have to be plus or all
        # minus spins
        assert all(len(sh) == n for sh in shapes), \
            "the length of all half-integer partition shapes should be the rank"
        assert all(2*i % 2 == 1 for shape in spin_shapes for i in shape), \
            "shapes should be either all partitions or all half-integer partitions"
        if cartan_type.type() == 'D':
            if all(i >= 0 for shape in spin_shapes for i in shape):
                S = CrystalOfSpinsPlus(cartan_type)
            elif all(shape[-1] < 0 for shape in spin_shapes):
                S = CrystalOfSpinsMinus(cartan_type)
            else:
                raise ValueError, "In type D spins should all be positive or negative"
        else:
            assert all( i >= 0 for shape in spin_shapes for i in shape), \
                "shapes should all be partitions"
            S = CrystalOfSpins(cartan_type)
        B = CrystalOfTableaux(cartan_type, shapes=shapes)
        T = TensorProductOfCrystals(S,
                                    B,
                                    generators=[[S.module_generators[0], x]
                                                for x in B.module_generators])
        T.rename("The crystal of tableaux of type %s and shape(s) %s" %
                 (cartan_type, list(list(shape) for shape in spin_shapes)))
        T.shapes = spin_shapes
        return T
Пример #2
0
    def __classcall_private__(cls, cartan_type, shapes = None, shape = None):
        """
        Normalizes the input arguments to ensure unique representation,
        and to delegate the construction of spin tableaux.

        EXAMPLES::

            sage: T1 = CrystalOfTableaux(CartanType(['A',3]), shape  = [2,2])
            sage: T2 = CrystalOfTableaux(['A',3],             shape  = (2,2))
            sage: T3 = CrystalOfTableaux(['A',3],             shapes = ([2,2],))
            sage: T2 is T1, T3 is T1
            (True, True)
        """
        cartan_type = CartanType(cartan_type)
        n = cartan_type.rank()
        # standardize shape/shapes input into a tuple of tuples
        assert operator.xor(shape is not None, shapes is not None)
        if shape is not None:
            shapes = (shape,)
        spin_shapes = tuple( tuple(shape) for shape in shapes )
        try:
            shapes = tuple( tuple(trunc(i) for i in shape) for shape in spin_shapes )
        except StandardError:
            raise ValueError("shapes should all be partitions or half-integer partitions")
        if spin_shapes == shapes:
            return super(CrystalOfTableaux, cls).__classcall__(cls, cartan_type, shapes)

        # Handle the construction of a crystals of spin tableaux
        # Caveat: this currently only supports all shapes being half
        # integer partitions of length the rank for type B and D. In
        # particular, for type D, the spins all have to be plus or all
        # minus spins
        assert all(len(sh) == n for sh in shapes), \
            "the length of all half-integer partition shapes should be the rank"
        assert all(2*i % 2 == 1 for shape in spin_shapes for i in shape), \
            "shapes should be either all partitions or all half-integer partitions"
        if cartan_type.type() == 'D':
            if all( i >= 0 for shape in spin_shapes for i in shape):
                S = CrystalOfSpinsPlus(cartan_type)
            elif all(shape[-1]<0 for shape in spin_shapes):
                S = CrystalOfSpinsMinus(cartan_type)
            else:
                raise ValueError, "In type D spins should all be positive or negative"
        else:
            assert all( i >= 0 for shape in spin_shapes for i in shape), \
                "shapes should all be partitions"
            S = CrystalOfSpins(cartan_type)
        B = CrystalOfTableaux(cartan_type, shapes = shapes)
        T = TensorProductOfCrystals(S,B, generators=[[S.module_generators[0],x] for x in B.module_generators])
        T.rename("The crystal of tableaux of type %s and shape(s) %s"%(cartan_type, list(list(shape) for shape in spin_shapes)))
        T.shapes = spin_shapes
        return T
Пример #3
0
    def __classcall_private__(cls, R, cartan_type):
        """
        Return the correct parent based on input.

        EXAMPLES::

            sage: lie_algebras.ClassicalMatrix(QQ, ['A', 4])
            Special linear Lie algebra of rank 5 over Rational Field
            sage: lie_algebras.ClassicalMatrix(QQ, CartanType(['B',4]))
            Special orthogonal Lie algebra of rank 9 over Rational Field
            sage: lie_algebras.ClassicalMatrix(QQ, 'C4')
            Symplectic Lie algebra of rank 8 over Rational Field
            sage: lie_algebras.ClassicalMatrix(QQ, cartan_type=['D',4])
            Special orthogonal Lie algebra of rank 8 over Rational Field
        """
        if isinstance(cartan_type, (CartanMatrix, DynkinDiagram_class)):
            cartan_type = cartan_type.cartan_type()
        else:
            cartan_type = CartanType(cartan_type)

        if not cartan_type.is_finite():
            raise ValueError("only for finite types")

        if cartan_type.type() == 'A':
            return sl(R, cartan_type.rank() + 1)
        if cartan_type.type() == 'B':
            return so(R, 2*cartan_type.rank() + 1)
        if cartan_type.type() == 'C':
            return sp(R, 2*cartan_type.rank())
        if cartan_type.type() == 'D':
            return so(R, 2*cartan_type.rank())
        if cartan_type.type() == 'E':
            if cartan_type.rank() == 6:
                return e6(R)
            if cartan_type.rank() in [7,8]:
                raise NotImplementedError("not yet implemented")
        if cartan_type.type() == 'F' and cartan_type.rank() == 4:
            return f4(R)
        if cartan_type.type() == 'G' and cartan_type.rank() == 2:
            return g2(R)
        raise ValueError("invalid Cartan type")
Пример #4
0
def Associahedron(cartan_type, backend='ppl'):
    r"""
    Construct an associahedron.

    The generalized associahedron is a polytopal complex with vertices in
    one-to-one correspondence with clusters in the cluster complex, and with
    edges between two vertices if and only if the associated two clusters
    intersect in codimension 1.

    The associahedron of type `A_n` is one way to realize the classical
    associahedron as defined in the :wikipedia:`Associahedron`.

    A polytopal realization of the associahedron can be found in [CFZ2002]_. The
    implementation is based on [CFZ2002]_, Theorem 1.5, Remark 1.6, and Corollary
    1.9.

    INPUT:

    - ``cartan_type`` -- a cartan type according to
      :class:`sage.combinat.root_system.cartan_type.CartanTypeFactory`

    - ``backend`` -- string (``'ppl'``); the backend to use;
      see :meth:`sage.geometry.polyhedron.constructor.Polyhedron`

    EXAMPLES::

        sage: Asso = polytopes.associahedron(['A',2]); Asso
        Generalized associahedron of type ['A', 2] with 5 vertices

        sage: sorted(Asso.Hrepresentation(), key=repr)
        [An inequality (-1, 0) x + 1 >= 0,
         An inequality (0, -1) x + 1 >= 0,
         An inequality (0, 1) x + 1 >= 0,
         An inequality (1, 0) x + 1 >= 0,
         An inequality (1, 1) x + 1 >= 0]

        sage: Asso.Vrepresentation()
        (A vertex at (1, -1), A vertex at (1, 1), A vertex at (-1, 1),
         A vertex at (-1, 0), A vertex at (0, -1))

        sage: polytopes.associahedron(['B',2])
        Generalized associahedron of type ['B', 2] with 6 vertices

    The two pictures of [CFZ2002]_ can be recovered with::

        sage: Asso = polytopes.associahedron(['A',3]); Asso
        Generalized associahedron of type ['A', 3] with 14 vertices
        sage: Asso.plot()  # long time
        Graphics3d Object

        sage: Asso = polytopes.associahedron(['B',3]); Asso
        Generalized associahedron of type ['B', 3] with 20 vertices
        sage: Asso.plot()  # long time
        Graphics3d Object

    TESTS::

        sage: sorted(polytopes.associahedron(['A',3]).vertices())
        [A vertex at (-3/2, 0, -1/2), A vertex at (-3/2, 0, 3/2),
         A vertex at (-3/2, 1, -3/2), A vertex at (-3/2, 2, -3/2),
         A vertex at (-3/2, 2, 3/2), A vertex at (-1/2, -1, -1/2),
         A vertex at (-1/2, 0, -3/2), A vertex at (1/2, -2, 1/2),
         A vertex at (1/2, -2, 3/2), A vertex at (3/2, -2, 1/2),
         A vertex at (3/2, -2, 3/2), A vertex at (3/2, 0, -3/2),
         A vertex at (3/2, 2, -3/2), A vertex at (3/2, 2, 3/2)]

        sage: sorted(polytopes.associahedron(['B',3]).vertices())
        [A vertex at (-3, 0, 0), A vertex at (-3, 0, 3),
         A vertex at (-3, 2, -2), A vertex at (-3, 4, -3),
         A vertex at (-3, 5, -3), A vertex at (-3, 5, 3),
         A vertex at (-2, 1, -2), A vertex at (-2, 3, -3),
         A vertex at (-1, -2, 0), A vertex at (-1, -1, -1),
         A vertex at (1, -4, 1), A vertex at (1, -3, 0),
         A vertex at (2, -5, 2), A vertex at (2, -5, 3),
         A vertex at (3, -5, 2), A vertex at (3, -5, 3),
         A vertex at (3, -3, 0), A vertex at (3, 3, -3),
         A vertex at (3, 5, -3), A vertex at (3, 5, 3)]

        sage: polytopes.associahedron(['A',4]).f_vector()
        (1, 42, 84, 56, 14, 1)
        sage: polytopes.associahedron(['B',4]).f_vector()
        (1, 70, 140, 90, 20, 1)

        sage: p1 = polytopes.associahedron(['A',4], backend='normaliz')   # optional - pynormaliz
        sage: TestSuite(p1).run(skip='_test_pickling')                    # optional - pynormaliz
        sage: p2 = polytopes.associahedron(['A',4], backend='cdd')
        sage: TestSuite(p2).run()
        sage: p3 = polytopes.associahedron(['A',4], backend='field')
        sage: TestSuite(p3).run()
    """
    cartan_type = CartanType(cartan_type)
    parent = Associahedra(QQ, cartan_type.rank(), backend)
    return parent(cartan_type)
def Associahedron(cartan_type):
    r"""
    Construct an associahedron

    An Associahedron

    The generalized associahedron is a polytopal complex with vertices in
    one-to-one correspondence with clusters in the cluster complex, and with
    edges between two vertices if and only if the associated two clusters
    intersect in codimension 1.

    The associahedron of type `A_n` is one way to realize the classical
    associahedron as defined in :wikipedia:`Associahedron`

    A polytopal realization of the associahedron can be found in [CFZ].  The
    implementation is based on [CFZ, Theorem 1.5, Remark 1.6, and Corollary
    1.9.].

    EXAMPLES::

        sage: Asso = Associahedron(['A',2]); Asso
        Generalized associahedron of type ['A', 2] with 5 vertices
        sage: sorted(Asso.Hrepresentation(), key=repr)
        [An inequality (-1, 0) x + 1 >= 0,
         An inequality (0, -1) x + 1 >= 0,
         An inequality (0, 1) x + 1 >= 0,
         An inequality (1, 0) x + 1 >= 0,
         An inequality (1, 1) x + 1 >= 0]
        sage: Asso.Vrepresentation()
        (A vertex at (1, -1), A vertex at (1, 1), A vertex at (-1, 1),
         A vertex at (-1, 0), A vertex at (0, -1))

        sage: Associahedron(['B',2])
        Generalized associahedron of type ['B', 2] with 6 vertices

   The two pictures of [CFZ] can be recovered with::

        sage: Asso = Associahedron(['A',3]); Asso
        Generalized associahedron of type ['A', 3] with 14 vertices
        sage: Asso.plot()

        sage: Asso = Associahedron(['B',3]); Asso
        Generalized associahedron of type ['B', 3] with 20 vertices
        sage: Asso.plot()

    TESTS::

        sage: sorted(Associahedron(['A',3]).vertices())
        [A vertex at (-3/2, 0, -1/2), A vertex at (-3/2, 0, 3/2),
         A vertex at (-3/2, 1, -3/2), A vertex at (-3/2, 2, -3/2),
         A vertex at (-3/2, 2, 3/2), A vertex at (-1/2, -1, -1/2),
         A vertex at (-1/2, 0, -3/2), A vertex at (1/2, -2, 1/2),
         A vertex at (1/2, -2, 3/2), A vertex at (3/2, -2, 1/2),
         A vertex at (3/2, -2, 3/2), A vertex at (3/2, 0, -3/2),
         A vertex at (3/2, 2, -3/2), A vertex at (3/2, 2, 3/2)]

        sage: sorted(Associahedron(['B',3]).vertices())
        [A vertex at (-3, 0, 0), A vertex at (-3, 0, 3),
         A vertex at (-3, 2, -2), A vertex at (-3, 4, -3),
         A vertex at (-3, 5, -3), A vertex at (-3, 5, 3),
         A vertex at (-2, 1, -2), A vertex at (-2, 3, -3),
         A vertex at (-1, -2, 0), A vertex at (-1, -1, -1),
         A vertex at (1, -4, 1), A vertex at (1, -3, 0),
         A vertex at (2, -5, 2), A vertex at (2, -5, 3),
         A vertex at (3, -5, 2), A vertex at (3, -5, 3),
         A vertex at (3, -3, 0), A vertex at (3, 3, -3),
         A vertex at (3, 5, -3), A vertex at (3, 5, 3)]

        sage: Associahedron(['A',4]).f_vector()
        (1, 42, 84, 56, 14, 1)
        sage: Associahedron(['B',4]).f_vector()
        (1, 70, 140, 90, 20, 1)

    REFERENCES:

    - [CFZ] Chapoton, Fomin, Zelevinsky - Polytopal realizations of
      generalized associahedra, arXiv:0202004.
    """
    cartan_type = CartanType(cartan_type)
    parent = Associahedra(QQ, cartan_type.rank())
    return parent(cartan_type)
Пример #6
0
    def __classcall_private__(cls, *args, **kwds):
        """
        Normalize input so we can inherit from spare 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
        """
        # Special case with 0 args and kwds has cartan type
        if "cartan_type" in kwds and len(args) == 0:
            args = (CartanType(kwds["cartan_type"]),)
        if len(args) == 0:
            data = []
            n = 0
            index_set = tuple()
            cartan_type = None
            subdivisions = None
        elif len(args) == 4 and isinstance(args[0], MatrixSpace): # For pickling
            return typecall(cls, args[0], args[1], args[2], args[3])
        elif isinstance(args[0], CartanMatrix):
            return args[0]
        else:
            cartan_type = None
            dynkin_diagram = None
            subdivisions = None
            try:
                cartan_type = CartanType(args[0])
                dynkin_diagram = cartan_type.dynkin_diagram()
            except (TypeError, ValueError):
                pass

            if dynkin_diagram is not None:
                n = cartan_type.rank()
                index_set = dynkin_diagram.index_set()
                reverse = dict((index_set[i], i) for i in range(len(index_set)))
                data = {(i, i): 2 for i in range(n)}
                for (i,j,l) in dynkin_diagram.edge_iterator():
                    data[(reverse[j], reverse[i])] = -l
            else:
                M = matrix(args[0])
                if not is_generalized_cartan_matrix(M):
                    raise ValueError("The input matrix is not a generalized Cartan matrix.")
                n = M.ncols()
                if "cartan_type" in kwds:
                    cartan_type = CartanType(kwds["cartan_type"])
                elif n == 1:
                    cartan_type = CartanType(['A', 1])
                elif kwds.get("cartan_type_check", True):
                    cartan_type = find_cartan_type_from_matrix(M)
                data = M.dict()
                subdivisions = M._subdivisions

            if len(args) == 1:
                if cartan_type is not None:
                    index_set = tuple(cartan_type.index_set())
                else:
                    index_set = tuple(range(M.ncols()))
            elif len(args) == 2:
                index_set = tuple(args[1])
                if len(index_set) != n and len(set(index_set)) != n:
                    raise ValueError("The given index set is not valid.")
            else:
                raise ValueError("Too many arguments.")

        mat = typecall(cls, MatrixSpace(ZZ, n, sparse=True), data, cartan_type, index_set)
        mat._subdivisions = subdivisions
        return mat
Пример #7
0
    def __classcall_private__(cls, cartan_type, shapes=None, shape=None):
        """
        Normalizes the input arguments to ensure unique representation,
        and to delegate the construction of spin tableaux.

        EXAMPLES::

            sage: T1 = crystals.Tableaux(CartanType(['A',3]), shape  = [2,2])
            sage: T2 = crystals.Tableaux(['A',3],             shape  = (2,2))
            sage: T3 = crystals.Tableaux(['A',3],             shapes = ([2,2],))
            sage: T2 is T1, T3 is T1
            (True, True)

            sage: T1 = crystals.Tableaux(['A', [1,1]], shape=[3,1,1,1])
            sage: T1
            Crystal of BKK tableaux of shape [3, 1, 1, 1] of gl(2|2)
            sage: T2 = crystals.Tableaux(['A', [1,1]], [3,1,1,1])
            sage: T1 is T2
            True

        """
        cartan_type = CartanType(cartan_type)
        if cartan_type.letter == 'A' and isinstance(cartan_type,
                                                    SuperCartanType_standard):
            if shape is None:
                shape = shapes
            shape = _Partitions(shape)
            from sage.combinat.crystals.bkk_crystals import CrystalOfBKKTableaux
            return CrystalOfBKKTableaux(cartan_type, shape=shape)
        if cartan_type.letter == 'Q':
            if any(shape[i] == shape[i + 1] for i in range(len(shape) - 1)):
                raise ValueError("not a strict partition")
            shape = _Partitions(shape)
            return CrystalOfQueerTableaux(cartan_type, shape=shape)
        n = cartan_type.rank()
        # standardize shape/shapes input into a tuple of tuples
        # of length n, or n+1 in type A
        assert operator.xor(shape is not None, shapes is not None)
        if shape is not None:
            shapes = (shape, )
        if cartan_type.type() == "A":
            n1 = n + 1
        else:
            n1 = n
        if not all(all(i == 0 for i in shape[n1:]) for shape in shapes):
            raise ValueError(
                "shapes should all have length at most equal to the rank or the rank + 1 in type A"
            )
        spin_shapes = tuple((tuple(shape) + (0, ) * (n1 - len(shape)))[:n1]
                            for shape in shapes)
        try:
            shapes = tuple(
                tuple(trunc(i) for i in shape) for shape in spin_shapes)
        except Exception:
            raise ValueError(
                "shapes should all be partitions or half-integer partitions")
        if spin_shapes == shapes:
            shapes = tuple(
                _Partitions(shape) if shape[n1 - 1] in NN else shape
                for shape in shapes)
            return super(CrystalOfTableaux,
                         cls).__classcall__(cls, cartan_type, shapes)

        # Handle the construction of a crystals of spin tableaux
        # Caveat: this currently only supports all shapes being half
        # integer partitions of length the rank for type B and D. In
        # particular, for type D, the spins all have to be plus or all
        # minus spins
        if any(len(sh) != n for sh in shapes):
            raise ValueError(
                "the length of all half-integer partition shapes should be the rank"
            )
        if any(2 * i % 2 != 1 for shape in spin_shapes for i in shape):
            raise ValueError(
                "shapes should be either all partitions or all half-integer partitions"
            )
        if any(
                any(i < j
                    for i, j in zip(shape, shape[1:-1] + (abs(shape[-1]), )))
                for shape in spin_shapes):
            raise ValueError("entries of each shape must be weakly decreasing")
        if cartan_type.type() == 'D':
            if all(i >= 0 for shape in spin_shapes for i in shape):
                S = CrystalOfSpinsPlus(cartan_type)
            elif all(shape[-1] < 0 for shape in spin_shapes):
                S = CrystalOfSpinsMinus(cartan_type)
            else:
                raise ValueError(
                    "in type D spins should all be positive or negative")
        else:
            if any(i < 0 for shape in spin_shapes for i in shape):
                raise ValueError("shapes should all be partitions")
            S = CrystalOfSpins(cartan_type)
        B = CrystalOfTableaux(cartan_type, shapes=shapes)
        T = TensorProductOfCrystals(S,
                                    B,
                                    generators=[[S.module_generators[0], x]
                                                for x in B.module_generators])
        T.rename("The crystal of tableaux of type %s and shape(s) %s" %
                 (cartan_type, list(list(shape) for shape in spin_shapes)))
        T.shapes = spin_shapes
        return T
Пример #8
0
    def Shi(self, data, K=QQ, names=None, m=1):
        r"""
        Return the Shi arrangement.

        INPUT:

        - ``data`` -- either an integer or a Cartan type (or coercible
          into; see "CartanType")

        - ``K`` -- field (default:``QQ``)

        - ``names`` -- tuple of strings or ``None`` (default); the
          variable names for the ambient space

        - ``m`` -- integer (default: 1)

        OUTPUT:

        - If ``data`` is an integer `n`, return the Shi arrangement in
          dimension `n`, i.e. the set of `n(n-1)` hyperplanes:
          `\{ x_i - x_j = 0,1 : 1 \leq i \leq j \leq n \}`. This corresponds
          to the Shi arrangement of Cartan type `A_{n-1}`.

        - If ``data`` is a Cartan type, return the Shi arrangement of given
          type.

        - If `m > 1`, return the `m`-extended Shi arrangement of given type.

        The `m`-extended Shi arrangement of a given crystallographic
        Cartan type is defined by the inner product
        `\langle a,x \rangle = k` for `-m < k \leq m` and
        `a \in \Phi^+` is a positive root of the root system `\Phi`.

        EXAMPLES::

            sage: hyperplane_arrangements.Shi(4)
            Arrangement of 12 hyperplanes of dimension 4 and rank 3
            sage: hyperplane_arrangements.Shi("A3")
            Arrangement of 12 hyperplanes of dimension 4 and rank 3
            sage: hyperplane_arrangements.Shi("A3",m=2)
            Arrangement of 24 hyperplanes of dimension 4 and rank 3
            sage: hyperplane_arrangements.Shi("B4")
            Arrangement of 32 hyperplanes of dimension 4 and rank 4
            sage: hyperplane_arrangements.Shi("B4",m=3)
            Arrangement of 96 hyperplanes of dimension 4 and rank 4
            sage: hyperplane_arrangements.Shi("C3")
            Arrangement of 18 hyperplanes of dimension 3 and rank 3
            sage: hyperplane_arrangements.Shi("D4",m=3)
            Arrangement of 72 hyperplanes of dimension 4 and rank 4
            sage: hyperplane_arrangements.Shi("E6")
            Arrangement of 72 hyperplanes of dimension 8 and rank 6
            sage: hyperplane_arrangements.Shi("E6",m=2)
            Arrangement of 144 hyperplanes of dimension 8 and rank 6

        If the Cartan type is not crystallographic, the Shi arrangement
        is not defined::

            sage: hyperplane_arrangements.Shi("H4")
            Traceback (most recent call last):
            ...
            NotImplementedError: Shi arrangements are not defined for non crystallographic Cartan types

        The characteristic polynomial is pre-computed using the results
        of [Ath1996]_::

            sage: hyperplane_arrangements.Shi("A3").characteristic_polynomial()
            x^4 - 12*x^3 + 48*x^2 - 64*x
            sage: hyperplane_arrangements.Shi("A3",m=2).characteristic_polynomial()
            x^4 - 24*x^3 + 192*x^2 - 512*x
            sage: hyperplane_arrangements.Shi("C3").characteristic_polynomial()
            x^3 - 18*x^2 + 108*x - 216
            sage: hyperplane_arrangements.Shi("E6").characteristic_polynomial()
            x^8 - 72*x^7 + 2160*x^6 - 34560*x^5 + 311040*x^4 - 1492992*x^3 + 2985984*x^2
            sage: hyperplane_arrangements.Shi("B4",m=3).characteristic_polynomial()
            x^4 - 96*x^3 + 3456*x^2 - 55296*x + 331776

        TESTS::

            sage: h = hyperplane_arrangements.Shi(4)
            sage: h.characteristic_polynomial()
            x^4 - 12*x^3 + 48*x^2 - 64*x
            sage: h.characteristic_polynomial.clear_cache()  # long time
            sage: h.characteristic_polynomial()              # long time
            x^4 - 12*x^3 + 48*x^2 - 64*x
            sage: h = hyperplane_arrangements.Shi("A3",m=2)
            sage: h.characteristic_polynomial()
            x^4 - 24*x^3 + 192*x^2 - 512*x
            sage: h.characteristic_polynomial.clear_cache()
            sage: h.characteristic_polynomial()
            x^4 - 24*x^3 + 192*x^2 - 512*x
            sage: h = hyperplane_arrangements.Shi("B3",m=3)
            sage: h.characteristic_polynomial()
            x^3 - 54*x^2 + 972*x - 5832
            sage: h.characteristic_polynomial.clear_cache()
            sage: h.characteristic_polynomial()
            x^3 - 54*x^2 + 972*x - 5832
        """
        if data in NN:
            cartan_type = CartanType(["A", data - 1])
        else:
            cartan_type = CartanType(data)
        if not cartan_type.is_crystallographic():
            raise NotImplementedError(
                "Shi arrangements are not defined for non crystallographic Cartan types"
            )
        n = cartan_type.rank()
        h = cartan_type.coxeter_number()
        Ra = RootSystem(cartan_type).ambient_space()
        PR = Ra.positive_roots()
        d = Ra.dimension()
        H = make_parent(K, d, names)
        x = H.gens()
        hyperplanes = []

        for a in PR:
            for const in range(-m + 1, m + 1):
                hyperplanes.append(sum(a[j] * x[j] for j in range(d)) - const)
        A = H(*hyperplanes)
        x = polygen(QQ, 'x')
        charpoly = x**(d - n) * (x - m * h)**n
        A.characteristic_polynomial.set_cache(charpoly)
        return A
Пример #9
0
def Associahedron(cartan_type):
    r"""
    Construct an associahedron.

    The generalized associahedron is a polytopal complex with vertices in
    one-to-one correspondence with clusters in the cluster complex, and with
    edges between two vertices if and only if the associated two clusters
    intersect in codimension 1.

    The associahedron of type `A_n` is one way to realize the classical
    associahedron as defined in the :wikipedia:`Associahedron`.

    A polytopal realization of the associahedron can be found in [CFZ]_. The
    implementation is based on [CFZ]_, Theorem 1.5, Remark 1.6, and Corollary
    1.9.

    EXAMPLES::

        sage: Asso = polytopes.associahedron(['A',2]); Asso
        Generalized associahedron of type ['A', 2] with 5 vertices

        sage: sorted(Asso.Hrepresentation(), key=repr)
        [An inequality (-1, 0) x + 1 >= 0,
         An inequality (0, -1) x + 1 >= 0,
         An inequality (0, 1) x + 1 >= 0,
         An inequality (1, 0) x + 1 >= 0,
         An inequality (1, 1) x + 1 >= 0]

        sage: Asso.Vrepresentation()
        (A vertex at (1, -1), A vertex at (1, 1), A vertex at (-1, 1),
         A vertex at (-1, 0), A vertex at (0, -1))

        sage: polytopes.associahedron(['B',2])
        Generalized associahedron of type ['B', 2] with 6 vertices

    The two pictures of [CFZ]_ can be recovered with::

        sage: Asso = polytopes.associahedron(['A',3]); Asso
        Generalized associahedron of type ['A', 3] with 14 vertices
        sage: Asso.plot()
        Graphics3d Object

        sage: Asso = polytopes.associahedron(['B',3]); Asso
        Generalized associahedron of type ['B', 3] with 20 vertices
        sage: Asso.plot()
        Graphics3d Object

    TESTS::

        sage: sorted(polytopes.associahedron(['A',3]).vertices())
        [A vertex at (-3/2, 0, -1/2), A vertex at (-3/2, 0, 3/2),
         A vertex at (-3/2, 1, -3/2), A vertex at (-3/2, 2, -3/2),
         A vertex at (-3/2, 2, 3/2), A vertex at (-1/2, -1, -1/2),
         A vertex at (-1/2, 0, -3/2), A vertex at (1/2, -2, 1/2),
         A vertex at (1/2, -2, 3/2), A vertex at (3/2, -2, 1/2),
         A vertex at (3/2, -2, 3/2), A vertex at (3/2, 0, -3/2),
         A vertex at (3/2, 2, -3/2), A vertex at (3/2, 2, 3/2)]

        sage: sorted(polytopes.associahedron(['B',3]).vertices())
        [A vertex at (-3, 0, 0), A vertex at (-3, 0, 3),
         A vertex at (-3, 2, -2), A vertex at (-3, 4, -3),
         A vertex at (-3, 5, -3), A vertex at (-3, 5, 3),
         A vertex at (-2, 1, -2), A vertex at (-2, 3, -3),
         A vertex at (-1, -2, 0), A vertex at (-1, -1, -1),
         A vertex at (1, -4, 1), A vertex at (1, -3, 0),
         A vertex at (2, -5, 2), A vertex at (2, -5, 3),
         A vertex at (3, -5, 2), A vertex at (3, -5, 3),
         A vertex at (3, -3, 0), A vertex at (3, 3, -3),
         A vertex at (3, 5, -3), A vertex at (3, 5, 3)]

        sage: polytopes.associahedron(['A',4]).f_vector()
        (1, 42, 84, 56, 14, 1)
        sage: polytopes.associahedron(['B',4]).f_vector()
        (1, 70, 140, 90, 20, 1)
    """
    cartan_type = CartanType(cartan_type)
    parent = Associahedra(QQ, cartan_type.rank())
    return parent(cartan_type)
Пример #10
0
    def __classcall_private__(cls, *args, **kwds):
        """
        Normalize input so we can inherit from spare 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
        """
        # Special case with 0 args and kwds has cartan type
        if "cartan_type" in kwds and len(args) == 0:
            args = (CartanType(kwds["cartan_type"]), )
        if len(args) == 0:
            data = []
            n = 0
            index_set = tuple()
            cartan_type = None
            subdivisions = None
        elif len(args) == 4 and isinstance(args[0],
                                           MatrixSpace):  # For pickling
            return typecall(cls, args[0], args[1], args[2], args[3])
        elif isinstance(args[0], CartanMatrix):
            return args[0]
        else:
            cartan_type = None
            dynkin_diagram = None
            subdivisions = None
            try:
                cartan_type = CartanType(args[0])
                dynkin_diagram = cartan_type.dynkin_diagram()
            except (TypeError, ValueError):
                pass

            if dynkin_diagram is not None:
                n = cartan_type.rank()
                index_set = dynkin_diagram.index_set()
                reverse = dict(
                    (index_set[i], i) for i in range(len(index_set)))
                data = {(i, i): 2 for i in range(n)}
                for (i, j, l) in dynkin_diagram.edge_iterator():
                    data[(reverse[j], reverse[i])] = -l
            else:
                M = matrix(args[0])
                if not is_generalized_cartan_matrix(M):
                    raise ValueError(
                        "The input matrix is not a generalized Cartan matrix.")
                n = M.ncols()
                if "cartan_type" in kwds:
                    cartan_type = CartanType(kwds["cartan_type"])
                elif n == 1:
                    cartan_type = CartanType(['A', 1])
                elif kwds.get("cartan_type_check", True):
                    cartan_type = find_cartan_type_from_matrix(M)
                data = M.dict()
                subdivisions = M._subdivisions

            if len(args) == 1:
                if cartan_type is not None:
                    index_set = tuple(cartan_type.index_set())
                else:
                    index_set = tuple(range(M.ncols()))
            elif len(args) == 2:
                index_set = tuple(args[1])
                if len(index_set) != n and len(set(index_set)) != n:
                    raise ValueError("The given index set is not valid.")
            else:
                raise ValueError("Too many arguments.")

        mat = typecall(cls, MatrixSpace(ZZ, n, sparse=True), data, cartan_type,
                       index_set)
        mat._subdivisions = subdivisions
        return mat