def __init__(self,R, index_set=None, central_elements=None, category=None,
                 element_class=None, prefix=None, **kwds):
        """
        Initialize self.

        TESTS::

            sage: V = lie_conformal_algebras.Virasoro(QQ)
            sage: TestSuite(V).run()
        """
        self._generators = Family(index_set)
        E = cartesian_product([index_set, NonNegativeIntegers()])
        if central_elements is not None:
            self._generators = DisjointUnionEnumeratedSets([index_set,
                                                    Family(central_elements)])
            E = DisjointUnionEnumeratedSets((cartesian_product([
                Family(central_elements), {Integer(0)}]),E))

        super(FreelyGeneratedLieConformalAlgebra,self).__init__(R, basis_keys=E,
            element_class=element_class, category=category, prefix=prefix,
            **kwds)

        if central_elements is not None:
            self._central_elements = Family(central_elements)
        else:
            self._central_elements = tuple()
    def __init__(self, n, k, q, F):
        r"""
        Initialize ``self``.

        EXAMPLES::

            sage: Cl = algebras.QuantumClifford(1,2)
            sage: TestSuite(Cl).run(elements=Cl.basis())

            sage: Cl = algebras.QuantumClifford(1,3)
            sage: TestSuite(Cl).run(elements=Cl.basis())  # long time

            sage: Cl = algebras.QuantumClifford(3)  # long time
            sage: elts = Cl.some_elements() + list(Cl.algebra_generators())  # long time
            sage: TestSuite(Cl).run(elements=elts)  # long time

            sage: Cl = algebras.QuantumClifford(2,4)  # long time
            sage: elts = Cl.some_elements() + list(Cl.algebra_generators())  # long time
            sage: TestSuite(Cl).run(elements=elts)  # long time
        """
        self._n = n
        self._k = k
        self._q = q
        self._psi = cartesian_product([(-1,0,1)]*n)
        self._w_poly = PolynomialRing(F, n, 'w')
        indices = [(tuple(psi), tuple(w))
                   for psi in self._psi
                   for w in product(*[list(range((4-2*abs(psi[i]))*k)) for i in range(n)])]
        indices = FiniteEnumeratedSet(indices)

        cat = Algebras(F).FiniteDimensional().WithBasis()
        CombinatorialFreeModule.__init__(self, F, indices, category=cat)
        self._assign_names(self.algebra_generators().keys())
def add_degree_symmetric(d1, d2):
    """
    Compute the sum componentwise of d1 and d2 and return a sorted grading
    set with no negative component as result.
    
    INPUT:
        - ``d1``,``d2`` -- lists of integers
    
    EXAMPLES::
        
        sage: D = cartesian_product([ZZ for i in range(3)])
        sage: add_degree_symmetric(D([3,2,1]), D([-2,0,0]))
        (2, 1, 1)
        sage: add_degree_symmetric(D([3,2,1]), D([-2,1,4]))
        (5, 3, 1)
        sage: add_degree_symmetric(D([3,2,1]), D([2,1,1]))
        (5, 3, 2)
        sage: add_degree_symmetric(D([3,2,1]), D([2,1,-2]))
        Traceback (most recent call last):
        ...
        ValueError: invalid degree
    """
    d = d1 + d2
    D = cartesian_product([ZZ for i in range(len(d))])
    if not all(i >= 0 for i in d):
        raise ValueError("invalid degree")
    return D(sorted(d, reverse=True))
Exemple #4
0
            def group_generators(self):
                """
                Return the group generators of ``self``.

                EXAMPLES::

                    sage: C5 = CyclicPermutationGroup(5)
                    sage: C4 = CyclicPermutationGroup(4)
                    sage: S4 = SymmetricGroup(3)
                    sage: C = cartesian_product([C5, C4, S4])
                    sage: C.group_generators()
                    Family (((1,2,3,4,5), (), ()),
                            ((), (1,2,3,4), ()),
                            ((), (), (1,2)),
                            ((), (), (2,3)))

                We check the other portion of :trac:`16718` is fixed::

                    sage: len(C.j_classes())
                    1

                An example with an infinitely generated group (a better output
                is needed)::

                    sage: G = Groups.free([1,2])
                    sage: H = Groups.free(ZZ)
                    sage: C = cartesian_product([G, H])
                    sage: C.monoid_generators()
                    Lazy family (gen(i))_{i in The Cartesian product of (...)}
                """
                F = self.cartesian_factors()
                ids = tuple(G.one() for G in F)

                def lift(i, gen):
                    cur = list(ids)
                    cur[i] = gen
                    return self._cartesian_product_of_elements(cur)

                from sage.sets.family import Family

                # Finitely generated
                cat = FiniteEnumeratedSets()
                if all(G.group_generators() in cat
                       or isinstance(G.group_generators(), (tuple, list))
                       for G in F):
                    ret = [
                        lift(i, gen) for i, G in enumerate(F)
                        for gen in G.group_generators()
                    ]
                    return Family(ret)

                # Infinitely generated
                # This does not return a good output, but it is "correct"
                # TODO: Figure out a better way to do things
                from sage.categories.cartesian_product import cartesian_product
                gens_prod = cartesian_product([
                    Family(G.group_generators(), lambda g: (i, g))
                    for i, G in enumerate(F)
                ])
                return Family(gens_prod, lift, name="gen")
Exemple #5
0
def Possible(n):
    r"""
    Possible stack of DyckWords inside a n x n cube.

    EXAMPLES::

        sage: from slabbe.dyck_3d import Possible
        sage: Possible(1)
        The Cartesian product of ({[1, 0]},)
        sage: Possible(2)
        The Cartesian product of ({[1, 1, 0, 0]}, {[1, 0, 1, 0], [1, 1, 0, 0]})
        sage: Possible(3).list()
        [([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 0, 1, 0, 1, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 0, 1, 1, 0, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 1, 0, 0, 1, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 1, 0, 1, 0, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 1, 1, 0, 0, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 0, 1, 0, 1, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 0, 1, 1, 0, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 0, 0, 1, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0])]

    """
    from sage.combinat.dyck_word import DyckWords, DyckWord
    from sage.categories.cartesian_product import cartesian_product
    L = []
    for i in range(1, n+1):
        K = []
        for w in DyckWords(i):
            w = DyckWord([1]*(n-i) + list(w) + [0]*(n-i))
            K.append(w) 
        L.append(K)
    return cartesian_product(L)
Exemple #6
0
    def basis(self):
        r"""
        Return the basis of ``self``.

        EXAMPLES::

            sage: g = LieAlgebra(QQ, cartan_type=['D',4,1])
            sage: B = g.basis()
            sage: al = RootSystem(['D',4]).root_lattice().simple_roots()
            sage: B[al[1]+al[2]+al[4],4]
            (E[alpha[1] + alpha[2] + alpha[4]])#t^4
            sage: B[-al[1]-2*al[2]-al[3]-al[4],2]
            (E[-alpha[1] - 2*alpha[2] - alpha[3] - alpha[4]])#t^2
            sage: B[al[4],-2]
            (E[alpha[4]])#t^-2
            sage: B['c']
            c
            sage: B['d']
            d
        """
        K = cartesian_product([self._g.basis().keys(), ZZ])
        from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
        c = FiniteEnumeratedSet(['c'])
        if self._kac_moody:
            d = FiniteEnumeratedSet(['d'])
            keys = DisjointUnionEnumeratedSets([c, d, K])
        else:
            keys = DisjointUnionEnumeratedSets([c, K])
        return Family(keys, self.monomial)
    def basis(self):
        r"""
        Return the basis of ``self``.

        EXAMPLES::

            sage: g = LieAlgebra(QQ, cartan_type=['D',4,1])
            sage: B = g.basis()
            sage: al = RootSystem(['D',4]).root_lattice().simple_roots()
            sage: B[al[1]+al[2]+al[4],4]
            (E[alpha[1] + alpha[2] + alpha[4]])#t^4
            sage: B[-al[1]-2*al[2]-al[3]-al[4],2]
            (E[-alpha[1] - 2*alpha[2] - alpha[3] - alpha[4]])#t^2
            sage: B[al[4],-2]
            (E[alpha[4]])#t^-2
            sage: B['c']
            c
            sage: B['d']
            d
        """
        K = cartesian_product([self._g.basis().keys(), ZZ])
        from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
        c = FiniteEnumeratedSet(['c'])
        if self._kac_moody:
            d = FiniteEnumeratedSet(['d'])
            keys = DisjointUnionEnumeratedSets([c, d, K])
        else:
            keys = DisjointUnionEnumeratedSets([c, K])
        return Family(keys, self.monomial)
Exemple #8
0
    def strongly_fatter(self):
        """
        Return the set of ordered set partitions which are strongly fatter
        than ``self``.

        See :meth:`strongly_finer` for the definition of "strongly fatter".

        EXAMPLES::

            sage: C = OrderedSetPartition([[2, 5], [1], [3, 4]]).strongly_fatter()
            sage: C.cardinality()
            2
            sage: sorted(C)
            [[{2, 5}, {1, 3, 4}],
             [{2, 5}, {1}, {3, 4}]]

            sage: OrderedSetPartition([[4, 9], [-1, 2]]).strongly_fatter().list()
            [[{4, 9}, {-1, 2}]]

        Some extreme cases::

            sage: list(OrderedSetPartition([[5]]).strongly_fatter())
            [[{5}]]
            sage: list(OrderedSetPartition([]).strongly_fatter())
            [[]]
            sage: sorted(OrderedSetPartition([[1], [2], [3], [4]]).strongly_fatter())
            [[{1, 2, 3, 4}],
             [{1, 2, 3}, {4}],
             [{1, 2}, {3, 4}],
             [{1, 2}, {3}, {4}],
             [{1}, {2, 3, 4}],
             [{1}, {2, 3}, {4}],
             [{1}, {2}, {3, 4}],
             [{1}, {2}, {3}, {4}]]
            sage: sorted(OrderedSetPartition([[1], [3], [2], [4]]).strongly_fatter())
            [[{1, 3}, {2, 4}],
             [{1, 3}, {2}, {4}],
             [{1}, {3}, {2, 4}],
             [{1}, {3}, {2}, {4}]]
            sage: sorted(OrderedSetPartition([[4], [1], [5], [3]]).strongly_fatter())
            [[{4}, {1, 5}, {3}], [{4}, {1}, {5}, {3}]]
        """
        c = [sorted(X) for X in self]
        l = len(c)
        g = [-1] + [i
                    for i in range(l - 1) if c[i][-1] > c[i + 1][0]] + [l - 1]
        # g lists the positions of the blocks that cannot be merged
        # with their right neighbors.
        subcomps = [
            OrderedSetPartition(c[g[i] + 1:g[i + 1] + 1])
            for i in range(len(g) - 1)
        ]
        # Now, self is the concatenation of the entries of subcomps.
        # We can fatten each of the ordered set partitions setcomps
        # arbitrarily, and then concatenate the results.
        fattenings = [list(subcomp.fatter()) for subcomp in subcomps]
        return FiniteEnumeratedSet([
            OrderedSetPartition(sum([list(gg) for gg in fattening], []))
            for fattening in cartesian_product(fattenings)
        ])
    def strongly_finer(self):
        """
        Return the set of ordered set partitions which are strongly
        finer than ``self``.

        See :meth:`is_strongly_finer` for the definition of "strongly
        finer".

        EXAMPLES::

            sage: C = OrderedSetPartition([[1, 3], [2]]).strongly_finer()
            sage: C.cardinality()
            2
            sage: C.list()
            [[{1}, {3}, {2}], [{1, 3}, {2}]]

            sage: OrderedSetPartition([]).strongly_finer()
            {[]}

            sage: W = OrderedSetPartition([[4, 9], [-1, 2]])
            sage: W.strongly_finer().list()
            [[{4}, {9}, {-1}, {2}],
             [{4}, {9}, {-1, 2}],
             [{4, 9}, {-1}, {2}],
             [{4, 9}, {-1, 2}]]
        """
        par = parent(self)
        if not self:
            return FiniteEnumeratedSet([self])
        else:
            buo = OrderedSetPartition.bottom_up_osp
            return FiniteEnumeratedSet([par(sum((list(P) for P in C), []))
                    for C in cartesian_product([[buo(X, comp) for comp in Compositions(len(X))] for X in self])])
Exemple #10
0
    def __init__(self, crystals, **options):
        """
        TESTS::

            sage: from sage.combinat.crystals.tensor_product import FullTensorProductOfCrystals
            sage: C = crystals.Letters(['A',2])
            sage: T = crystals.TensorProduct(C,C)
            sage: isinstance(T, FullTensorProductOfCrystals)
            True
            sage: TestSuite(T).run()
        """
        category = Category.meet([crystal.category() for crystal in crystals])
        category = category.TensorProducts()
        if any(c in Sets().Infinite() for c in crystals):
            category = category.Infinite()
        Parent.__init__(self, category=category)
        self.crystals = crystals
        if 'cartan_type' in options:
            self._cartan_type = CartanType(options['cartan_type'])
        else:
            if not crystals:
                raise ValueError(
                    "you need to specify the Cartan type if the tensor product list is empty"
                )
            else:
                self._cartan_type = crystals[0].cartan_type()
        self.cartesian_product = cartesian_product(self.crystals)
        self.module_generators = self
Exemple #11
0
    def strongly_finer(self):
        """
        Return the set of ordered set partitions which are strongly
        finer than ``self``.

        See :meth:`is_strongly_finer` for the definition of "strongly
        finer".

        EXAMPLES::

            sage: C = OrderedSetPartition([[1, 3], [2]]).strongly_finer()
            sage: C.cardinality()
            2
            sage: C.list()
            [[{1}, {3}, {2}], [{1, 3}, {2}]]

            sage: OrderedSetPartition([]).strongly_finer()
            {[]}

            sage: W = OrderedSetPartition([[4, 9], [-1, 2]])
            sage: W.strongly_finer().list()
            [[{4}, {9}, {-1}, {2}],
             [{4}, {9}, {-1, 2}],
             [{4, 9}, {-1}, {2}],
             [{4, 9}, {-1, 2}]]
        """
        par = parent(self)
        if not self:
            return FiniteEnumeratedSet([self])
        else:
            buo = OrderedSetPartition.bottom_up_osp
            return FiniteEnumeratedSet([par(sum((list(P) for P in C), []))
                    for C in cartesian_product([[buo(X, comp) for comp in Compositions(len(X))] for X in self])])
Exemple #12
0
    def __init__(self, space, number_errors, number_erasures):
        r"""


        TESTS:

        If the sum of number of errors and number of erasures
        exceeds (or may exceed, in the case of tuples) the dimension of the input space,
        it will return an error::

            sage: n_err, n_era = 21, 21
            sage: Chan = channels.ErrorErasureChannel(GF(59)^40, n_err, n_era)
            Traceback (most recent call last):
            ...
            ValueError: The total number of errors and erasures can not exceed the dimension of the input space
        """
        if isinstance(number_errors, (Integer, int)):
            number_errors = (number_errors, number_errors)
        if not isinstance(number_errors, (tuple, list)):
            raise ValueError("number_errors must be a tuple, a list, an Integer or a Python int")

        if isinstance(number_erasures, (Integer, int)):
            number_erasures = (number_erasures, number_erasures)
        if not isinstance(number_erasures, (tuple, list)):
            raise ValueError("number_erasures must be a tuple, a list, an Integer or a Python int")

        output_space = cartesian_product([space, VectorSpace(GF(2), space.dimension())])
        super(ErrorErasureChannel, self).__init__(space, output_space)
        if number_errors[1] + number_erasures[1] > space.dimension():
            raise ValueError("The total number of errors and erasures can not exceed the dimension of the input space")
        self._number_errors = number_errors
        self._number_erasures = number_erasures
Exemple #13
0
def Possible(n):
    r"""
    Possible stack of DyckWords inside a n x n cube.

    EXAMPLES::

        sage: from slabbe.dyck_3d import Possible
        sage: Possible(1)
        The Cartesian product of ({[1, 0]},)
        sage: Possible(2)
        The Cartesian product of ({[1, 1, 0, 0]}, {[1, 0, 1, 0], [1, 1, 0, 0]})
        sage: Possible(3).list()
        [([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 0, 1, 0, 1, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 0, 1, 1, 0, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 1, 0, 0, 1, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 1, 0, 1, 0, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0], [1, 1, 1, 0, 0, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 0, 1, 0, 1, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 0, 1, 1, 0, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 0, 0, 1, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 0, 1, 0, 0]),
         ([1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0])]

    """
    from sage.combinat.dyck_word import DyckWords, DyckWord
    from sage.categories.cartesian_product import cartesian_product
    L = []
    for i in range(1, n + 1):
        K = []
        for w in DyckWords(i):
            w = DyckWord([1] * (n - i) + list(w) + [0] * (n - i))
            K.append(w)
        L.append(K)
    return cartesian_product(L)
Exemple #14
0
    def __init__(self, space, number_errors, number_erasures):
        r"""


        TESTS:

        If the sum of number of errors and number of erasures
        exceeds (or may exceed, in the case of tuples) the dimension of the input space,
        it will return an error::

            sage: n_err, n_era = 21, 21
            sage: Chan = channels.ErrorErasureChannel(GF(59)^40, n_err, n_era)
            Traceback (most recent call last):
            ...
            ValueError: The total number of errors and erasures can not exceed the dimension of the input space
        """
        if isinstance(number_errors, (Integer, int)):
            number_errors = (number_errors, number_errors)
        if not isinstance(number_errors, (tuple, list)):
            raise ValueError("number_errors must be a tuple, a list, an Integer or a Python int")

        if isinstance(number_erasures, (Integer, int)):
            number_erasures = (number_erasures, number_erasures)
        if not isinstance(number_erasures, (tuple, list)):
            raise ValueError("number_erasures must be a tuple, a list, an Integer or a Python int")

        output_space = cartesian_product([space, VectorSpace(GF(2), space.dimension())])
        super(ErrorErasureChannel, self).__init__(space, output_space)
        if number_errors[1] + number_erasures[1] > space.dimension():
            raise ValueError("The total number of errors and erasures can not exceed the dimension of the input space")
        self._number_errors = number_errors
        self._number_erasures = number_erasures
Exemple #15
0
    def __init__(self, crystals, **options):
        """
        TESTS::

            sage: from sage.combinat.crystals.tensor_product import FullTensorProductOfCrystals
            sage: C = crystals.Letters(['A',2])
            sage: T = crystals.TensorProduct(C,C)
            sage: isinstance(T, FullTensorProductOfCrystals)
            True
            sage: TestSuite(T).run()
        """
        category = Category.meet([crystal.category() for crystal in crystals])
        category = category.TensorProducts()
        if any(c in Sets().Infinite() for c in crystals):
            category = category.Infinite()
        Parent.__init__(self, category=category)
        self.crystals = crystals
        if 'cartan_type' in options:
            self._cartan_type = CartanType(options['cartan_type'])
        else:
            if not crystals:
                raise ValueError("you need to specify the Cartan type if the tensor product list is empty")
            else:
                self._cartan_type = crystals[0].cartan_type()
        self.cartesian_product = cartesian_product(self.crystals)
        self.module_generators = self
Exemple #16
0
def symmetrized_coordinate_sums(dim, n):
    """
    Return formal symmetrized sum of multi-indices

    INPUT:

    - ``dim`` -- integer. The dimension (range of each index).

    - ``n`` -- integer. The total number of indices.

    OUTPUT:

    A symmetrized formal sum of multi-indices (tuples of integers)

    EXAMPLES::

        sage: from sage.modules.tensor_operations import symmetrized_coordinate_sums
        sage: symmetrized_coordinate_sums(2, 2)
        ((0, 1) + (1, 0), (0, 0), (1, 1))
    """
    from sage.structure.formal_sum import FormalSum
    coordinates = [range(dim) for i in range(n)]
    table = dict()
    from sage.categories.cartesian_product import cartesian_product
    for i in cartesian_product(coordinates):
        sort_i = tuple(sorted(i))
        x = table.get(sort_i, [])
        x.append([+1, tuple(i)])
        table[sort_i] = x
    return tuple(FormalSum(x) for x in table.values())
Exemple #17
0
            def one(self):
                """
                EXAMPLES::

                    sage: cartesian_product([QQ, ZZ, RR]).one()
                    (1, 1, 1.00000000000000)
                """
                return cartesian_product([set.one() for set in self._sets])
Exemple #18
0
            def one(self):
                """
                EXAMPLES::

                    sage: cartesian_product([QQ, ZZ, RR]).one()
                    (1, 1, 1.00000000000000)
                """
                return cartesian_product([set.one() for set in self._sets])
def bitstring_rotation(n, ones=None):
    r"""
    Return the invertible finite discrete dynamical system
    consisting of all bitstrings of size `n` (that is, of
    all `n`-tuples `(i_1, \ldots, i_n) \in \{0, 1\}^n`),
    evolving by cyclic rotation.

    If the optional parameter ``ones`` is provided, the
    system is restricted only to those bitstrings whose
    number of ones is the value of this parameter.

    EXAMPLES::

        sage: F = finite_dynamical_systems.bitstring_rotation(5)
        sage: sorted(F.orbit_lengths())
        [1, 1, 5, 5, 5, 5, 5, 5]
        sage: F.orbit((0, 1, 1, 0, 1))
        [(0, 1, 1, 0, 1),
         (1, 1, 0, 1, 0),
         (1, 0, 1, 0, 1),
         (0, 1, 0, 1, 1),
         (1, 0, 1, 1, 0)]
        sage: F.is_homomesic(lambda x: sum(1 for i in range(5) for j in range(i) if x[j] > x[i]))
        False
        sage: F.is_homomesic(lambda x: x[0])
        False
        sage: F = finite_dynamical_systems.bitstring_rotation(5, ones=3)
        sage: F.verify_inverse_evolution()
        True
        sage: sorted(F.orbit_lengths())
        [5, 5]
        sage: F.orbit((0, 1, 1, 0, 1))
        [(0, 1, 1, 0, 1),
         (1, 1, 0, 1, 0),
         (1, 0, 1, 0, 1),
         (0, 1, 0, 1, 1),
         (1, 0, 1, 1, 0)]
        sage: F.is_homomesic(lambda x: sum(1 for i in range(5) for j in range(i) if x[j] > x[i]))
        True
        sage: F.is_homomesic(lambda x: x[0])
        True
    """
    if ones is None:
        from sage.categories.cartesian_product import cartesian_product
        X = cartesian_product([[0, 1]] * n)
    else:
        from itertools import combinations
        X = [
            tuple((1 if i in cs else 0) for i in range(n))
            for cs in combinations(range(n), ones)
        ]
    if n == 0:
        phi = lambda x: x
        psi = phi
    else:
        phi = lambda x: x[1:] + (x[0], )
        psi = lambda x: (x[-1], ) + x[:-1]
    return InvertibleFiniteDynamicalSystem(X, phi, inverse=psi)
Exemple #20
0
    def _init_product_vectors(self, i):
        r"""
        Helper to build up ``self._vectors`` incrementally during the
        constructor.

        INPUT:

        - `i` -- list/tuple of integers. Multi-index of length equal
          to the number of constituent vector collections. The $j$-th
          entry $i[j]$ indexes a ray in the $j$-th vector
          collection. Hence, $i$ specifies one element in each vector
          collection.

        OUTPUT:

        This method mutates the :class:`TensorOperation` instance. In
        particular, the tensor product of the vectors of the vector
        collection is computed, and added to the elements of the
        tensor operation if it has not been encountered before. 

        The index of this tensor product vector is returned as an
        integer.

        .. NOTE::

            In a convenient choice of coordinates the tensor product
            of, say, two vectors $(a,b)$ and $(c,d)$, is $(ac, ad, bc,
            bd)$.

        EXAMPLES::

            sage: from sage.modules.tensor_operations import \
            ....:      VectorCollection, TensorOperation
            sage: R = VectorCollection([(1,0), (1,2), (-1,-2)], QQ, 2)
            sage: S = VectorCollection([(1,), (-1,)], QQ, 1)
            sage: R_tensor_S = TensorOperation([R,S])
            sage: R_tensor_S.index_map(1, 1)
            3
            sage: R_tensor_S.index_map(2, 0)
            3
            sage: R_tensor_S.vectors()   # indirect doctest
            ((1, 0), (-1, 0), (1, 2), (-1, -2))
        """
        # Pick out the i[j]-th vector
        rays = [list(self._V[j].vectors()[k]) for j, k in enumerate(i)]
        v = []
        # Note: convert to list, as cartesian_product of vectors is unrelated
        from sage.categories.cartesian_product import cartesian_product
        for r in cartesian_product(map(list, rays)):
            v.append(prod(r))   # build up the tensor product
        v = tuple(v)
        # Use index of pre-existing tensor product vector if there is one
        try:
            result = self._vectors.index(v)
        except ValueError:
            self._vectors.append(v)
            result = len(self._vectors) - 1
        return result
def twin_prime_powers_difference_set(p, check=True):
    r"""
    Return a difference set on `GF(p) \times GF(p+2)`.

    The difference set is built from the following element of the cartesian
    product of finite fields `GF(p) \times GF(p+2)`:

    - `(x,0)` with any `x`
    - `(x,y)` with `x` and `y` squares
    - `(x,y)` with `x` and `y` non-squares

    For more information see :wikipedia:`Difference_set`.

    INPUT:

    - ``check`` -- boolean (default: ``True``). If ``True`` then the result of
      the computation is checked before being returned. This should not be
      needed but ensures that the output is correct.

    EXAMPLES::

        sage: from sage.combinat.designs.difference_family import twin_prime_powers_difference_set
        sage: G,D = twin_prime_powers_difference_set(3)
        sage: G
        The cartesian product of (Finite Field of size 3, Finite Field of size 5)
        sage: D
        [[(1, 1), (1, 4), (2, 2), (2, 3), (0, 0), (1, 0), (2, 0)]]
    """
    from sage.rings.finite_rings.constructor import FiniteField
    from sage.categories.cartesian_product import cartesian_product
    from itertools import product
    Fp = FiniteField(p, 'x')
    Fq = FiniteField(p + 2, 'x')
    Fpset = set(Fp)
    Fqset = set(Fq)
    Fp_squares = set(x**2 for x in Fpset)
    Fq_squares = set(x**2 for x in Fqset)

    # Pairs of squares, pairs of non-squares
    d = []
    d.extend(product(Fp_squares.difference([0]), Fq_squares.difference([0])))
    d.extend(
        product(Fpset.difference(Fp_squares), Fqset.difference(Fq_squares)))

    # All (x,0)
    d.extend((x, 0) for x in Fpset)

    G = cartesian_product([Fp, Fq])

    if check and not is_difference_family(G, [d]):
        raise RuntimeError("twin_prime_powers_difference_set produced a wrong "
                           "difference set with p={}. Please contact "
                           "*****@*****.**".format(p))

    return G, [d]
    def strongly_fatter(self):
        """
        Return the set of ordered set partitions which are strongly fatter
        than ``self``.

        See :meth:`strongly_finer` for the definition of "strongly fatter".

        EXAMPLES::

            sage: C = OrderedSetPartition([[2, 5], [1], [3, 4]]).strongly_fatter()
            sage: C.cardinality()
            2
            sage: sorted(C)
            [[{2, 5}, {1, 3, 4}],
             [{2, 5}, {1}, {3, 4}]]

            sage: OrderedSetPartition([[4, 9], [-1, 2]]).strongly_fatter().list()
            [[{4, 9}, {-1, 2}]]

        Some extreme cases::

            sage: list(OrderedSetPartition([[5]]).strongly_fatter())
            [[{5}]]
            sage: list(OrderedSetPartition([]).strongly_fatter())
            [[]]
            sage: sorted(OrderedSetPartition([[1], [2], [3], [4]]).strongly_fatter())
            [[{1, 2, 3, 4}],
             [{1, 2, 3}, {4}],
             [{1, 2}, {3, 4}],
             [{1, 2}, {3}, {4}],
             [{1}, {2, 3, 4}],
             [{1}, {2, 3}, {4}],
             [{1}, {2}, {3, 4}],
             [{1}, {2}, {3}, {4}]]
            sage: sorted(OrderedSetPartition([[1], [3], [2], [4]]).strongly_fatter())
            [[{1, 3}, {2, 4}],
             [{1, 3}, {2}, {4}],
             [{1}, {3}, {2, 4}],
             [{1}, {3}, {2}, {4}]]
            sage: sorted(OrderedSetPartition([[4], [1], [5], [3]]).strongly_fatter())
            [[{4}, {1, 5}, {3}], [{4}, {1}, {5}, {3}]]
        """
        c = [sorted(X) for X in self]
        l = len(c)
        g = [-1] + [i for i in range(l-1) if c[i][-1] > c[i+1][0]] + [l-1]
        # g lists the positions of the blocks that cannot be merged
        # with their right neighbors.
        subcomps = [OrderedSetPartition(c[g[i] + 1 : g[i+1] + 1]) for i in range(len(g)-1)]
        # Now, self is the concatenation of the entries of subcomps.
        # We can fatten each of the ordered set partitions setcomps
        # arbitrarily, and then concatenate the results.
        fattenings = [list(subcomp.fatter()) for subcomp in subcomps]
        return FiniteEnumeratedSet([OrderedSetPartition(sum([list(g) for g in fattening], []))
            for fattening in cartesian_product(fattenings)])
Exemple #23
0
def twin_prime_powers_difference_set(p, check=True):
    r"""
    Return a difference set on `GF(p) \times GF(p+2)`.

    The difference set is built from the following element of the cartesian
    product of finite fields `GF(p) \times GF(p+2)`:

    - `(x,0)` with any `x`
    - `(x,y)` with `x` and `y` squares
    - `(x,y)` with `x` and `y` non-squares

    For more information see :wikipedia:`Difference_set`.

    INPUT:

    - ``check`` -- boolean (default: ``True``). If ``True`` then the result of
      the computation is checked before being returned. This should not be
      needed but ensures that the output is correct.

    EXAMPLES::

        sage: from sage.combinat.designs.difference_family import twin_prime_powers_difference_set
        sage: G,D = twin_prime_powers_difference_set(3)
        sage: G
        The cartesian product of (Finite Field of size 3, Finite Field of size 5)
        sage: D
        [[(1, 1), (1, 4), (2, 2), (2, 3), (0, 0), (1, 0), (2, 0)]]
    """
    from sage.rings.finite_rings.constructor import FiniteField
    from sage.categories.cartesian_product import cartesian_product
    from itertools import product
    Fp = FiniteField(p,'x')
    Fq = FiniteField(p+2,'x')
    Fpset = set(Fp)
    Fqset = set(Fq)
    Fp_squares = set(x**2 for x in Fpset)
    Fq_squares = set(x**2 for x in Fqset)

    # Pairs of squares, pairs of non-squares
    d = []
    d.extend(product(Fp_squares.difference([0]),Fq_squares.difference([0])))
    d.extend(product(Fpset.difference(Fp_squares),Fqset.difference(Fq_squares)))

    # All (x,0)
    d.extend((x,0) for x in Fpset)

    G = cartesian_product([Fp,Fq])

    if check and not is_difference_family(G, [d]):
        raise RuntimeError("twin_prime_powers_difference_set produced a wrong "
                           "difference set with p={}. Please contact "
                           "*****@*****.**".format(p))

    return G, [d]
Exemple #24
0
            def group_generators(self):
                """
                Return the group generators of ``self``.

                EXAMPLES::

                    sage: C5 = CyclicPermutationGroup(5)
                    sage: C4 = CyclicPermutationGroup(4)
                    sage: S4 = SymmetricGroup(3)
                    sage: C = cartesian_product([C5, C4, S4])
                    sage: C.group_generators()
                    Family (((1,2,3,4,5), (), ()),
                            ((), (1,2,3,4), ()),
                            ((), (), (1,2)),
                            ((), (), (2,3)))

                We check the other portion of :trac:`16718` is fixed::

                    sage: len(C.j_classes())
                    1

                An example with an infinitely generated group (a better output
                is needed)::

                    sage: G = Groups.free([1,2])
                    sage: H = Groups.free(ZZ)
                    sage: C = cartesian_product([G, H])
                    sage: C.monoid_generators()
                    Lazy family (gen(i))_{i in The Cartesian product of (...)}
                """
                F = self.cartesian_factors()
                ids = tuple(G.one() for G in F)
                def lift(i, gen):
                    cur = list(ids)
                    cur[i] = gen
                    return self._cartesian_product_of_elements(cur)
                from sage.sets.family import Family

                # Finitely generated
                cat = FiniteEnumeratedSets()
                if all(G.group_generators() in cat
                       or isinstance(G.group_generators(), (tuple, list)) for G in F):
                    ret = [lift(i, gen) for i,G in enumerate(F) for gen in G.group_generators()]
                    return Family(ret)

                # Infinitely generated
                # This does not return a good output, but it is "correct"
                # TODO: Figure out a better way to do things
                from sage.categories.cartesian_product import cartesian_product
                gens_prod = cartesian_product([Family(G.group_generators(),
                                                      lambda g: (i, g))
                                               for i,G in enumerate(F)])
                return Family(gens_prod, lift, name="gen")
Exemple #25
0
    def _power_operation(self, n, operation):
        """
        Return tensor power operation.

        INPUT:

        - ``n`` -- integer. the number of factors of ``self``.

        - ``operation`` -- string. See
          :class:`~sage.modules.tensor_operations.TensorOperation` for
          details.

        EXAMPLES::

            sage: F = FilteredVectorSpace(1, 1) + FilteredVectorSpace(1, 2);  F
            QQ^2 >= QQ^1 >= 0
            sage: F._power_operation(2, 'symmetric')
            QQ^3 >= QQ^2 >= QQ^1 >= 0
            sage: F._power_operation(2, 'antisymmetric')
            QQ^1 >= 0
        """
        from sage.modules.tensor_operations import VectorCollection, TensorOperation
        generators, indices = self.presentation()
        V = VectorCollection(generators, self.base_ring(), self.dimension())
        T = TensorOperation([V] * n, operation)

        iters = [self.support()] * n
        filtration = dict()
        from sage.categories.cartesian_product import cartesian_product
        for degrees in cartesian_product(iters):
            deg = sum(degrees)
            filt_deg = filtration.get(deg, set())
            for i in cartesian_product([indices.get(d) for d in degrees]):
                pow_i = T.index_map(*i)
                if pow_i is not None:
                    filt_deg.add(pow_i)
            filtration[deg] = filt_deg
        return FilteredVectorSpace(T.vectors(),
                                   filtration,
                                   base_ring=self.base_ring())
def difference_matrix_product(k, M1, G1, lmbda1, M2, G2, lmbda2, check=True):
    r"""
    Return the product of the ``(G1,k,lmbda1)`` and ``(G2,k,lmbda2)`` difference
    matrices ``M1`` and ``M2``.

    The result is a `(G1 \times G2, k, \lambda_1 \lambda_2)`-difference matrix.

    INPUT:

    - ``k,lmbda1,lmbda2`` -- positive integer

    - ``G1, G2`` -- groups

    - ``M1, M2`` -- ``(G1,k,lmbda1)`` and ``(G,k,lmbda2)`` difference
      matrices

    - ``check`` (boolean) -- if ``True`` (default), the output is checked before
      being returned.

    EXAMPLES::

        sage: from sage.combinat.designs.difference_matrices import (
        ....:     difference_matrix_product,
        ....:     is_difference_matrix)
        sage: G1,M1 = designs.difference_matrix(11,6)
        sage: G2,M2 = designs.difference_matrix(7,6)
        sage: G,M = difference_matrix_product(6,M1,G1,1,M2,G2,1)
        sage: G1
        Finite Field of size 11
        sage: G2
        Finite Field of size 7
        sage: G
        The cartesian product of (Finite Field of size 11, Finite Field of size 7)
        sage: is_difference_matrix(M,G,6,1)
        True
    """
    g1 = G1.cardinality()
    g2 = G2.cardinality()
    g = g1 * g2
    lmbda = lmbda1 * lmbda2
    from sage.categories.cartesian_product import cartesian_product
    G = cartesian_product([G1, G2])

    M = [[G((M1[j1][i], M2[j2][i])) for i in range(k)]
         for j1 in range(lmbda1 * g1) for j2 in range(lmbda2 * g2)]

    if check and not is_difference_matrix(M, G, k, lmbda, True):
        raise RuntimeError(
            "In the product construction, Sage built something which is not a ({},{},{})-DM!"
            .format(g, k, lmbda))

    return G, M
def difference_matrix_product(k, M1, G1, lmbda1, M2, G2, lmbda2, check=True):
    r"""
    Return the product of the ``(G1,k,lmbda1)`` and ``(G2,k,lmbda2)`` difference
    matrices ``M1`` and ``M2``.

    The result is a `(G1 \times G2, k, \lambda_1 \lambda_2)`-difference matrix.

    INPUT:

    - ``k,lmbda1,lmbda2`` -- positive integer

    - ``G1, G2`` -- groups

    - ``M1, M2`` -- ``(G1,k,lmbda1)`` and ``(G,k,lmbda2)`` difference
      matrices

    - ``check`` (boolean) -- if ``True`` (default), the output is checked before
      being returned.

    EXAMPLES::

        sage: from sage.combinat.designs.difference_matrices import (
        ....:     difference_matrix_product,
        ....:     is_difference_matrix)
        sage: G1,M1 = designs.difference_matrix(11,6)
        sage: G2,M2 = designs.difference_matrix(7,6)
        sage: G,M = difference_matrix_product(6,M1,G1,1,M2,G2,1)
        sage: G1
        Finite Field of size 11
        sage: G2
        Finite Field of size 7
        sage: G
        The Cartesian product of (Finite Field of size 11, Finite Field of size 7)
        sage: is_difference_matrix(M,G,6,1)
        True
    """
    g1 = G1.cardinality()
    g2 = G2.cardinality()
    g = g1 * g2
    lmbda = lmbda1 * lmbda2
    from sage.categories.cartesian_product import cartesian_product

    G = cartesian_product([G1, G2])

    M = [[G((M1[j1][i], M2[j2][i])) for i in range(k)] for j1 in range(lmbda1 * g1) for j2 in range(lmbda2 * g2)]

    if check and not is_difference_matrix(M, G, k, lmbda, True):
        raise RuntimeError(
            "In the product construction, Sage built something which is not a ({},{},{})-DM!".format(g, k, lmbda)
        )

    return G, M
 def __init__(self, R, n, r, inert=0):
     names = ["x%s%s" % (i, j) for i in range(r) for j in range(n)] + [
         "theta%s%s" % (i, j) for i in range(inert) for j in range(n)
     ]
     P = PolynomialRing(R, n * (r + inert), names)
     IsomorphicObject.__init__(self, P, Algebras(R))
     self._n = n
     self._r = r
     self._inert = inert
     self._P = P
     self._R = R
     self._grading_set = cartesian_product([ZZ for i in range(r)])
     self._hilbert_parent = PolynomialRing(ZZ, r, 'q')
Exemple #29
0
            def monoid_generators(self):
                """
                Return the generators of ``self``.

                EXAMPLES::

                    sage: M = Monoids.free([1,2,3])
                    sage: N = Monoids.free(['a','b'])
                    sage: C = cartesian_product([M, N])
                    sage: C.monoid_generators()
                    Family ((F[1], 1), (F[2], 1), (F[3], 1),
                            (1, F['a']), (1, F['b']))

                An example with an infinitely generated group (a better output
                is needed)::

                    sage: N = Monoids.free(ZZ)
                    sage: C = cartesian_product([M, N])
                    sage: C.monoid_generators()
                    Lazy family (gen(i))_{i in The Cartesian product of (...)}
                """
                F = self.cartesian_factors()
                ids = tuple(M.one() for M in F)

                def lift(i, gen):
                    cur = list(ids)
                    cur[i] = gen
                    return self._cartesian_product_of_elements(cur)

                from sage.sets.family import Family

                # Finitely generated
                cat = FiniteEnumeratedSets()
                if all(M.monoid_generators() in cat
                       or isinstance(M.monoid_generators(), (tuple, list))
                       for M in F):
                    ret = [
                        lift(i, gen) for i, M in enumerate(F)
                        for gen in M.monoid_generators()
                    ]
                    return Family(ret)

                # Infinitely generated
                # This does not return a good output, but it is "correct"
                # TODO: Figure out a better way to do things
                from sage.categories.cartesian_product import cartesian_product
                gens_prod = cartesian_product([
                    Family(M.monoid_generators(), lambda g: (i, g))
                    for i, M in enumerate(F)
                ])
                return Family(gens_prod, lift, name="gen")
    def _power_operation(self, n, operation):
        """
        Return tensor power operation.

        INPUT:

        - ``n`` -- integer. the number of factors of ``self``.

        - ``operation`` -- string. See
          :class:`~sage.modules.tensor_operations.TensorOperation` for
          details.

        EXAMPLES::

            sage: F = FilteredVectorSpace(1, 1) + FilteredVectorSpace(1, 2);  F
            QQ^2 >= QQ^1 >= 0
            sage: F._power_operation(2, 'symmetric')
            QQ^3 >= QQ^2 >= QQ^1 >= 0
            sage: F._power_operation(2, 'antisymmetric')
            QQ^1 >= 0
        """
        from sage.modules.tensor_operations import VectorCollection, TensorOperation
        generators, indices = self.presentation()
        V = VectorCollection(generators, self.base_ring(), self.dimension())
        T = TensorOperation([V] * n, operation)

        iters = [self.support()] * n
        filtration = dict()
        from sage.categories.cartesian_product import cartesian_product
        for degrees in cartesian_product(iters):
            deg = sum(degrees)
            filt_deg = filtration.get(deg, set())
            for i in cartesian_product([indices.get(d) for d in degrees]):
                pow_i = T.index_map(*i)
                if pow_i is not None:
                    filt_deg.add(pow_i)
            filtration[deg] = filt_deg
        return FilteredVectorSpace(T.vectors(), filtration, base_ring=self.base_ring())
Exemple #31
0
        def example(self):
            """
            EXAMPLES::

                sage: Sets().CartesianProducts().example()
                The cartesian product of (Set of prime numbers (basic implementation), An example of an infinite enumerated set: the non negative integers, An example of a finite enumerated set: {1,2,3})
            """
            from finite_enumerated_sets import FiniteEnumeratedSets
            from infinite_enumerated_sets import InfiniteEnumeratedSets
            from cartesian_product import cartesian_product
            S1 = Sets().example()
            S2 = InfiniteEnumeratedSets().example()
            S3 = FiniteEnumeratedSets().example()
            return cartesian_product([S1, S2, S3])
Exemple #32
0
        def example(self):
            """
            EXAMPLES::

                sage: Sets().CartesianProducts().example()
                The cartesian product of (Set of prime numbers (basic implementation), An example of an infinite enumerated set: the non negative integers, An example of a finite enumerated set: {1,2,3})
            """
            from finite_enumerated_sets import FiniteEnumeratedSets
            from infinite_enumerated_sets import InfiniteEnumeratedSets
            from cartesian_product import cartesian_product
            S1 = Sets().example()
            S2 = InfiniteEnumeratedSets().example()
            S3 = FiniteEnumeratedSets().example()
            return cartesian_product([S1, S2, S3])
        def _test_cartesian_product(self, tester=None, **options):
            from sage.misc.sage_unittest import TestSuite
            from sage.misc.lazy_format import LazyFormat

            if hasattr(self, "_suspension_tested"):
                return  # avoids infinity test cycle
            is_sub_testsuite = tester is not None
            tester = self._tester(tester=tester, **options)
            myatt = "_ycp_cartesian_product_tested"
            if not hasattr(self, myatt):
                X = cartesian_product((self, self))
                setattr(X, myatt, "yo")
                try:
                    tester.info(
                        "\n  Running the test suite of (self (+) self)")
                    TestSuite(X).run(
                        verbose=tester._verbose,
                        prefix=tester._prefix + "  ",
                        raise_on_failure=is_sub_testsuite,
                    )
                    f = X.cartesian_projection(0)
                    tester.info(
                        "\n  Running the test suite of the projection (self (+) self) -> self"
                    )
                    TestSuite(f).run(
                        verbose=tester._verbose,
                        prefix=tester._prefix + "  ",
                        raise_on_failure=is_sub_testsuite,
                        skip=[
                            "_test_category",
                            "_test_nonzero_equal",
                            "_test_pickling",
                        ],
                    )
                    f = X.summand_embedding(1)
                    tester.info(
                        "\n  Running the test suite of the embedding self -> (self (+) self)"
                    )
                    TestSuite(f).run(
                        verbose=tester._verbose,
                        prefix=tester._prefix + "  ",
                        raise_on_failure=is_sub_testsuite,
                        skip=[
                            "_test_category",
                            "_test_nonzero_equal",
                            "_test_pickling",
                        ],
                    )
                finally:
                    delattr(X, myatt)
Exemple #34
0
            def monoid_generators(self):
                """
                Return the generators of ``self``.

                EXAMPLES::

                    sage: M = Monoids.free([1,2,3])
                    sage: N = Monoids.free(['a','b'])
                    sage: C = cartesian_product([M, N])
                    sage: C.monoid_generators()
                    Family ((F[1], 1), (F[2], 1), (F[3], 1),
                            (1, F['a']), (1, F['b']))

                An example with an infinitely generated group (a better output
                is needed)::

                    sage: N = Monoids.free(ZZ)
                    sage: C = cartesian_product([M, N])
                    sage: C.monoid_generators()
                    Lazy family (gen(i))_{i in The Cartesian product of (...)}
                """
                F = self.cartesian_factors()
                ids = tuple(M.one() for M in F)

                def lift(i, gen):
                    cur = list(ids)
                    cur[i] = gen
                    return self._cartesian_product_of_elements(cur)

                from sage.sets.family import Family

                # Finitely generated
                cat = FiniteEnumeratedSets()
                if all(M.monoid_generators() in cat or isinstance(M.monoid_generators(), (tuple, list)) for M in F):
                    ret = [lift(i, gen) for i, M in enumerate(F) for gen in M.monoid_generators()]
                    return Family(ret)

                # Infinitely generated
                # This does not return a good output, but it is "correct"
                # TODO: Figure out a better way to do things
                from sage.categories.cartesian_product import cartesian_product

                gens_prod = cartesian_product(
                    [Family(M.monoid_generators(), lambda g: (i, g)) for i, M in enumerate(F)]
                )
                return Family(gens_prod, lift, name="gen")
Exemple #35
0
    def __init__(self, R):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: L = lie_algebras.Heisenberg(QQ, oo)
            sage: TestSuite(L).run()
            sage: L.p(1).bracket(L.q(1)) == L.z()
            True
            sage: L.q(1).bracket(L.p(1)) == -L.z()
            True
        """
        S = cartesian_product([PositiveIntegers(), ['p','q']])
        cat = LieAlgebras(R).Nilpotent().WithBasis()
        LieAlgebraWithGenerators.__init__(self, R, index_set=S, category=cat)
        HeisenbergAlgebra_abstract.__init__(self, S)
Exemple #36
0
    def __init__(self, R):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: L = lie_algebras.Heisenberg(QQ, oo)
            sage: TestSuite(L).run()
            sage: L.p(1).bracket(L.q(1)) == L.z()
            True
            sage: L.q(1).bracket(L.p(1)) == -L.z()
            True
        """
        S = cartesian_product([PositiveIntegers(), ['p', 'q']])
        cat = LieAlgebras(R).Nilpotent().WithBasis()
        LieAlgebraWithGenerators.__init__(self, R, index_set=S, category=cat)
        HeisenbergAlgebra_abstract.__init__(self, S)
Exemple #37
0
    def __init__(self, R, q):
        r"""
        Initialize ``self``.

        EXAMPLES::

            sage: AW = algebras.AskeyWilson(QQ)
            sage: TestSuite(AW).run()  # long time
        """
        self._q = q
        cat = Algebras(Rings().Commutative()).WithBasis()
        indices = cartesian_product([NonNegativeIntegers()]*6)
        CombinatorialFreeModule.__init__(self, R, indices, prefix='AW',
                                         sorting_key=_basis_key,
                                         sorting_reverse=True,
                                         category=cat)
        self._assign_names('A,B,C,a,b,g')
Exemple #38
0
        def cartesian_product(*elements):
            """
            Returns the cartesian product of its arguments, as an element of
            the cartesian product of the parents of those elements.

            EXAMPLES::

                sage: C = AlgebrasWithBasis(QQ)
                sage: A = C.example()
                sage: (a,b,c) = A.algebra_generators()
                sage: a.cartesian_product(b, c)
                B[(0, word: a)] + B[(1, word: b)] + B[(2, word: c)]

            FIXME: is this a policy that we want to enforce on all parents?
            """
            from sage.structure.element import parent, Element
            assert(all(isinstance(element, Element) for element in elements))
            parents = [parent(element) for element in elements]
            return cartesian_product(parents)._cartesian_product_of_elements(elements) # good name???
Exemple #39
0
    def _init_product(self):
        """
        Initialization for the tensor product

        EXAMPLES::

            sage: from sage.modules.tensor_operations import \
            ....:      VectorCollection, TensorOperation
            sage: R = VectorCollection([(1,0), (1,2), (-1,-2)], QQ, 2)
            sage: S = VectorCollection([(1,), (-1,)], QQ, 1)
            sage: R_tensor_S = TensorOperation([R,S], operation='product')
            sage: sorted(R_tensor_S._index_map.iteritems())   # indirect doctest
            [((0, 0), 0), ((0, 1), 1), ((1, 0), 2), ((1, 1), 3), ((2, 0), 3), ((2, 1), 2)]
        """
        V_list_indices = [range(V.n_vectors()) for V in self._V]
        from sage.categories.cartesian_product import cartesian_product
        for i in cartesian_product(V_list_indices):
            self._index_map[tuple(i)] = self._init_product_vectors(i)
        self._symmetrize_indices = False
def add_degrees_symmetric(gen_deg, op_deg):
    """
    Compute the sum componentwise of the lists of integrers contained in d1 and d2 
    and return an ordered grading set and the partition contained in d2 as result.
    
    INPUT:
        - ``d1`` -- list containing a list of integers and a partition
        - ``d2`` -- list of integers

    EXAMPLES::
        sage: d1 = ([0,3],[2,1])
        sage: d2 = [0,-1]
        sage: add_degrees_symmetric(d1, d2)
        ((2, 0), [2, 1])
        sage: add_degrees_symmetric(([2,0,1],[3,2]), [-1,0,0])
        ((1, 1, 0), [3, 2])
    """
    D = cartesian_product([ZZ for i in range(len(gen_deg[0]))])
    d1, d2 = add_degrees_isotypic(gen_deg, op_deg)
    return D(sorted(d1, reverse=True)), d2
Exemple #41
0
        def cartesian_product(*elements):
            """
            Returns the cartesian product of its arguments, as an element of
            the cartesian product of the parents of those elements.

            EXAMPLES::

                sage: C = AlgebrasWithBasis(QQ)
                sage: A = C.example()
                sage: (a,b,c) = A.algebra_generators()
                sage: a.cartesian_product(b, c)
                B[(0, word: a)] + B[(1, word: b)] + B[(2, word: c)]

            FIXME: is this a policy that we want to enforce on all parents?
            """
            from sage.structure.element import parent, Element
            assert (all(isinstance(element, Element) for element in elements))
            parents = [parent(element) for element in elements]
            return cartesian_product(parents)._cartesian_product_of_elements(
                elements)  # good name???
Exemple #42
0
    def basis(self):
        """
        Return the basis of ``self``.

        EXAMPLES::

            sage: L = lie_algebras.Heisenberg(QQ, oo)
            sage: L.basis()
            Lazy family (basis map(i))_{i in Disjoint union of Family ({'z'},
             The Cartesian product of (Positive integers, {'p', 'q'}))}
            sage: L.basis()['z']
            z
            sage: L.basis()[(12, 'p')]
            p12
        """
        S = cartesian_product([PositiveIntegers(), ['p','q']])
        I = DisjointUnionEnumeratedSets([Set(['z']), S])
        def basis_elt(x):
            if isinstance(x, str):
                return self.monomial(x)
            return self.monomial(x[1] + str(x[0]))
        return Family(I, basis_elt, name="basis map")
Exemple #43
0
    def __init__(self, R, cartan_matrix, wt, prefix):
        """
        Initialize ``self``.
        """
        self._cartan_matrix = cartan_matrix
        self._weight = wt
        self._d = sum(wt)

        # Reduced words
        #red_words = Family(Permutations(self._d), lambda p: tuple(p.reduced_word()))
        red_words = FiniteEnumeratedSet([tuple(p.reduced_word())
                                         for p in Permutations(self._d)])
        red_words.rename("reduced words of S_{}".format(self._d))
        # The monomials
        M = FreeAbelianMonoid(self._d, names=['x%s'%i for i in range(1, self._d+1)])
        # Idempotents (i.e. the colors of the strands)
        index_set = self._cartan_matrix.index_set()
        P = Permutations(sum([[index_set[i]]*v for i,v in enumerate(wt)],[]))
        I = cartesian_product([red_words, M, P])
        CombinatorialFreeModule.__init__(self, R, I, prefix=prefix,
                                         monomial_key=KLRAlgebra._monomial_key,
                                         category=Algebras(R).WithBasis().Graded())
Exemple #44
0
    def _init_symmetric(self):
        """
        Initialization for the symmetric product.

        EXAMPLES::

            sage: from sage.modules.tensor_operations import \
            ....:      VectorCollection, TensorOperation
            sage: R = VectorCollection([(1,0), (1,2), (-1,-2)], QQ, 2)
            sage: Sym2_R = TensorOperation([R,R], operation='symmetric')  # indirect doctest
            sage: sorted(Sym2_R._index_map.iteritems())
            [((0, 0), 0), ((0, 1), 1), ((0, 2), 2), ((1, 1), 3), ((1, 2), 4), ((2, 2), 3)]
        """
        V_list_indices = [range(V.n_vectors()) for V in self._V]
        Sym = symmetrized_coordinate_sums(self._V[0].dimension(), len(self._V))
        from sage.categories.cartesian_product import cartesian_product
        N = len(V_list_indices)
        for i in cartesian_product(V_list_indices):
            if any(i[j - 1] > i[j] for j in range(1, N)):
                continue
            self._index_map[tuple(i)] = self._init_power_operation_vectors(i, Sym)
        self._symmetrize_indices = True
Exemple #45
0
    def basis(self):
        """
        Return the basis of ``self``.

        EXAMPLES::

            sage: L = lie_algebras.Heisenberg(QQ, oo)
            sage: L.basis()
            Lazy family (basis map(i))_{i in Disjoint union of Family ({'z'},
             The Cartesian product of (Positive integers, {'p', 'q'}))}
            sage: L.basis()['z']
            z
            sage: L.basis()[(12, 'p')]
            p12
        """
        S = cartesian_product([PositiveIntegers(), ['p','q']])
        I = DisjointUnionEnumeratedSets([Set(['z']), S])
        def basis_elt(x):
            if isinstance(x, str):
                return self.monomial(x)
            return self.monomial(x[1] + str(x[0]))
        return Family(I, basis_elt, name="basis map")
Exemple #46
0
    def finer(self):
        """
        Return the set of ordered set partitions which are finer
        than ``self``.

        See :meth:`is_finer` for the definition of "finer".

        EXAMPLES::

            sage: C = OrderedSetPartition([[1, 3], [2]]).finer()
            sage: C.cardinality()
            3
            sage: C.list()
            [[{1}, {3}, {2}], [{3}, {1}, {2}], [{1, 3}, {2}]]

            sage: OrderedSetPartition([]).finer()
            {[]}

            sage: W = OrderedSetPartition([[4, 9], [-1, 2]])
            sage: W.finer().list()
            [[{9}, {4}, {2}, {-1}],
             [{9}, {4}, {-1}, {2}],
             [{9}, {4}, {-1, 2}],
             [{4}, {9}, {2}, {-1}],
             [{4}, {9}, {-1}, {2}],
             [{4}, {9}, {-1, 2}],
             [{4, 9}, {2}, {-1}],
             [{4, 9}, {-1}, {2}],
             [{4, 9}, {-1, 2}]]
        """
        par = parent(self)
        if not self:
            return FiniteEnumeratedSet([self])
        else:
            return FiniteEnumeratedSet([
                par(sum((list(i) for i in C), [])) for C in cartesian_product(
                    [OrderedSetPartitions(X) for X in self])
            ])
    def _construct_spx(r, s, multiedges = None, **kargs):
        r"""
        Construct a SPX(2, r, s) graph.

        Return a tuple containing the data that can be used to construct
        the requested SPX graph, and a boolean indicating whether the
        constructed graph should be considered a multigraph.

        INPUT:

        - ``r`` - the ``r`` parameter indicating the range of the counter.

        - ``s`` - the ``s`` parameter indicating the length of the string.

        - ``multiedges`` - whether the constructed graph should be considered
          a multigraph. If ``None`` (default), the second element of the output
          will be set to ``True`` when ``r = 1``. If ``False`` and ``r = 1``,
          a ``ValueError`` is raised. Otherwise, the second element of the
          output will be ``multiedges``.

        - any other named parameters are silently ignored.
        """
        c = [tuple(x) for x
             in cartesian_product([[tuple(y) for y
                                    in Integers(2)**Integer(s)], Integers(r),
                                   [Integer(1), Integer(-1)]])]
        if r == 1:
            if multiedges is False:
                raise ValueError("A SPX graph with r = 1 has multiple edges")
            data = sum([[((v, n, t), (v, n, -t)),
                         ((v, n, t), (v[1:] + (Integer(0),), n, -t)),
                         ((v, n, t), (v[1:] + (Integer(1),), n, -t))]
                        for v, n, t in c if t == 1], [])
            multiedges = True
        else:
            data = [c, spx_adj]
        return (data, multiedges)
    def finer(self):
        """
        Return the set of ordered set partitions which are finer
        than ``self``.

        See :meth:`is_finer` for the definition of "finer".

        EXAMPLES::

            sage: C = OrderedSetPartition([[1, 3], [2]]).finer()
            sage: C.cardinality()
            3
            sage: C.list()
            [[{1}, {3}, {2}], [{3}, {1}, {2}], [{1, 3}, {2}]]

            sage: OrderedSetPartition([]).finer()
            {[]}

            sage: W = OrderedSetPartition([[4, 9], [-1, 2]])
            sage: W.finer().list()
            [[{9}, {4}, {2}, {-1}],
             [{9}, {4}, {-1}, {2}],
             [{9}, {4}, {-1, 2}],
             [{4}, {9}, {2}, {-1}],
             [{4}, {9}, {-1}, {2}],
             [{4}, {9}, {-1, 2}],
             [{4, 9}, {2}, {-1}],
             [{4, 9}, {-1}, {2}],
             [{4, 9}, {-1, 2}]]
        """
        par = parent(self)
        if not self:
            return FiniteEnumeratedSet([self])
        else:
            return FiniteEnumeratedSet([par(sum((list(i) for i in C), []))
                    for C in cartesian_product([OrderedSetPartitions(X) for X in self])])
    def SingularityAnalysis(var, zeta=1, alpha=0, beta=0, delta=0,
                            precision=None, normalized=True):
        r"""
        Return the asymptotic expansion of the coefficients of
        an power series with specified pole and logarithmic singularity.

        More precisely, this extracts the `n`-th coefficient

        .. MATH::

            [z^n] \left(\frac{1}{1-z/\zeta}\right)^\alpha
            \left(\frac{1}{z/\zeta} \log \frac{1}{1-z/\zeta}\right)^\beta
            \left(\frac{1}{z/\zeta} \log
            \left(\frac{1}{z/\zeta} \log \frac{1}{1-z/\zeta}\right)\right)^\delta

        (if ``normalized=True``, the default) or

        .. MATH::

            [z^n] \left(\frac{1}{1-z/\zeta}\right)^\alpha
            \left(\log \frac{1}{1-z/\zeta}\right)^\beta
            \left(\log
            \left(\frac{1}{z/\zeta} \log \frac{1}{1-z/\zeta}\right)\right)^\delta

        (if ``normalized=False``).

        INPUT:

        - ``var`` -- a string for the variable name.

        - ``zeta`` -- (default: `1`) the location of the singularity.

        - ``alpha`` -- (default: `0`) the pole order of the singularty.

        - ``beta`` -- (default: `0`) the order of the logarithmic singularity.

        - ``delta`` -- (default: `0`) the order of the log-log singularity.
          Not yet implemented for ``delta != 0``.

        - ``precision`` -- (default: ``None``) an integer. If ``None``, then
          the default precision of the asymptotic ring is used.

        - ``normalized`` -- (default: ``True``) a boolean, see above.

        OUTPUT:

        An asymptotic expansion.

        EXAMPLES::

            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=1)
            1
            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=2)
            n + 1
            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=3)
            1/2*n^2 + 3/2*n + 1
            sage: _.parent()
            Asymptotic Ring <n^ZZ> over Rational Field

        ::

            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=-3/2,
            ....:     precision=3)
            3/4/sqrt(pi)*n^(-5/2)
            + 45/32/sqrt(pi)*n^(-7/2)
            + 1155/512/sqrt(pi)*n^(-9/2)
            + O(n^(-11/2))
            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=-1/2,
            ....:     precision=3)
            -1/2/sqrt(pi)*n^(-3/2)
            - 3/16/sqrt(pi)*n^(-5/2)
            - 25/256/sqrt(pi)*n^(-7/2)
            + O(n^(-9/2))
            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=1/2,
            ....:     precision=4)
            1/sqrt(pi)*n^(-1/2)
            - 1/8/sqrt(pi)*n^(-3/2)
            + 1/128/sqrt(pi)*n^(-5/2)
            + 5/1024/sqrt(pi)*n^(-7/2)
            + O(n^(-9/2))
            sage: _.parent()
            Asymptotic Ring <n^QQ> over Symbolic Constants Subring

        ::

            sage: S = SR.subring(rejecting_variables=('n',))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=S.var('a'),
            ....:     precision=4).map_coefficients(lambda c: c.factor())
            1/gamma(a)*n^(a - 1)
            + (1/2*(a - 1)*a/gamma(a))*n^(a - 2)
            + (1/24*(3*a - 1)*(a - 1)*(a - 2)*a/gamma(a))*n^(a - 3)
            + (1/48*(a - 1)^2*(a - 2)*(a - 3)*a^2/gamma(a))*n^(a - 4)
            + O(n^(a - 5))
            sage: _.parent()
            Asymptotic Ring <n^(Symbolic Subring rejecting the variable n)>
            over Symbolic Subring rejecting the variable n

        ::

            sage: ae = asymptotic_expansions.SingularityAnalysis('n',
            ....:          alpha=1/2, beta=1, precision=4); ae
            1/sqrt(pi)*n^(-1/2)*log(n) + ((euler_gamma + 2*log(2))/sqrt(pi))*n^(-1/2)
            - 5/8/sqrt(pi)*n^(-3/2)*log(n) + (1/8*(3*euler_gamma + 6*log(2) - 8)/sqrt(pi)
            - (euler_gamma + 2*log(2) - 2)/sqrt(pi))*n^(-3/2) + O(n^(-5/2)*log(n))
            sage: n = ae.parent().gen()
            sage: ae.subs(n=n-1).map_coefficients(lambda x: x.canonicalize_radical())
            1/sqrt(pi)*n^(-1/2)*log(n)
            + ((euler_gamma + 2*log(2))/sqrt(pi))*n^(-1/2)
            - 1/8/sqrt(pi)*n^(-3/2)*log(n)
            + (-1/8*(euler_gamma + 2*log(2))/sqrt(pi))*n^(-3/2)
            + O(n^(-5/2)*log(n))

        ::

            sage: asymptotic_expansions.SingularityAnalysis('n',
            ....:     alpha=1, beta=1/2, precision=4)
            log(n)^(1/2) + 1/2*euler_gamma*log(n)^(-1/2)
            + (-1/8*euler_gamma^2 + 1/48*pi^2)*log(n)^(-3/2)
            + (1/16*euler_gamma^3 - 1/32*euler_gamma*pi^2 + 1/8*zeta(3))*log(n)^(-5/2)
            + O(log(n)^(-7/2))

        ::

            sage: ae = asymptotic_expansions.SingularityAnalysis('n',
            ....:     alpha=0, beta=2, precision=14)
            sage: n = ae.parent().gen()
            sage: ae.subs(n=n-2)
            2*n^(-1)*log(n) + 2*euler_gamma*n^(-1) - n^(-2) - 1/6*n^(-3) + O(n^(-5))

        ::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=-1/2, beta=1, precision=2, normalized=False)
            -1/2/sqrt(pi)*n^(-3/2)*log(n)
            + (-1/2*(euler_gamma + 2*log(2) - 2)/sqrt(pi))*n^(-3/2)
            + O(n^(-5/2)*log(n))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1/2, alpha=0, beta=1, precision=3, normalized=False)
            2^n*n^(-1) + O(2^n*n^(-2))


        ALGORITHM:

        See [FS2009]_ together with the
        `errata list <http://algo.inria.fr/flajolet/Publications/AnaCombi/errata.pdf>`_.

        REFERENCES:

        .. [FS2009] Philippe Flajolet and Robert Sedgewick,
           `Analytic combinatorics <http://algo.inria.fr/flajolet/Publications/AnaCombi/book.pdf>`_.
           Cambridge University Press, Cambridge, 2009.

        TESTS::

            sage: ex = asymptotic_expansions.SingularityAnalysis('n', alpha=-1/2,
            ....:     precision=4)
            sage: n = ex.parent().gen()
            sage: coefficients = ((1-x)^(1/2)).series(
            ....:     x, 21).truncate().coefficients(x, sparse=False)
            sage: ex.compare_with_values(n,    # rel tol 1e-6
            ....:     lambda k: coefficients[k], [5, 10, 20])
            [(5, 0.015778873294?), (10, 0.01498952777?), (20, 0.0146264622?)]
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=3, precision=2)
            1/2*n^2 + 3/2*n + O(1)
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=3, precision=3)
            1/2*n^2 + 3/2*n + 1
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=3, precision=4)
            1/2*n^2 + 3/2*n + 1

        ::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=0)
            Traceback (most recent call last):
            ...
            NotImplementedOZero: The error term in the result is O(0)
            which means 0 for sufficiently large n.
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=-1)
            Traceback (most recent call last):
            ...
            NotImplementedOZero: The error term in the result is O(0)
            which means 0 for sufficiently large n.

        ::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'm', alpha=-1/2, precision=3)
            -1/2/sqrt(pi)*m^(-3/2)
            - 3/16/sqrt(pi)*m^(-5/2)
            - 25/256/sqrt(pi)*m^(-7/2)
            + O(m^(-9/2))
            sage: _.parent()
            Asymptotic Ring <m^QQ> over Symbolic Constants Subring

        Location of the singularity::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=1, zeta=2, precision=3)
            (1/2)^n
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=1, zeta=1/2, precision=3)
            2^n
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=1, zeta=CyclotomicField(3).gen(),
            ....:      precision=3)
            (-zeta3 - 1)^n
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=4, zeta=2, precision=3)
            1/6*(1/2)^n*n^3 + (1/2)^n*n^2 + 11/6*(1/2)^n*n + O((1/2)^n)
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=-1, zeta=2, precision=3)
            Traceback (most recent call last):
            ...
            NotImplementedOZero: The error term in the result is O(0)
            which means 0 for sufficiently large n.
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=1/2, zeta=2, precision=3)
            1/sqrt(pi)*(1/2)^n*n^(-1/2) - 1/8/sqrt(pi)*(1/2)^n*n^(-3/2)
            + 1/128/sqrt(pi)*(1/2)^n*n^(-5/2) + O((1/2)^n*n^(-7/2))

        The following tests correspond to Table VI.5 in [FS2009]_. ::

            sage: A.<n> = AsymptoticRing('n^QQ * log(n)^QQ', QQ)
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=-1/2, beta=1, precision=2,
            ....:     normalized=False) * (- sqrt(pi*n^3))
            1/2*log(n) + 1/2*euler_gamma + log(2) - 1 + O(n^(-1)*log(n))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=0, beta=1, precision=3,
            ....:     normalized=False)
            n^(-1) + O(n^(-2))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=0, beta=2,  precision=14,
            ....:     normalized=False) * n
            2*log(n) + 2*euler_gamma - n^(-1) - 1/6*n^(-2) +  O(n^(-4))
            sage: (asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=1/2, beta=1, precision=4,
            ....:     normalized=False) * sqrt(pi*n)).\
            ....:     map_coefficients(lambda x: x.expand())
            log(n) + euler_gamma + 2*log(2) - 1/8*n^(-1)*log(n) +
            (-1/8*euler_gamma - 1/4*log(2))*n^(-1) + O(n^(-2)*log(n))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=1, beta=1, precision=13,
            ....:     normalized=False)
            log(n) + euler_gamma + 1/2*n^(-1) - 1/12*n^(-2) + 1/120*n^(-4)
            + O(n^(-6))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=1, beta=2, precision=4,
            ....:     normalized=False)
            log(n)^2 + 2*euler_gamma*log(n) + euler_gamma^2 - 1/6*pi^2
            + O(n^(-1)*log(n))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=3/2, beta=1, precision=3,
            ....:     normalized=False) * sqrt(pi/n)
            2*log(n) + 2*euler_gamma + 4*log(2) - 4 + 3/4*n^(-1)*log(n)
            + O(n^(-1))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=2, beta=1, precision=5,
            ....:     normalized=False)
            n*log(n) + (euler_gamma - 1)*n + log(n) + euler_gamma + 1/2
            + O(n^(-1))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=2, beta=2, precision=4,
            ....:     normalized=False) / n
            log(n)^2 + (2*euler_gamma - 2)*log(n)
            - 2*euler_gamma + euler_gamma^2 - 1/6*pi^2 + 2
            + n^(-1)*log(n)^2 + O(n^(-1)*log(n))

        Be aware that the last result does *not* coincide with [FS2009]_,
        they do have a different error term.

        Checking parameters::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, 1, 1/2, precision=0, normalized=False)
            Traceback (most recent call last):
            ...
            ValueError: beta and delta must be integers
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, 1, 1, 1/2, normalized=False)
            Traceback (most recent call last):
            ...
            ValueError: beta and delta must be integers

        ::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=0, beta=0, delta=1, precision=3)
            Traceback (most recent call last):
            ...
            NotImplementedError: not implemented for delta!=0
        """
        from itertools import islice, count
        from asymptotic_ring import AsymptoticRing
        from growth_group import ExponentialGrowthGroup, \
                MonomialGrowthGroup
        from sage.arith.all import falling_factorial
        from sage.categories.cartesian_product import cartesian_product
        from sage.functions.other import binomial, gamma
        from sage.calculus.calculus import limit
        from sage.misc.cachefunc import cached_function
        from sage.arith.srange import srange
        from sage.rings.rational_field import QQ
        from sage.rings.integer_ring import ZZ
        from sage.symbolic.ring import SR

        SCR = SR.subring(no_variables=True)
        s = SR('s')
        iga = 1/gamma(alpha)
        if iga.parent() is SR:
            try:
                iga = SCR(iga)
            except TypeError:
                pass

        coefficient_ring = iga.parent()
        if beta != 0:
            coefficient_ring = SCR

        @cached_function
        def inverse_gamma_derivative(shift, r):
            """
            Return value of `r`-th derivative of 1/Gamma
            at alpha-shift.
            """
            if r == 0:
                result = iga*falling_factorial(alpha-1, shift)
            else:
                result = limit((1/gamma(s)).diff(s, r), s=alpha-shift)

            try:
                return coefficient_ring(result)
            except TypeError:
                return result

        if isinstance(alpha, int):
            alpha = ZZ(alpha)
        if isinstance(beta, int):
            beta = ZZ(beta)
        if isinstance(delta, int):
            delta = ZZ(delta)

        if precision is None:
            precision = AsymptoticRing.__default_prec__


        if not normalized and not (beta in ZZ and delta in ZZ):
            raise ValueError("beta and delta must be integers")
        if delta != 0:
            raise NotImplementedError("not implemented for delta!=0")

        groups = []
        if zeta != 1:
            groups.append(ExponentialGrowthGroup((1/zeta).parent(), var))

        groups.append(MonomialGrowthGroup(alpha.parent(), var))
        if beta != 0:
            groups.append(MonomialGrowthGroup(beta.parent(), 'log({})'.format(var)))

        group = cartesian_product(groups)
        A = AsymptoticRing(growth_group=group, coefficient_ring=coefficient_ring,
                           default_prec=precision)
        n = A.gen()

        if zeta == 1:
            exponential_factor = 1
        else:
            exponential_factor = n.rpow(1/zeta)

        if beta in ZZ and beta >= 0:
            it = ((k, r)
                  for k in count()
                  for r in srange(beta+1))
            k_max = precision
        else:
            it = ((0, r)
                  for r in count())
            k_max = 0

        if beta != 0:
            log_n = n.log()
        else:
            # avoid construction of log(n)
            # because it does not exist in growth group.
            log_n = 1

        it = reversed(list(islice(it, precision+1)))
        if normalized:
            beta_denominator = beta
        else:
            beta_denominator = 0
        L = _sa_coefficients_lambda_(max(1, k_max), beta=beta_denominator)
        (k, r) = next(it)
        result = (n**(-k) * log_n**(-r)).O()

        if alpha in ZZ and beta == 0:
            if alpha > 0 and alpha <= precision:
                result = A(0)
            elif alpha <= 0 and precision > 0:
                from misc import NotImplementedOZero
                raise NotImplementedOZero(A)

        for (k, r) in it:
            result += binomial(beta, r) * \
                sum(L[(k, ell)] * (-1)**ell *
                    inverse_gamma_derivative(ell, r)
                    for ell in srange(k, 2*k+1)
                    if (k, ell) in L) * \
                n**(-k) * log_n**(-r)

        result *= exponential_factor * n**(alpha-1) * log_n**beta

        return result
Exemple #50
0
def mcfarland_1973_construction(q, s):
    r"""
    Return a difference set.

    The difference set returned has the following parameters

    .. MATH::

        v = \frac{q^{s+1}(q^{s+1}+q-2)}{q-1},
        k = \frac{q^s (q^{s+1}-1)}{q-1},
        \lambda = \frac{q^s(q^s-1)}{q-1}

    This construction is due to [McF1973]_.

    INPUT:

    - ``q``, ``s`` - (integers) parameters for the difference set (see the above
      formulas for the expression of ``v``, ``k``, ``l`` in terms of ``q`` and
      ``s``)

    .. SEEALSO::

        The function :func:`are_mcfarland_1973_parameters` makes the translation
        between the parameters `(q,s)` corresponding to a given triple
        `(v,k,\lambda)`.

    REFERENCES:

    .. [McF1973] Robert L. McFarland
       "A family of difference sets in non-cyclic groups"
       Journal of Combinatorial Theory (A) vol 15 (1973).
       http://dx.doi.org/10.1016/0097-3165(73)90031-9

    EXAMPLES::

        sage: from sage.combinat.designs.difference_family import (
        ....:    mcfarland_1973_construction, is_difference_family)

        sage: G,D = mcfarland_1973_construction(3, 1)
        sage: assert is_difference_family(G, D, 45, 12, 3)

        sage: G,D = mcfarland_1973_construction(2, 2)
        sage: assert is_difference_family(G, D, 64, 28, 12)
    """
    from sage.rings.finite_rings.finite_field_constructor import GF
    from sage.modules.free_module import VectorSpace
    from sage.rings.finite_rings.integer_mod_ring import Zmod
    from sage.categories.cartesian_product import cartesian_product
    from itertools import izip

    r = (q**(s+1)-1) // (q-1)
    F = GF(q,'a')
    V = VectorSpace(F, s+1)
    K = Zmod(r+1)

    G = cartesian_product([F]*(s+1) + [K])

    D = []
    for k,H in izip(K, V.subspaces(s)):
        for v in H:
            D.append(G((tuple(v) + (k,))))

    return G,[D]
    def _pushout_(self, other):
        r"""
        Construct the pushout of this and the other growth group. This is called by
        :func:`sage.categories.pushout.pushout`.

        TESTS::

            sage: from sage.rings.asymptotic.growth_group import GrowthGroup
            sage: from sage.categories.pushout import pushout
            sage: cm = sage.structure.element.get_coercion_model()
            sage: A = GrowthGroup('QQ^x * x^ZZ')
            sage: B = GrowthGroup('x^ZZ * log(x)^ZZ')
            sage: A._pushout_(B)
            Growth Group QQ^x * x^ZZ * log(x)^ZZ
            sage: pushout(A, B)
            Growth Group QQ^x * x^ZZ * log(x)^ZZ
            sage: cm.discover_coercion(A, B)
            ((map internal to coercion system -- copy before use)
             Conversion map:
               From: Growth Group QQ^x * x^ZZ
               To:   Growth Group QQ^x * x^ZZ * log(x)^ZZ,
             (map internal to coercion system -- copy before use)
             Conversion map:
               From: Growth Group x^ZZ * log(x)^ZZ
               To:   Growth Group QQ^x * x^ZZ * log(x)^ZZ)
            sage: cm.common_parent(A, B)
            Growth Group QQ^x * x^ZZ * log(x)^ZZ

        ::

            sage: C = GrowthGroup('QQ^x * x^QQ * y^ZZ')
            sage: D = GrowthGroup('x^ZZ * log(x)^QQ * QQ^z')
            sage: C._pushout_(D)
            Growth Group QQ^x * x^QQ * log(x)^QQ * y^ZZ * QQ^z
            sage: cm.common_parent(C, D)
            Growth Group QQ^x * x^QQ * log(x)^QQ * y^ZZ * QQ^z
            sage: A._pushout_(D)
            Growth Group QQ^x * x^ZZ * log(x)^QQ * QQ^z
            sage: cm.common_parent(A, D)
            Growth Group QQ^x * x^ZZ * log(x)^QQ * QQ^z
            sage: cm.common_parent(B, D)
            Growth Group x^ZZ * log(x)^QQ * QQ^z
            sage: cm.common_parent(A, C)
            Growth Group QQ^x * x^QQ * y^ZZ
            sage: E = GrowthGroup('log(x)^ZZ * y^ZZ')
            sage: cm.common_parent(A, E)
            Traceback (most recent call last):
            ...
            TypeError: no common canonical parent for objects with parents:
            'Growth Group QQ^x * x^ZZ' and 'Growth Group log(x)^ZZ * y^ZZ'

        ::

            sage: F = GrowthGroup('z^QQ')
            sage: pushout(C, F)
            Growth Group QQ^x * x^QQ * y^ZZ * z^QQ

        ::

            sage: pushout(GrowthGroup('QQ^x * x^ZZ'), GrowthGroup('ZZ^x * x^QQ'))
            Growth Group QQ^x * x^QQ
            sage: cm.common_parent(GrowthGroup('QQ^x * x^ZZ'), GrowthGroup('ZZ^x * x^QQ'))
            Growth Group QQ^x * x^QQ
        """
        from growth_group import GenericGrowthGroup, AbstractGrowthGroupFunctor
        from misc import merge_overlapping
        from misc import underlying_class

        if isinstance(other, GenericProduct):
            Ofactors = other.cartesian_factors()
        elif isinstance(other, GenericGrowthGroup):
            Ofactors = (other,)
        elif other.construction() is not None and isinstance(other.construction()[0], AbstractGrowthGroupFunctor):
            Ofactors = (other,)
        else:
            return

        def pushout_univariate_factors(self, other, var, Sfactors, Ofactors):
            try:
                return merge_overlapping(Sfactors, Ofactors, lambda f: (underlying_class(f), f._var_.var_repr))
            except ValueError:
                pass

            cm = sage.structure.element.get_coercion_model()
            try:
                Z = cm.common_parent(*Sfactors + Ofactors)
                return (Z,), (Z,)
            except TypeError:
                pass

            def subfactors(F):
                for f in F:
                    if isinstance(f, GenericProduct):
                        for g in subfactors(f.cartesian_factors()):
                            yield g
                    else:
                        yield f

            try:
                return merge_overlapping(
                    tuple(subfactors(Sfactors)),
                    tuple(subfactors(Ofactors)),
                    lambda f: (underlying_class(f), f._var_.var_repr),
                )
            except ValueError:
                pass

            from sage.structure.coerce_exceptions import CoercionException

            raise CoercionException(
                "Cannot construct the pushout of %s and %s: The factors "
                "with variables %s are not overlapping, "
                "no common parent was found, and "
                "splitting the factors was unsuccessful." % (self, other, var)
            )

        class it:
            def __init__(self, it):
                self.it = it
                self.var = None
                self.factors = None

            def next(self):
                try:
                    self.var, factors = next(self.it)
                    self.factors = tuple(factors)
                except StopIteration:
                    self.var = None
                    self.factors = tuple()

        from itertools import groupby

        S = it(groupby(self.cartesian_factors(), key=lambda k: k.variable_names()))
        O = it(groupby(Ofactors, key=lambda k: k.variable_names()))

        newS = []
        newO = []

        S.next()
        O.next()
        while S.var is not None or O.var is not None:
            if S.var is not None and S.var < O.var:
                newS.extend(S.factors)
                newO.extend(S.factors)
                S.next()
            elif O.var is not None and S.var > O.var:
                newS.extend(O.factors)
                newO.extend(O.factors)
                O.next()
            else:
                SL, OL = pushout_univariate_factors(self, other, S.var, S.factors, O.factors)
                newS.extend(SL)
                newO.extend(OL)
                S.next()
                O.next()

        assert len(newS) == len(newO)

        if len(self.cartesian_factors()) == len(newS) and len(other.cartesian_factors()) == len(newO):
            # We had already all factors in each of the self and
            # other, thus splitting it in subproblems (one for
            # each factor) is the strategy to use. If a pushout is
            # possible :func:`sage.categories.pushout.pushout`
            # will manage this by itself.
            return

        from sage.categories.pushout import pushout
        from sage.categories.cartesian_product import cartesian_product

        return pushout(cartesian_product(newS), cartesian_product(newO))
Exemple #52
0
 def polygon_labels(self):
     from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
     from sage.categories.cartesian_product import cartesian_product
     return cartesian_product([self._words, FiniteEnumeratedSet([0,1,2,3])])
Exemple #53
0
def CartesianProduct(*iters):
    """
    This is deprecated. Use :obj:`cartesian_product` instead.

    EXAMPLES::

        sage: cp = CartesianProduct([1,2], [3,4]); cp
        doctest:...: DeprecationWarning: CartesianProduct is deprecated. Use
        cartesian_product instead
        See http://trac.sagemath.org/18411 for details.
        The Cartesian product of ({1, 2}, {3, 4})
        sage: cp.list()
        [(1, 3), (1, 4), (2, 3), (2, 4)]

    Note that you must not use a generator-type object that is
    returned by a function (using "yield"). They cannot be copied or
    rewound (you cannot jump back to the beginning), but this is
    necessary to construct the Cartesian product::

        sage: def a(n): yield 1*n; yield 2*n
        sage: def b(): yield 'a'; yield 'b'
        sage: CartesianProduct(a(3), b()).list()
        Traceback (most recent call last):
        ...
        ValueError: generators are not allowed, see the
        documentation (type "CartesianProduct?") for a workaround

    The usage of iterable is also deprecated, so the following will no longer be
    supported::

        sage: from sage.combinat.misc import IterableFunctionCall
        sage: C = CartesianProduct(IterableFunctionCall(a, 3), IterableFunctionCall(b))
        doctest:...: DeprecationWarning: Usage of IterableFunctionCall in
        CartesianProduct is deprecated. You can use EnumeratedSetFromIterator
        (in sage.sets.set_from_iterator) instead.
        See http://trac.sagemath.org/18411 for details.
        sage: list(C)
        doctest:...: UserWarning: Sage is not able to determine whether the
        factors of this Cartesian product are finite. The lexicographic ordering
        might not go through all elements.
        [(3, 'a'), (3, 'b'), (6, 'a'), (6, 'b')]

    You might use
    :class:`~sage.sets.set_from_iterator.EnumeratedSetFromIterator` for that
    purpose.::

        sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator
        sage: A = EnumeratedSetFromIterator(a, (3,), category=FiniteEnumeratedSets())
        sage: B = EnumeratedSetFromIterator(b, category=FiniteEnumeratedSets())
        sage: C = cartesian_product([A, B])
        sage: C.list()
        [(3, 'a'), (3, 'b'), (6, 'a'), (6, 'b')]
    """
    if any(isgenerator(i) for i in iters):
        raise ValueError('generators are not allowed, see the documentation '+
                         '(type "CartesianProduct?") for a workaround')

    from sage.misc.superseded import deprecation
    deprecation(18411, "CartesianProduct is deprecated. Use cartesian_product instead")

    from sage.combinat.misc import IterableFunctionCall
    deprecate_ifc = False
    iiters = []
    for a in iters:
        if isinstance(a, IterableFunctionCall):
            deprecate_ifc = True
            iiters.append(EnumeratedSetFromIterator(a.f, a.args, a.kwargs))
        else:
            iiters.append(a)
    iters = tuple(iiters)

    if deprecate_ifc:
        deprecation(18411, """Usage of IterableFunctionCall in CartesianProduct is deprecated. You can use EnumeratedSetFromIterator (in sage.sets.set_from_iterator) instead.""")

    from sage.categories.cartesian_product import cartesian_product
    return cartesian_product(iters)
Exemple #54
0
def difference_family(v, k, l=1, existence=False, explain_construction=False, check=True):
    r"""
    Return a (``k``, ``l``)-difference family on an Abelian group of cardinality ``v``.

    Let `G` be a finite Abelian group. For a given subset `D` of `G`, we define
    `\Delta D` to be the multi-set of differences `\Delta D = \{x - y; x \in D,
    y \in D, x \not= y\}`. A `(G,k,\lambda)`-*difference family* is a collection
    of `k`-subsets of `G`, `D = \{D_1, D_2, \ldots, D_b\}` such that the union
    of the difference sets `\Delta D_i` for `i=1,...b`, seen as a multi-set,
    contains each element of `G \backslash \{0\}` exactly `\lambda`-times.

    When there is only one block, i.e. `\lambda(v - 1) = k(k-1)`, then a
    `(G,k,\lambda)`-difference family is also called a *difference set*.

    See also :wikipedia:`Difference_set`.

    If there is no such difference family, an ``EmptySetError`` is raised and if
    there is no construction at the moment ``NotImplementedError`` is raised.

    INPUT:

    - ``v,k,l`` -- parameters of the difference family. If ``l`` is not provided
      it is assumed to be ``1``.

    - ``existence`` -- if ``True``, then return either ``True`` if Sage knows
      how to build such design, ``Unknown`` if it does not and ``False`` if it
      knows that the design does not exist..

    - ``explain_construction`` -- instead of returning a difference family,
      returns a string that explains the construction used.

    - ``check`` -- boolean (default: ``True``). If ``True`` then the result of
      the computation is checked before being returned. This should not be
      needed but ensures that the output is correct.

    OUTPUT:

    A pair ``(G,D)`` made of a group `G` and a difference family `D` on that
    group. Or, if ``existence`` is ``True`` a troolean or if
    ``explain_construction`` is ``True`` a string.

    EXAMPLES::

        sage: G,D = designs.difference_family(73,4)
        sage: G
        Finite Field of size 73
        sage: D
        [[0, 1, 8, 64],
         [0, 2, 16, 55],
         [0, 3, 24, 46],
         [0, 25, 54, 67],
         [0, 35, 50, 61],
         [0, 36, 41, 69]]
        sage: print designs.difference_family(73, 4, explain_construction=True)
        Radical difference family on a finite field

        sage: G,D = designs.difference_family(15,7,3)
        sage: G
        The cartesian product of (Finite Field of size 3, Finite Field of size 5)
        sage: D
        [[(1, 1), (1, 4), (2, 2), (2, 3), (0, 0), (1, 0), (2, 0)]]
        sage: print designs.difference_family(15,7,3,explain_construction=True)
        Twin prime powers difference family

        sage: print designs.difference_family(91,10,1,explain_construction=True)
        Singer difference set

    For `k=6,7` we look at the set of small prime powers for which a
    construction is available::

        sage: def prime_power_mod(r,m):
        ....:     k = m+r
        ....:     while True:
        ....:         if is_prime_power(k):
        ....:             yield k
        ....:         k += m

        sage: from itertools import islice
        sage: l6 = {True:[], False: [], Unknown: []}
        sage: for q in islice(prime_power_mod(1,30), 60):
        ....:     l6[designs.difference_family(q,6,existence=True)].append(q)
        sage: l6[True]
        [31, 121, 151, 181, 211, ...,  3061, 3121, 3181]
        sage: l6[Unknown]
        [61]
        sage: l6[False]
        []

        sage: l7 = {True: [], False: [], Unknown: []}
        sage: for q in islice(prime_power_mod(1,42), 60):
        ....:     l7[designs.difference_family(q,7,existence=True)].append(q)
        sage: l7[True]
        [337, 421, 463, 883, 1723, 3067, 3319, 3529, 3823, 3907, 4621, 4957, 5167]
        sage: l7[Unknown]
        [43, 127, 169, 211, ..., 4999, 5041, 5209]
        sage: l7[False]
        []

    List available constructions::

        sage: for v in xrange(2,100):
        ....:     constructions = []
        ....:     for k in xrange(2,10):
        ....:         for l in xrange(1,10):
        ....:             if designs.difference_family(v,k,l,existence=True):
        ....:                 constructions.append((k,l))
        ....:                 _ = designs.difference_family(v,k,l)
        ....:     if constructions:
        ....:         print "%2d: %s"%(v, ', '.join('(%d,%d)'%(k,l) for k,l in constructions))
         3: (2,1)
         4: (3,2)
         5: (2,1), (4,3)
         6: (5,4)
         7: (2,1), (3,1), (3,2), (4,2), (6,5)
         8: (7,6)
         9: (2,1), (4,3), (8,7)
        10: (9,8)
        11: (2,1), (4,6), (5,2), (5,4), (6,3)
        13: (2,1), (3,1), (3,2), (4,1), (4,3), (5,5), (6,5)
        15: (3,1), (4,6), (5,6), (7,3)
        16: (3,2), (5,4), (6,2)
        17: (2,1), (4,3), (5,5), (8,7)
        19: (2,1), (3,1), (3,2), (4,2), (6,5), (9,4), (9,8)
        21: (3,1), (4,3), (5,1), (6,3), (6,5)
        22: (4,2), (6,5), (7,4), (8,8)
        23: (2,1)
        25: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (7,7), (8,7)
        27: (2,1), (3,1)
        28: (3,2), (6,5)
        29: (2,1), (4,3), (7,3), (7,6), (8,4), (8,6)
        31: (2,1), (3,1), (3,2), (4,2), (5,2), (5,4), (6,1), (6,5)
        33: (3,1), (5,5), (6,5)
        34: (4,2)
        35: (5,2)
        37: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (9,2), (9,8)
        39: (3,1), (6,5)
        40: (3,2), (4,1)
        41: (2,1), (4,3), (5,1), (5,4), (6,3), (8,7)
        43: (2,1), (3,1), (3,2), (4,2), (6,5), (7,2), (7,3), (7,6), (8,4)
        45: (3,1), (5,1)
        46: (4,2), (6,2)
        47: (2,1)
        49: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (8,7), (9,3)
        51: (3,1), (5,2), (6,3)
        52: (4,1)
        53: (2,1), (4,3)
        55: (3,1), (9,4)
        57: (3,1), (7,3), (8,1)
        59: (2,1)
        61: (2,1), (3,1), (3,2), (4,3), (5,1), (5,4), (6,2), (6,3), (6,5)
        63: (3,1)
        64: (3,2), (4,1), (7,2), (7,6), (9,8)
        65: (5,1)
        67: (2,1), (3,1), (3,2), (6,5)
        69: (3,1)
        71: (2,1), (5,2), (5,4), (7,3), (7,6), (8,4)
        73: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (8,7), (9,1), (9,8)
        75: (3,1), (5,2)
        76: (4,1)
        79: (2,1), (3,1), (3,2), (6,5)
        81: (2,1), (3,1), (4,3), (5,1), (5,4), (8,7)
        83: (2,1)
        85: (4,1), (7,2), (7,3), (8,2)
        89: (2,1), (4,3), (8,7)
        91: (6,1)
        97: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (8,7), (9,3)

    TESTS:

    Check more of the Wilson constructions from [Wi72]_::

        sage: Q5 = [241, 281,421,601,641, 661, 701, 821,881]
        sage: Q9 = [73, 1153, 1873, 2017]
        sage: Q15 = [76231]
        sage: Q4 = [13, 73, 97, 109, 181, 229, 241, 277, 337, 409, 421, 457]
        sage: Q8 = [1009, 3137, 3697]
        sage: for Q,k in [(Q4,4),(Q5,5),(Q8,8),(Q9,9),(Q15,15)]:
        ....:     for q in Q:
        ....:         assert designs.difference_family(q,k,1,existence=True) is True
        ....:         _ = designs.difference_family(q,k,1)

    Check Singer difference sets::

        sage: sgp = lambda q,d: ((q**(d+1)-1)//(q-1), (q**d-1)//(q-1), (q**(d-1)-1)//(q-1))

        sage: for q in range(2,10):
        ....:     if is_prime_power(q):
        ....:         for d in [2,3,4]:
        ....:           v,k,l = sgp(q,d)
        ....:           assert designs.difference_family(v,k,l,existence=True) is True
        ....:           _ = designs.difference_family(v,k,l)

    Check twin primes difference sets::

        sage: for p in [3,5,7,9,11]:
        ....:     v = p*(p+2); k = (v-1)/2;  lmbda = (k-1)/2
        ....:     G,D = designs.difference_family(v,k,lmbda)

    Check the database:

        sage: from sage.combinat.designs.database import DF
        sage: for v,k,l in DF:
        ....:     df = designs.difference_family(v,k,l,check=True)

    Check a failing construction (:trac:`17528`):

        sage: designs.difference_family(9,3)
        Traceback (most recent call last):
        ...
        NotImplementedError: No construction available for (9,3,1)-difference family

    .. TODO::

        Implement recursive constructions from Buratti "Recursive for difference
        matrices and relative difference families" (1998) and Jungnickel
        "Composition theorems for difference families and regular planes" (1978)
    """
    from block_design import are_hyperplanes_in_projective_geometry_parameters

    from database import DF

    if (v,k,l) in DF:
        if existence:
            return True
        elif explain_construction:
            return "The database contains a ({},{},{})-difference family".format(v,k,l)

        vv, blocks = next(DF[v,k,l].iteritems())

        # Build the group
        from sage.rings.finite_rings.integer_mod_ring import Zmod
        if len(vv) == 1:
            G = Zmod(vv[0])
        else:
            from sage.categories.cartesian_product import cartesian_product
            G = cartesian_product([Zmod(i) for i in vv])

        df = [[G(i) for i in b] for b in blocks]

        if check and not is_difference_family(G, df, v=v, k=k, l=l):
            raise RuntimeError("There is an invalid ({},{},{})-difference "
                    "family in the database... Please contact "
                    "*****@*****.**".format(v,k,l))

        return G,df

    e = k*(k-1)
    if (l*(v-1)) % e:
        if existence:
            return Unknown
        raise NotImplementedError("No construction available for ({},{},{})-difference family".format(v,k,l))
    t = l*(v-1) // e  # number of blocks

    # trivial construction
    if k == (v-1) and l == (v-2):
        from sage.rings.finite_rings.integer_mod_ring import Zmod
        G = Zmod(v)
        return G, [range(1,v)]

    factorization = arith.factor(v)
    D = None

    if len(factorization) == 1:  # i.e. is v a prime power
        from sage.rings.finite_rings.constructor import GF
        G = K = GF(v,'z')

        if radical_difference_family(K, k, l, existence=True):
            if existence:
                return True
            elif explain_construction:
                return "Radical difference family on a finite field"
            else:
                D = radical_difference_family(K,k,l)

        elif l == 1 and k == 6 and df_q_6_1(K,existence=True):
            if existence:
                return True
            elif explain_construction:
                return "Wilson 1972 difference family made from the union of two cyclotomic cosets"
            else:
                D = df_q_6_1(K)

    # Twin prime powers construction
    # i.e. v = p(p+2) where p and p+2 are prime powers
    #      k = (v-1)/2
    #      lambda = (k-1)/2 (ie 2l+1 = k)
    elif (k == (v-1)//2 and
          l == (k-1)//2 and
          len(factorization) == 2 and
          abs(pow(*factorization[0]) - pow(*factorization[1])) == 2):
        if existence:
            return True
        elif explain_construction:
            return "Twin prime powers difference family"
        else:
            p = pow(*factorization[0])
            q = pow(*factorization[1])
            if p > q:
                p,q = q,p
            G,D = twin_prime_powers_difference_set(p,check=False)

    if D is None and are_hyperplanes_in_projective_geometry_parameters(v,k,l):
        _, (q,d) = are_hyperplanes_in_projective_geometry_parameters(v,k,l,True)
        if existence:
            return True
        elif explain_construction:
            return "Singer difference set"
        else:
            G,D = singer_difference_set(q,d)

    if D is None:
        if existence:
            return Unknown
        raise NotImplementedError("No constructions for these parameters")

    if check and not is_difference_family(G,D,v=v,k=k,l=l,verbose=False):
        raise RuntimeError("There is a problem. Sage built the following "
                "difference family on G='{}' with parameters ({},{},{}):\n "
                "{}\nwhich seems to not be a difference family... "
                "Please contact [email protected]".format(G,v,k,l,D))

    return G, D