Example #1
0
    def ambient(self):
        r"""
        Return the ambient space from which ``self`` is a quotient.

        EXAMPLES::

            sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6); S.ambient()
            Integer vectors that sum to 6
            sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6, max_part=12); S.ambient()
            Integer vectors that sum to 6 with constraints: max_part=12

        .. todo::

         Integer vectors should accept ``max_part`` as a single argument, and the following should change::

            sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=12); S.ambient()
            Integer vectors

        """
        if self._sum is not None:
            if self._max_part <= -1:
                return IntegerVectors(n=self._sum)
            else:
                return IntegerVectors(n=self._sum, max_part=self._max_part)
        else:
            # Fix me once max_part should be accepted as a single
            # argument for integer vectors
            return IntegerVectors(max_part=self._max_part)
Example #2
0
def homogenous_symmetric_function(j, x):
    r"""
    Return a complete homogeneous symmetric polynomial
    (:wikipedia:`Complete_homogeneous_symmetric_polynomial`).

    INPUT:

    - ``j`` -- the degree as a nonnegative integer

    - ``x`` -- an iterable of variables

    OUTPUT:

    A polynomial of the common parent of all entries of ``x``

    EXAMPLES::

        sage: from sage.rings.polynomial.omega import homogenous_symmetric_function
        sage: P = PolynomialRing(ZZ, 'X', 3)
        sage: homogenous_symmetric_function(0, P.gens())
        1
        sage: homogenous_symmetric_function(1, P.gens())
        X0 + X1 + X2
        sage: homogenous_symmetric_function(2, P.gens())
        X0^2 + X0*X1 + X1^2 + X0*X2 + X1*X2 + X2^2
        sage: homogenous_symmetric_function(3, P.gens())
        X0^3 + X0^2*X1 + X0*X1^2 + X1^3 + X0^2*X2 +
        X0*X1*X2 + X1^2*X2 + X0*X2^2 + X1*X2^2 + X2^3
    """
    from sage.combinat.integer_vector import IntegerVectors
    from sage.misc.misc_c import prod

    return sum(
        prod(xx**pp for xx, pp in zip(x, p))
        for p in IntegerVectors(j, length=len(x)))
Example #3
0
    def __iter__(self):
        """
        Iterate through the subsets of size ``self._k`` of the multiset
        ``self._s``.

        Note that each subset is represented by a list of the
        elements rather than a set since we can have multiplicities (no
        multiset data structure yet in sage).

        EXAMPLES::

            sage: S = Subsets([1,2,2,3],2, submultiset=True)
            sage: S.list()
            [[1, 2], [1, 3], [2, 2], [2, 3]]

        Check that :trac:`28588` is fixed::

            sage: Subsets([3,2,2], submultiset=True).list()
            [[], [3], [2], [3, 2], [2, 2], [3, 2, 2]]

        """
        from sage.combinat.integer_vector import IntegerVectors
        elts = self._keys
        for iv in IntegerVectors(self._k,
                                 len(self._d),
                                 outer=[self._d[k] for k in elts]):
            yield sum([[elts[i]] * iv[i] for i in range(len(iv))], [])
    def ambient(self):
        r"""
        Return the ambient space from which ``self`` is a quotient.

        EXAMPLES::

            sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6); S.ambient()
            Integer vectors that sum to 6
            sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6, max_part=12); S.ambient()
            Integer vectors that sum to 6 with constraints: max_part=12
            sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=12); S.ambient()
            Integer vectors with constraints: max_part=12
        """
        if self._sum is not None:
            if self._max_part <= -1:
                return IntegerVectors(n=self._sum)
            else:
                return IntegerVectors(n=self._sum, max_part=self._max_part)
        else:
            return IntegerVectors(max_part=self._max_part)
    def ambient(self):
        r"""
        Return the ambient space from which ``self`` is a quotient.

        EXAMPLES::

            sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
            sage: S.ambient()
            Integer vectors of length 4
        """
        return IntegerVectors(length=self.n)
Example #6
0
    def ambient(self):
        r"""
        Return the ambient space from which ``self`` is a quotient.

        EXAMPLES::

            sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
            sage: S.ambient()
            Integer vectors
        """
        # TODO: Fix me once 'IntegerVectors(length=bla)' will return
        # the integer vectors of length bla
        return IntegerVectors(length=self.n)
Example #7
0
    def __iter__(self):
        """
        EXAMPLES::

            sage: from sage.combinat.words.shuffle_product import ShuffleProduct_overlapping_r
            sage: w, u = Word([1,2]), Word([3,4])
            sage: ShuffleProduct_overlapping_r(w,u,1).list()
            [word: 424, word: 154, word: 442, word: 136, word: 352, word: 316]
            sage: w, u = map(Words(range(1,7)), [[1,2], [3,4]])
            sage: W = Words(range(1,7))
            sage: w, u = W([1,2]), W([3,4])
            sage: ShuffleProduct_overlapping_r(w, u, 1).list() #indirect doctest
            [word: 424, word: 154, word: 442, word: 136, word: 352, word: 316]
        """
        W = self._w1.parent()

        m = len(self._w1)
        n = len(self._w2)
        r = self.r

        wc1, wc2 = self._w1, self._w2

        blank = [0] * (m + n - r)
        for iv in IntegerVectors(m, m + n - r, max_part=1):
            w = blank[:]
            filled_places = []
            unfilled_places = []
            #Fill in w1 into the iv slots
            i = 0
            for j in range(len(iv)):
                if iv[j] == 1:
                    w[j] = wc1[i]
                    i += 1
                    filled_places.append(j)
                else:
                    unfilled_places.append(j)

            #Choose r of these filled places
            for subset in Subsets(filled_places, r):
                places_to_fill = unfilled_places + list(subset)
                places_to_fill.sort()

                #Fill in w2 into the places
                i = 0
                res = w[:]
                for j in places_to_fill:
                    res[j] += wc2[i]
                    i += 1

                yield W(res)
Example #8
0
    def __iter__(self):
        """
        Iterates through the subsets of size ``self._k`` of the multiset
        ``self._s``. Note that each subset is represented by a list of the
        elements rather than a set since we can have multiplicities (no
        multiset data structure yet in sage).

        EXAMPLES::

            sage: S = Subsets([1,2,2,3],2, submultiset=True)
            sage: S.list()
            [[1, 2], [1, 3], [2, 2], [2, 3]]
        """
        from sage.combinat.integer_vector import IntegerVectors
        for iv in IntegerVectors(self._k, len(self._indices), outer=self._multiplicities):
            yield sum([ [self._s[self._indices[i]]]*iv[i] for i in range(len(iv))], [])
    def ambient(self):
        r"""
        Return the ambient space from which ``self`` is a quotient.

        EXAMPLES::

            sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]))
            sage: S.ambient()
            Integer vectors
        """
        ## TODO: Fix me once 'IntegerVectors(length=bla)' will return
        ## the integer vectors of length bla
        #return IntegerVectors(length=self.n)

        # (#17927) The previous line was replaced by the following, as
        # IntegerVectors(length=k) is invalid at the moment.
        return IntegerVectors()
Example #10
0
    def __iter__(self):
        """
        Return an iterator for the words in the
        shuffle product of ``w1`` and ``w2``.

        EXAMPLES::

            sage: from sage.combinat.words.shuffle_product import ShuffleProduct_w1w2
            sage: w, u = map(Words("abcd"), ["ab", "cd"])
            sage: S = ShuffleProduct_w1w2(w,u)
            sage: S.list() #indirect test
            [word: abcd, word: acbd, word: acdb, word: cabd, word: cadb, word: cdab]
        """
        n1 = len(self._w1)
        n2 = len(self._w2)
        for iv in IntegerVectors(n1, n1 + n2, max_part=1):
            yield self._proc(iv)
Example #11
0
    def __iter__(self):
        """
        TESTS::

            sage: LyndonWords(3,3).list() # indirect doctest
            [word: 112, word: 113, word: 122, word: 123, word: 132, word: 133, word: 223, word: 233]
        """
        for c in IntegerVectors(self._k, self._n):
            cf = []
            nonzero_indices = []
            for i, x in enumerate(c):
                if x:
                    nonzero_indices.append(i)
                    cf.append(x)
            for lw in LyndonWords_evaluation(Composition(cf)):
                yield self._words([nonzero_indices[x - 1] + 1 for x in lw],
                                  check=False)
Example #12
0
def _list_all_decreasing_runs(word, m):
    """
    List all possible decreasing runs into ``m`` factors for ``word`` in a
    0-Hecke monoid.

    EXAMPLES::

        sage: from sage.combinat.crystals.fully_commutative_stable_grothendieck import _list_all_decreasing_runs
        sage: _list_all_decreasing_runs([2, 1, 2, 1], 3)
        [[2, 2, 1, 1], [3, 2, 1, 1], [3, 3, 1, 1], [3, 3, 2, 1], [3, 3, 2, 2]]
    """
    from sage.combinat.integer_vector import IntegerVectors
    J = _jumps(word)
    jump_vector = [1] + [int(j in J) for j in range(1, len(word))]
    I = sorted(IntegerVectors(m - 1 - len(J), len(word) + 1), reverse=True)
    P = [[elt[i] + jump_vector[i] for i in range(len(word))] for elt in I]
    V = [[m + 1 - sum(elt[:i + 1]) for i in range(len(elt))] for elt in P]
    return V
Example #13
0
 def homogeneous_monomials(self,
                           fibre_degrees,
                           weights,
                           max_differential_orders=None):
     fibre_vars = self.fibre_variables()
     if not len(fibre_degrees) == len(fibre_vars):
         raise ValueError(
             'length of fibre_degrees vector must match number of fibre variables'
         )
     base_vars = self.base_variables()
     if not len(weights) == len(base_vars):
         raise ValueError(
             'length of weights vector must match number of base variables')
     monomials = []
     fibre_degree = sum(fibre_degrees)
     fibre_indexes = {}
     fibre_idx = 0
     for i in range(len(fibre_degrees)):
         for j in range(fibre_degrees[i]):
             fibre_indexes[fibre_idx] = i
             fibre_idx += 1
     proto = sum([[fibre_vars[i]] * fibre_degrees[i]
                  for i in range(len(fibre_degrees))], [])
     for V in product(*[IntegerVectors(w, fibre_degree) for w in weights]):
         total_differential_order = [0 for i in range(fibre_degree)]
         term = [p for p in proto]
         skip = False
         for j in range(fibre_degree):
             fibre_idx = fibre_indexes[j]
             for i in range(len(base_vars)):
                 if V[i][j] > 0:
                     total_differential_order[j] += V[i][j]
                     if max_differential_orders is not None and total_differential_order[
                             j] > max_differential_orders[fibre_idx]:
                         skip = True
                         break
                     term[j] = term[j].total_derivative(*([base_vars[i]] *
                                                          V[i][j]))
             if skip:
                 break
         if not skip:
             monomials.append(prod(term))
     return monomials
Example #14
0
 def __init__(self, base_ring, fibre_names, base_names,
              max_differential_orders):
     self._fibre_names = tuple(fibre_names)
     self._base_names = tuple(base_names)
     self._max_differential_orders = tuple(max_differential_orders)
     base_dim = len(self._base_names)
     fibre_dim = len(self._fibre_names)
     jet_names = []
     idx_to_name = {}
     for fibre_idx in range(fibre_dim):
         u = self._fibre_names[fibre_idx]
         idx_to_name[(fibre_idx, ) + tuple([0] * base_dim)] = u
         for d in range(1, max_differential_orders[fibre_idx] + 1):
             for multi_index in IntegerVectors(d, base_dim):
                 v = '{}_{}'.format(
                     u, ''.join(self._base_names[i] * multi_index[i]
                                for i in range(base_dim)))
                 jet_names.append(v)
                 idx_to_name[(fibre_idx, ) + tuple(multi_index)] = v
     self._polynomial_ring = PolynomialRing(
         base_ring, base_names + fibre_names + tuple(jet_names))
     self._idx_to_var = {
         idx: self._polynomial_ring(idx_to_name[idx])
         for idx in idx_to_name
     }
     self._var_to_idx = {
         jet: idx
         for (idx, jet) in self._idx_to_var.items()
     }
     # for conversion:
     base_vars = [var(b) for b in self._base_names]
     symbolic_functions = [
         function(f)(*base_vars) for f in self._fibre_names
     ]
     self._subs_jet_vars = SubstituteJetVariables(symbolic_functions)
     self._subs_tot_ders = SubstituteTotalDerivatives(symbolic_functions)
Example #15
0
    def invariants_of_degree(self, deg, chi=None, R=None):
        r"""
        Return the (relative) invariants of given degree for this group.

        For this group, compute the invariants of degree ``deg``
        with respect to the group character ``chi``. The method
        is to project each possible monomial of degree ``deg`` via
        the Reynolds operator. Note that if the polynomial ring ``R``
        is specified it's base ring may be extended if the resulting
        invariant is defined over a bigger field.

        INPUT:

        - ``degree`` -- a positive integer

        - ``chi`` -- (default: trivial character) a linear group character of this group

        - ``R`` -- (optional) a polynomial ring

        OUTPUT: list of polynomials

        EXAMPLES::

            sage: Gr = MatrixGroup(SymmetricGroup(2))
            sage: sorted(Gr.invariants_of_degree(3))
            [x0^2*x1 + x0*x1^2, x0^3 + x1^3]
            sage: R.<x,y> = QQ[]
            sage: sorted(Gr.invariants_of_degree(4, R=R))
            [x^2*y^2, x^3*y + x*y^3, x^4 + y^4]

        ::

            sage: R.<x,y,z> = QQ[]
            sage: Gr = MatrixGroup(DihedralGroup(3))
            sage: ct = Gr.character_table()
            sage: chi = Gr.character(ct[0])
            sage: all(f(*(g.matrix()*vector(R.gens()))) == chi(g)*f
            ....: for f in Gr.invariants_of_degree(3, R=R, chi=chi) for g in Gr)
            True

        ::

            sage: i = GF(7)(3)
            sage: G = MatrixGroup([[i^3,0,0,-i^3],[i^2,0,0,-i^2]])
            sage: G.invariants_of_degree(25)
            []

        ::

            sage: G = MatrixGroup(SymmetricGroup(5))
            sage: R = QQ['x,y']
            sage: G.invariants_of_degree(3, R=R)
            Traceback (most recent call last):
            ...
            TypeError: number of variables in polynomial ring must match size of matrices

        ::

            sage: K.<i> = CyclotomicField(4)
            sage: G =  MatrixGroup(CyclicPermutationGroup(3))
            sage: chi = G.character(G.character_table()[1])
            sage: R.<x,y,z> = K[]
            sage: sorted(G.invariants_of_degree(2, R=R, chi=chi))
            [x*y + (2*izeta3^3 + 3*izeta3^2 + 8*izeta3 + 3)*x*z + (-2*izeta3^3 - 3*izeta3^2 - 8*izeta3 - 4)*y*z,
             x^2 + (-2*izeta3^3 - 3*izeta3^2 - 8*izeta3 - 4)*y^2 + (2*izeta3^3 + 3*izeta3^2 + 8*izeta3 + 3)*z^2]

        ::

            sage: S3 = MatrixGroup(SymmetricGroup(3))
            sage: chi = S3.character(S3.character_table()[0])
            sage: sorted(S3.invariants_of_degree(5, chi=chi))
            [x0^3*x1^2 - x0^2*x1^3 - x0^3*x2^2 + x1^3*x2^2 + x0^2*x2^3 - x1^2*x2^3,
            x0^4*x1 - x0*x1^4 - x0^4*x2 + x1^4*x2 + x0*x2^4 - x1*x2^4]
        """
        D = self.degree()
        deg = int(deg)
        if deg <= 0:
            raise ValueError("degree must be a positive integer")
        if R is None:
            R = PolynomialRing(self.base_ring(), 'x', D)
        elif R.ngens() != D:
            raise TypeError(
                "number of variables in polynomial ring must match size of matrices"
            )

        ms = self.molien_series(prec=deg + 1, chi=chi)
        if ms[deg].is_zero():
            return []
        inv = set()
        for e in IntegerVectors(deg, D):
            F = self.reynolds_operator(R.monomial(*e), chi=chi)
            if not F.is_zero():
                F = F / F.lc()
                inv.add(F)
                if len(inv) == ms[deg]:
                    break
        return list(inv)
Example #16
0
    def is_perfect(self, level=1):
        r"""
        Checks whether the crystal ``self`` is perfect (of level ``level``).

        INPUT:

        - ``level`` -- (default: 1) positive integer

        A crystal `\mathcal{B}` is perfect of level `\ell` if:

        #. `\mathcal{B}` is isomorphic to the crystal graph of a finite-dimensional `U_q^{'}(\mathfrak{g})`-module.
        #. `\mathcal{B}\otimes \mathcal{B}` is connected.
        #. There exists a `\lambda\in X`, such that `\mathrm{wt}(\mathcal{B}) \subset \lambda
           + \sum_{i\in I} \mathbb{Z}_{\le 0} \alpha_i` and there is a unique element in `\mathcal{B}` of classical
           weight `\lambda`.
        #. `\forall b \in \mathcal{B}, \mathrm{level}(\varepsilon (b)) \geq \ell`.
        #. `\forall \Lambda` dominant weights of level `\ell`, there exist unique elements
           `b_{\Lambda}, b^{\Lambda} \in \mathcal{B}`,
           such that `\varepsilon ( b_{\Lambda}) = \Lambda = \varphi( b^{\Lambda})`.

        Points (1)-(3) are known to hold. This method checks points (4) and (5).

        EXAMPLES::

            sage: C = CartanType(['C',2,1])
            sage: R = RootSystem(C)
            sage: La = R.weight_space().basis()
            sage: LS = crystals.ProjectedLevelZeroLSPaths(La[1])
            sage: LS.is_perfect()
            False
            sage: LS = crystals.ProjectedLevelZeroLSPaths(La[2])
            sage: LS.is_perfect()
            True

            sage: C = CartanType(['E',6,1])
            sage: R = RootSystem(C)
            sage: La = R.weight_space().basis()
            sage: LS = crystals.ProjectedLevelZeroLSPaths(La[1])
            sage: LS.is_perfect()
            True
            sage: LS.is_perfect(2)
            False

            sage: C = CartanType(['D',4,1])
            sage: R = RootSystem(C)
            sage: La = R.weight_space().basis()
            sage: all(crystals.ProjectedLevelZeroLSPaths(La[i]).is_perfect() for i in [1,2,3,4])
            True

            sage: C = CartanType(['A',6,2])
            sage: R = RootSystem(C)
            sage: La = R.weight_space().basis()
            sage: LS = crystals.ProjectedLevelZeroLSPaths(La[1]+La[2])
            sage: LS.is_perfect()
            True
            sage: LS.is_perfect(2)
            False
        """
        MPhi = []
        for b in self:
            p = b.Phi().level()
            assert p == b.Epsilon().level()
            if p < level:
                return False
            if p == level:
                MPhi += [b]
        weights = []
        I = self.index_set()
        rank = len(I)
        La = self.weight_lattice_realization().basis()
        from sage.combinat.integer_vector import IntegerVectors
        for n in range(1, level + 1):
            for c in IntegerVectors(n, rank):
                w = sum(c[i] * La[i] for i in I)
                if w.level() == level:
                    weights.append(w)
        return sorted([b.Phi() for b in MPhi]) == sorted(weights)
Example #17
0
    def _linear_system_as_kernel(self, d, pt, m):
        """
        Return a matrix whose kernel consists of the coefficient vectors
        of the degree d hypersurfaces (wrt lexicographic ordering of its
        monomials) with multiplicity at least m at pt.

        INPUT:

        -  ``d`` -- a nonnegative integer

        -  ``pt`` -- a point of self (possibly represented by a list with at \
                     least one component equal to 1)

        -  ``m`` -- a nonnegative integer

        OUTPUT:

        A matrix of size `{m-1+n \choose n}` x `{d+n \choose n}` where n is the
        relative dimension of self. The base ring of the matrix is a ring that
        contains the base ring of self and the coefficients of the given point.

        EXAMPLES:

        If the degree `d` is 0, then a matrix consisting of the first unit vector
        is returned::

            sage: P = ProjectiveSpace(GF(5), 2, names='x')
            sage: pt = P([1, 1, 1])
            sage: P._linear_system_as_kernel(0, pt, 3)
            [1]
            [0]
            [0]
            [0]
            [0]
            [0]

        If the multiplcity `m` is 0, then the a matrix with zero rows is returned::

            sage: P = ProjectiveSpace(GF(5), 2, names='x')
            sage: pt = P([1, 1, 1])
            sage: M = P._linear_system_as_kernel(2, pt, 0)
            sage: [M.nrows(), M.ncols()]
            [0, 6]

        The base ring does not need to be a field or even an integral domain.
        In this case, the point can be given by a list::

            sage: R = Zmod(4)
            sage: P = ProjectiveSpace(R, 2, names='x')
            sage: pt = [R(1), R(3), R(0)]
            sage: P._linear_system_as_kernel(3, pt, 2)
            [1 3 0 1 0 0 3 0 0 0]
            [0 1 0 2 0 0 3 0 0 0]
            [0 0 1 0 3 0 0 1 0 0]

        When representing a point by a list at least one component must be 1
        (even when the base ring is a field and the list gives a well-defined
        point in projective space)::

            sage: R = GF(5)
            sage: P = ProjectiveSpace(R, 2, names='x')
            sage: pt = [R(3), R(3), R(0)]
            sage: P._linear_system_as_kernel(3, pt, 2)
            Traceback (most recent call last):
            ...
            TypeError: At least one component of pt=[3, 3, 0] must be equal
                          to 1

        The components of the list do not have to be elements of the base ring
        of the projective space. It suffices if there exists a common parent.
        For example, the kernel of the following matrix corresponds to
        hypersurfaces of degree 2 in 3-space with multiplicity at least 2 at a
        general point in the third affine patch::

            sage: P = ProjectiveSpace(QQ,3,names='x')
            sage: RPol.<t0,t1,t2,t3> = PolynomialRing(QQ,4)
            sage: pt = [t0,t1,1,t3]
            sage: P._linear_system_as_kernel(2,pt,2)
            [ 2*t0    t1     1    t3     0     0     0     0     0     0]
            [    0    t0     0     0  2*t1     1    t3     0     0     0]
            [ t0^2 t0*t1    t0 t0*t3  t1^2    t1 t1*t3     1    t3  t3^2]
            [    0     0     0    t0     0     0    t1     0     1  2*t3]

        .. TODO::

            Use this method as starting point to implement a class
            LinearSystem for linear systems of hypersurfaces.

        """
        if not isinstance(d, (int, Integer)):
            raise TypeError('The argument d=%s must be an integer' % d)
        if d < 0:
            raise ValueError('The integer d=%s must be nonnegative' % d)
        if not isinstance(pt, (list, tuple, \
                               SchemeMorphism_point_projective_ring)):
            raise TypeError('The argument pt=%s must be a list, tuple, or '
                            'point on a projective space' % pt)
        pt, R = prepare(pt, None)
        n = self.dimension_relative()
        if not len(pt) == n + 1:
            raise TypeError('The sequence pt=%s must have %s '
                            'components' % (pt, n + 1))
        if not R.has_coerce_map_from(self.base_ring()):
            raise TypeError('Unable to find a common ring for all elements')
        try:
            i = pt.index(1)
        except Exception:
            raise TypeError('At least one component of pt=%s must be equal '
                            'to 1' % pt)
        pt = pt[:i] + pt[i + 1:]
        if not isinstance(m, (int, Integer)):
            raise TypeError('The argument m=%s must be an integer' % m)
        if m < 0:
            raise ValueError('The integer m=%s must be nonnegative' % m)
        # the components of partials correspond to partial derivatives
        # of order at most m-1 with respect to n variables
        partials = IntegerVectors(m - 1, n + 1).list()
        # the components of monoms correspond to monomials of degree
        # at most d in n variables
        monoms = IntegerVectors(d, n + 1).list()
        M = matrix(R, len(partials), len(monoms))
        for row in range(M.nrows()):
            e = partials[row][:i] + partials[row][i + 1:]
            for col in range(M.ncols()):
                f = monoms[col][:i] + monoms[col][i + 1:]
                if min([f[j] - e[j] for j in range(n)]) >= 0:
                    M[row,col] = prod([binomial(f[j],e[j])*pt[j]**(f[j]-e[j]) \
                               for j in filter(lambda k: f[k]>e[k], range(n))])
        return M
Example #18
0
    def __iter__(self):
        """
        EXAMPLES::

            sage: from sage.combinat.words.shuffle_product import ShuffleProduct_overlapping_r
            sage: w, u = Word([1,2]), Word([3,4])
            sage: ShuffleProduct_overlapping_r(w,u,1).list()
            [word: 424, word: 154, word: 442, word: 136, word: 352, word: 316]
            sage: w, u = map(Words(range(1,7)), [[1,2], [3,4]])
            sage: W = Words(range(1,7))
            sage: w, u = W([1,2]), W([3,4])
            sage: ShuffleProduct_overlapping_r(w, u, 1).list() #indirect doctest
            [word: 424, word: 154, word: 442, word: 136, word: 352, word: 316]

            sage: I, J = Composition([2, 2]), Composition([1, 1])
            sage: S = ShuffleProduct_overlapping_r(I, J, 1)
            sage: S.list()
            [[3, 2, 1], [2, 3, 1], [3, 1, 2], [2, 1, 3], [1, 3, 2], [1, 2, 3]]

        TESTS:

        Sage is no longer confused by a too-restrictive parent
        of `I` when shuffling two compositions `I` and `J`
        (cf. :trac:`15131`)::

            sage: I, J = Compositions(4)([2, 2]), Composition([1, 1])
            sage: S = ShuffleProduct_overlapping_r(I, J, 1)
            sage: S.list()
            [[3, 2, 1], [2, 3, 1], [3, 1, 2], [2, 1, 3], [1, 3, 2], [1, 2, 3]]
        """
        W = self.W

        m = len(self._w1)
        n = len(self._w2)
        r = self.r

        wc1, wc2 = self._w1, self._w2

        blank = [0] * (m + n - r)
        for iv in IntegerVectors(m, m + n - r, max_part=1):
            w = blank[:]
            filled_places = []
            unfilled_places = []
            #Fill in w1 into the iv slots
            i = 0
            for j in range(len(iv)):
                if iv[j] == 1:
                    w[j] = wc1[i]
                    i += 1
                    filled_places.append(j)
                else:
                    unfilled_places.append(j)

            #Choose r of these filled places
            for subset in Subsets(filled_places, r):
                places_to_fill = unfilled_places + list(subset)
                places_to_fill.sort()

                #Fill in w2 into the places
                i = 0
                res = w[:]
                for j in places_to_fill:
                    res[j] += wc2[i]
                    i += 1

                yield W(res)
Example #19
0
        def is_perfect(self, ell=None):
            r"""
            Check if ``self`` is a perfect crystal of level ``ell``.

            A crystal `\mathcal{B}` is perfect of level `\ell` if:

            #. `\mathcal{B}` is isomorphic to the crystal graph of a
               finite-dimensional `U_q'(\mathfrak{g})`-module.
            #. `\mathcal{B} \otimes \mathcal{B}` is connected.
            #. There exists a `\lambda\in X`, such that
               `\mathrm{wt}(\mathcal{B}) \subset \lambda + \sum_{i\in I}
               \ZZ_{\le 0} \alpha_i` and there is a unique element in
               `\mathcal{B}` of classical weight `\lambda`.
            #. For all `b \in \mathcal{B}`,
               `\mathrm{level}(\varepsilon (b)) \geq \ell`.
            #. For all `\Lambda` dominant weights of level `\ell`, there
               exist unique elements `b_{\Lambda}, b^{\Lambda} \in
               \mathcal{B}`, such that `\varepsilon(b_{\Lambda}) =
               \Lambda = \varphi(b^{\Lambda})`.

            Points (1)-(3) are known to hold. This method checks
            points (4) and (5).

            If ``self`` is the Kirillov-Reshetikhin crystal `B^{r,s}`,
            then it was proven for non-exceptional types in [FOS2010]_
            that it is perfect if and only if `s/c_r` is an integer
            (where `c_r` is a constant related to the type of the crystal).

            It is conjectured this is true for all affine types.

            INPUT:

            - ``ell`` -- (default: `s / c_r`) integer; the level

            REFERENCES:

            [FOS2010]_

            EXAMPLES::

                sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1)
                sage: K.is_perfect()
                True

                sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 1)
                sage: K.is_perfect()
                False

                sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2)
                sage: K.is_perfect()
                True

                sage: K = crystals.KirillovReshetikhin(['E',6,1], 1,3)
                sage: K.is_perfect()
                True

            TESTS:

            Check that this works correctly for `B^{n,s}`
            of type `A_{2n}^{(2)\dagger}` (:trac:`24364`)::

                sage: K = crystals.KirillovReshetikhin(CartanType(['A',6,2]).dual(), 3,1)
                sage: K.is_perfect()
                True
                sage: K.is_perfect(1)
                True

            .. TODO::

                Implement a version for tensor products of KR crystals.
            """
            if ell is None:
                if (self.cartan_type().dual().type() == 'BC'
                        and self.cartan_type().rank() - 1 == self.r()):
                    return True
                ell = self.s() / self.cartan_type().c()[self.r()]
                if ell not in ZZ:
                    return False

            if ell not in ZZ:
                raise ValueError(
                    "perfectness not defined for non-integral levels")

            # [FOS2010]_ check
            if self.cartan_type().classical().type() not in ['E', 'F', 'G']:
                if (self.cartan_type().dual().type() == 'BC'
                        and self.cartan_type().rank() - 1 == self.r()):
                    return ell == self.s()
                return ell == self.s() / self.cartan_type().c()[self.r()]

            # Check by definition
            # TODO: This is duplicated from ProjectedLevelZeroLSPaths, combine the two methods.
            # TODO: Similarly, don't duplicate in the tensor product category, maybe
            #   move this to the derived affine category?
            MPhi = []
            for b in self:
                p = b.Phi().level()
                assert p == b.Epsilon().level()
                if p < ell:
                    return False
                if p == ell:
                    MPhi += [b]
            weights = []
            I = self.index_set()
            rank = len(I)
            La = self.weight_lattice_realization().basis()
            from sage.combinat.integer_vector import IntegerVectors
            for n in range(1, ell + 1):
                for c in IntegerVectors(n, rank):
                    w = sum(c[i] * La[i] for i in I)
                    if w.level() == ell:
                        weights.append(w)
            return sorted(b.Phi() for b in MPhi) == sorted(weights)
Example #20
0
    def __iter__(self):
        """
        EXAMPLES::

            sage: from sage.combinat.shuffle import ShuffleProduct_overlapping_r
            sage: w, u = Word([1,2]), Word([3,4])
            sage: ShuffleProduct_overlapping_r(w,u,1).list()
            [word: 424, word: 154, word: 442, word: 136, word: 352, word: 316]
            sage: w, u = map(Words(range(1,7)), [[1,2], [3,4]])
            sage: W = Words(range(1,7))
            sage: w, u = W([1,2]), W([3,4])
            sage: ShuffleProduct_overlapping_r(w, u, 1).list() #indirect doctest
            [word: 424, word: 154, word: 442, word: 136, word: 352, word: 316]

            sage: I, J = Composition([2, 2]), Composition([1, 1])
            sage: S = ShuffleProduct_overlapping_r(I, J, 1)
            sage: S.list()
            [[3, 2, 1], [2, 3, 1], [3, 1, 2], [2, 1, 3], [1, 3, 2], [1, 2, 3]]

        TESTS:

        We need to be explicitly more generic about the resulting parent
        when shuffling two compositions `I` and `J` (:trac:`15131`)::

            sage: I, J = Compositions(4)([2, 2]), Composition([1, 1])
            sage: S = ShuffleProduct_overlapping_r(I, J, 1, Compositions())
            sage: S.list()
            [[3, 2, 1], [2, 3, 1], [3, 1, 2], [2, 1, 3], [1, 3, 2], [1, 2, 3]]
        """
        EC = self._element_constructor_

        m = len(self._w1)
        n = len(self._w2)
        r = self.r
        add = self.add

        wc1, wc2 = self._w1, self._w2

        blank = [None] * (m+n-r)
        for iv in IntegerVectors(m, m+n-r, max_part=1):
            w = blank[:]
            filled_places = []
            unfilled_places = []
            #Fill in w1 into the iv slots
            i = 0
            for j in range(len(iv)):
                if iv[j] == 1:
                    w[j] = wc1[i]
                    i += 1
                    filled_places.append(j)
                else:
                    unfilled_places.append(j)

            #Choose r of these filled places
            for subset in itertools.combinations(filled_places, r):
                places_to_fill = sorted(unfilled_places + list(subset))

                #Fill in w2 into the places
                i = 0
                res = w[:]
                for j in places_to_fill:
                    if res[j] is not None:
                        res[j] = add(res[j], wc2[i])
                    else:
                        res[j] = wc2[i]
                    i += 1

                yield EC(res)
Example #21
0
    def polynomials(self, X=None, Y=None, degree=2, groebner=False):
        """
        Return a list of polynomials satisfying this S-box.

        First, a simple linear fitting is performed for the given
        ``degree`` (cf. for example [BC2003]_). If ``groebner=True`` a
        Groebner basis is also computed for the result of that
        process.

        INPUT:

        - ``X`` - input variables

        - ``Y`` - output variables

        - ``degree`` - integer > 0 (default: ``2``)

        - ``groebner`` - calculate a reduced Groebner basis of the
          spanning polynomials to obtain more polynomials (default:
          ``False``)

        EXAMPLES::

            sage: from sage.crypto.sbox import SBox
            sage: S = SBox(7,6,0,4,2,5,1,3)
            sage: P = S.ring()

        By default, this method returns an indirect representation::

            sage: S.polynomials()
            [x0*x2 + x1 + y1 + 1,
             x0*x1 + x1 + x2 + y0 + y1 + y2 + 1,
             x0*y1 + x0 + x2 + y0 + y2,
             x0*y0 + x0*y2 + x1 + x2 + y0 + y1 + y2 + 1,
             x1*x2 + x0 + x1 + x2 + y2 + 1,
             x0*y0 + x1*y0 + x0 + x2 + y1 + y2,
             x0*y0 + x1*y1 + x1 + y1 + 1,
             x1*y2 + x1 + x2 + y0 + y1 + y2 + 1,
             x0*y0 + x2*y0 + x1 + x2 + y1 + 1,
             x2*y1 + x0 + y1 + y2,
             x2*y2 + x1 + y1 + 1,
             y0*y1 + x0 + x2 + y0 + y1 + y2,
             y0*y2 + x1 + x2 + y0 + y1 + 1,
             y1*y2 + x2 + y0]

        We can get a direct representation by computing a
        lexicographical Groebner basis with respect to the right
        variable ordering, i.e. a variable ordering where the output
        bits are greater than the input bits::

            sage: P.<y0,y1,y2,x0,x1,x2> = PolynomialRing(GF(2),6,order='lex')
            sage: S.polynomials([x0,x1,x2],[y0,y1,y2], groebner=True)
            [y0 + x0*x1 + x0*x2 + x0 + x1*x2 + x1 + 1,
             y1 + x0*x2 + x1 + 1,
             y2 + x0 + x1*x2 + x1 + x2 + 1]
        """
        def nterms(nvars, deg):
            """
            Return the number of monomials possible up to a given
            degree.

            INPUT:

            - ``nvars`` - number of variables

            - ``deg`` - degree

            TESTS::

                sage: from sage.crypto.sbox import SBox
                sage: S = SBox(7,6,0,4,2,5,1,3)
                sage: F = S.polynomials(degree=3) # indirect doctest
            """
            total = 1
            divisor = 1
            var_choices = 1

            for d in range(1, deg+1):
                var_choices *= (nvars - d + 1)
                divisor *= d
                total += var_choices/divisor
            return total

        m = self.m
        n = self.n
        F = self._F

        if X is None and Y is None:
            P = self.ring()
            X = P.gens()[:m]
            Y = P.gens()[m:]
        else:
            P = X[0].parent()

        gens = X+Y

        bits = []
        for i in range(1<<m):
            bits.append( self.to_bits(i,m) + self(self.to_bits(i,m)) )

        ncols = (1<<m)+1

        A = Matrix(P, nterms(m+n, degree), ncols)

        exponents = []
        for d in range(degree+1):
            exponents += IntegerVectors(d, max_length=m+n, min_length=m+n, min_part=0, max_part=1).list()

        row = 0
        for exponent in exponents:
            A[row,ncols-1] = mul([gens[i]**exponent[i] for i in range(len(exponent))])
            for col in range(1<<m):
                A[row,col] = mul([bits[col][i] for i in range(len(exponent)) if exponent[i]])
            row +=1

        for c in range(ncols):
            A[0,c] = 1

        RR = A.echelon_form(algorithm='row_reduction')

        # extract spanning stet
        gens = (RR.column(ncols-1)[1<<m:]).list()

        if not groebner:
            return gens

        FI = set(FieldIdeal(P).gens())
        I = Ideal(gens + list(FI))
        gb = I.groebner_basis()

        gens = []
        for f in gb:
            if f not in FI: # filter out field equations
                gens.append(f)
        return gens
Example #22
0
        def graded_basis(self, k):
            """
            Return the basis for the ``k``-th graded piece of ``self``.

            EXAMPLES::

                sage: L = LieAlgebra(QQ, 'x', 3)
                sage: Lyn = L.Lyndon()
                sage: Lyn.graded_basis(1)
                (x0, x1, x2)
                sage: Lyn.graded_basis(2)
                ([x0, x1], [x0, x2], [x1, x2])
                sage: Lyn.graded_basis(4)
                ([x0, [x0, [x0, x1]]],
                 [x0, [x0, [x0, x2]]],
                 [x0, [[x0, x1], x1]],
                 [x0, [x0, [x1, x2]]],
                 [x0, [[x0, x2], x1]],
                 [[x0, x1], [x0, x2]],
                 [x0, [[x0, x2], x2]],
                 [[[x0, x1], x1], x1],
                 [x0, [x1, [x1, x2]]],
                 [[x0, [x1, x2]], x1],
                 [[[x0, x2], x1], x1],
                 [x0, [[x1, x2], x2]],
                 [[x0, x2], [x1, x2]],
                 [[[x0, x2], x2], x1],
                 [[[x0, x2], x2], x2],
                 [x1, [x1, [x1, x2]]],
                 [x1, [[x1, x2], x2]],
                 [[[x1, x2], x2], x2])

            TESTS::

                sage: L = LieAlgebra(QQ, 'x,y,z', 3)
                sage: Lyn = L.Lyndon()
                sage: [Lyn.graded_dimension(i) for i in range(1, 11)]
                [3, 3, 8, 18, 48, 116, 312, 810, 2184, 5880]
                sage: [len(Lyn.graded_basis(i)) for i in range(1, 11)]
                [3, 3, 8, 18, 48, 116, 312, 810, 2184, 5880]
            """
            if k <= 0 or not self._indices:
                return []

            names = self.variable_names()
            one = self.base_ring().one()
            if k == 1:
                return tuple(self.element_class(self, {LieGenerator(n): one}) for n in names)

            # Slightly modified form of LyndonWords_nk which is 0 indexed,
            #   does not create any temporary objects and simplifies the
            #   combined logic
            from sage.combinat.integer_vector import IntegerVectors
            from sage.combinat.necklace import _sfc

            n = len(self._indices)
            ret = []
            for c in IntegerVectors(k, n):
                nonzero_indices = [i for i,val in enumerate(c) if val != 0]

                cf = [c[i] for i in nonzero_indices]

                for z in _sfc(cf, equality=True):
                    b = self._standard_bracket(tuple([names[nonzero_indices[i]] for i in z]))
                    ret.append(self.element_class(self, {b: one}))
            return tuple(ret)