Example #1
0
    def node_to_word(self, state=0):
        r"""
        Returns the word obtained by reading the edge labels from 0 to
        ``state``.

        INPUT:

        - ``state`` - (default: 0) a state

        EXAMPLES::

            sage: from sage.combinat.words.suffix_trees import SuffixTrie
            sage: w = Words("abc")("abcba")
            sage: t = SuffixTrie(w)
            sage: t.node_to_word(10)
            word: abcba
            sage: t.node_to_word(7)
            word: abcb
        """
        if state == 0:
            return Words(self._alphabet)()
        # We first invert the transition function
        tf_inv = {b: a for a, b in iteritems(self._transition_function)}

        # Starting from the active state,
        # read labels along the unique path to the root.
        (u, letter) = tf_inv[state]
        w = letter
        s = u
        while s != 0:
            (u, letter) = tf_inv[s]
            w = letter * w
            s = u
        return w
Example #2
0
    def process_letter(self, letter):
        r"""
        Modify ``self`` to produce the suffix trie for ``self.word() +
        letter``.

        .. note::

           ``letter`` must occur within the alphabet of the word.

        EXAMPLES::

            sage: from sage.combinat.words.suffix_trees import SuffixTrie
            sage: w = Words("ab")("ababba")
            sage: t = SuffixTrie(w); t
            Suffix Trie of the word: ababba
            sage: t.process_letter("a"); t
            Suffix Trie of the word: ababbaa

        TESTS::

            sage: from sage.combinat.words.suffix_trees import SuffixTrie
            sage: w = Words("cao")("cacao")
            sage: t = SuffixTrie(w); t
            Suffix Trie of the word: cacao
            sage: t.process_letter("d")
            Traceback (most recent call last):
            ...
            ValueError: d not in alphabet!
        """
        # Make certain that letter is a word containing one letter.
        letter = Words(self._alphabet)([letter])
        self._process_letter(letter)
Example #3
0
    def __init__(self, R, names):
        r"""
        Initialize ``self``.

        EXAMPLES::

            sage: F = ShuffleAlgebra(QQ, 'xyz'); F
            Shuffle Algebra on 3 generators ['x', 'y', 'z'] over Rational Field
            sage: TestSuite(F).run()

        TESTS::

            sage: ShuffleAlgebra(24, 'toto')
            Traceback (most recent call last):
            ...
            TypeError: argument R must be a ring
        """
        if R not in Rings():
            raise TypeError("argument R must be a ring")
        self._alphabet = names
        self.__ngens = self._alphabet.cardinality()
        CombinatorialFreeModule.__init__(self,
                                         R,
                                         Words(names, infinite=False),
                                         latex_prefix="",
                                         category=(AlgebrasWithBasis(R),
                                                   CommutativeAlgebras(R),
                                                   CoalgebrasWithBasis(R)))
Example #4
0
    def from_finite_word(self, w):
        r"""
        Return the unique ordered set partition of `\{1, 2, \ldots, n\}` corresponding
        to a word `w` of length `n`.

        .. SEEALSO::

            :meth:`Word.to_ordered_set_partition`

        EXAMPLES::

            sage: A = OrderedSetPartitions().from_finite_word('abcabcabd'); A
            [{1, 4, 7}, {2, 5, 8}, {3, 6}, {9}]
            sage: B = OrderedSetPartitions().from_finite_word([1,2,3,1,2,3,1,2,4])
            sage: A == B
            True
        """
        # TODO: fix this if statement.
        #       In fact, what we need is for the underlying alphabet to be sortable.
        if isinstance(w, (list, tuple, str, FiniteWord_class)):
            return self.element_class(self,
                                      Words()(w).to_ordered_set_partition())
        else:
            raise ValueError(
                "Something is wrong: `from_finite_word` expects an object of type list/tuple/str/Word representing a finite word, received {}."
                .format(str(w)))
Example #5
0
    def to_word_by_row(self):
        """
        Returns a word obtained from a row reading of the skew tableau.

        EXAMPLES::

            sage: s = SkewTableau([[None,1],[2,3]])
            sage: s.pp()
              .  1
              2  3
            sage: s.to_word_by_row()
            word: 231
            sage: s = SkewTableau([[None, 2, 4], [None, 3], [1]])
            sage: s.pp()
              .  2  4
              .  3
              1
            sage: s.to_word_by_row()
            word: 1324
        """
        word = []
        for row in self:
            word = row + word

        return Words("positive integers")([i for i in word if i is not None])
Example #6
0
def _gen_names(elts):
    r"""
    Used to find a name for a generator when rings are created using the
    ``__getitem__`` syntax, e.g. ``ZZ['x']``, ``ZZ[sqrt(2)]``.

    EXAMPLES::

        sage: from sage.categories.rings import _gen_names
        sage: list(_gen_names([sqrt(5)]))
        ['sqrt5']
        sage: list(_gen_names([sqrt(-17), 2^(1/3)]))
        ['a', 'b']
        sage: list(_gen_names((1..27)))[-1]
        'aa'
    """
    import re
    from sage.structure.category_object import certify_names
    from sage.combinat.words.words import Words
    it = iter(Words("abcdefghijklmnopqrstuvwxyz", infinite=False))
    next(it) # skip empty word
    for x in elts:
        name = str(x)
        m = re.match(r'^sqrt\((\d+)\)$', name)
        if m:
            name = "sqrt%s" % m.groups()[0]
        try:
            certify_names([name])
        except ValueError:
            name = next(it).string_rep()
        yield name
def _gen_names(elts):
    r"""
    Used to find a name for a generator when rings are created using the
    ``__getitem__`` syntax, e.g. ``ZZ['x']``, ``ZZ[sqrt(2)]``.

    EXAMPLES::

        sage: from sage.categories.rings import _gen_names
        sage: list(_gen_names([sqrt(5)]))
        ['sqrt5']
        sage: list(_gen_names([sqrt(-17), 2^(1/3)]))
        ['a', 'b']
        sage: list(_gen_names((1..27)))[-1]
        'aa'
    """
    from sage.symbolic.ring import is_SymbolicVariable
    from sage.combinat.words.words import Words
    it = iter(Words("abcdefghijklmnopqrstuvwxyz"))
    it.next()  # skip empty word
    for x in elts:
        name = str(x)
        m = re.match('^sqrt\((\d+)\)$', name)
        if m:
            name = "sqrt%s" % m.groups()[0]
        try:
            _certify_names([name])
        except ValueError as msg:
            name = it.next().string_rep()
        yield name
Example #8
0
    def __init__(self, R, n, names):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: Z.<x,y,z> = algebras.FreeZinbiel(QQ)
            sage: TestSuite(Z).run()

        TESTS::

            sage: Z.<x,y,z> = algebras.FreeZinbiel(5)
            Traceback (most recent call last):
            ...
            TypeError: argument R must be a ring
        """
        if R not in Rings:
            raise TypeError("argument R must be a ring")
        indices = Words(Alphabet(n, names=names))
        cat = MagmaticAlgebras(R).WithBasis().Graded()
        self._n = n
        CombinatorialFreeModule.__init__(self,
                                         R,
                                         indices,
                                         prefix='Z',
                                         category=cat)
        self._assign_names(names)
Example #9
0
    def __init__(self, R, names, prefix):
        r"""
        Initialize ``self``.

        EXAMPLES::

            sage: F = ShuffleAlgebra(QQ, 'xyz'); F
            Shuffle Algebra on 3 generators ['x', 'y', 'z'] over Rational Field
            sage: TestSuite(F).run()  # long time

        TESTS::

            sage: ShuffleAlgebra(24, 'toto')
            Traceback (most recent call last):
            ...
            TypeError: argument R must be a ring

            sage: F = ShuffleAlgebra(QQ, 'xyz', prefix='f'); F
            Shuffle Algebra on 3 generators ['x', 'y', 'z'] over Rational Field
            sage: F.gens()
            Family (f[word: x], f[word: y], f[word: z])
        """
        if R not in Rings():
            raise TypeError("argument R must be a ring")
        self._alphabet = names
        self.__ngens = self._alphabet.cardinality()
        cat = GradedHopfAlgebrasWithBasis(R).Commutative().Connected()
        CombinatorialFreeModule.__init__(self,
                                         R,
                                         Words(names, infinite=False),
                                         latex_prefix="",
                                         prefix=prefix,
                                         category=cat)
Example #10
0
    def words_of_length_iterator(self, length):
        r"""
        Return an iterator over words of given length.

        INPUT:

        - ``length`` -- integer

        EXAMPLES::

            sage: from slabbe.language import Language
            sage: F = Language(alphabet=['a', 'b'])
            sage: it = F.words_of_length_iterator(2)
            sage: list(it)
            [word: aa, word: ab, word: ba, word: bb]
        """
        W = Words(self._alphabet)
        return W.iterate_by_length(length)
Example #11
0
    def words_of_length_iterator(self, length):
        r"""
        Return an iterator over words of given length.

        INPUT:

        - ``length`` -- integer

        EXAMPLES::

            sage: from slabbe.language import Language
            sage: F = Language(alphabet=['a', 'b'])
            sage: it = F.words_of_length_iterator(2)
            sage: list(it)
            [word: aa, word: ab, word: ba, word: bb]
        """
        W = Words(self._alphabet)
        return W.iterate_by_length(length)
    def __init__(self, R, alphabet = ("a", "b", "c")):
        """
        EXAMPLES::

            sage: A = AlgebrasWithBasis(QQ).example(); A
            An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field
            sage: TestSuite(A).run()

        """
        self._alphabet = alphabet
        CombinatorialFreeModule.__init__(self, R, Words(alphabet), category = AlgebrasWithBasis(R))
Example #13
0
    def algebra_generators(self):
        r"""
        Return the generators of this algebra.

        EXAMPLES::

            sage: A = ShuffleAlgebra(ZZ,'fgh'); A
            Shuffle Algebra on 3 generators ['f', 'g', 'h'] over Integer Ring
            sage: A.algebra_generators()
            Family (B[word: f], B[word: g], B[word: h])
        """
        Words = self.basis().keys()
        return Family([self.monomial(Words(a)) for a in self._alphabet])
Example #14
0
    def __init__(self, R, n, names, prefix):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: Z.<x,y,z> = algebras.FreeZinbiel(QQ)
            sage: TestSuite(Z).run()

            sage: Z = algebras.FreeZinbiel(QQ, ZZ)
            sage: G = Z.algebra_generators()
            sage: TestSuite(Z).run(elements=[Z.an_element(), G[1], G[1]*G[2]*G[0]])

        TESTS::

            sage: Z.<x,y,z> = algebras.FreeZinbiel(5)
            Traceback (most recent call last):
            ...
            TypeError: argument R must be a ring

            sage: algebras.FreeZinbiel(QQ, ['x', 'y'], prefix='f')
            Free Zinbiel algebra on generators (f[x], f[y]) over Rational Field
        """
        if R not in Rings():
            raise TypeError("argument R must be a ring")
        if names is None:
            indices = Words(Alphabet(n), infinite=False)
            self._n = None
        else:
            indices = Words(Alphabet(n, names=names), infinite=False)
            self._n = n
        cat = MagmaticAlgebras(R).WithBasis().Graded()
        CombinatorialFreeModule.__init__(self,
                                         R,
                                         indices,
                                         prefix=prefix,
                                         category=cat)
        if self._n is not None:
            self._assign_names(names)
    def algebra_generators(self):
        r"""
        Returns the generators of this algebra, as per :meth:`Algebras.ParentMethods.algebra_generators`.

        EXAMPLES::

            sage: A = AlgebrasWithBasis(QQ).example(); A
            An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field
            sage: A.algebra_generators()
            Family (B[word: a], B[word: b], B[word: c])
        """
        Words = self.basis().keys()
        return Family( [self.monomial(Words(a)) for a in self._alphabet] )
Example #16
0
    def __init__(self, R, names):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: D = ShuffleAlgebra(QQ, 'ab').dual_pbw_basis()
            sage: TestSuite(D).run()
        """
        self._alphabet = names
        self._alg = ShuffleAlgebra(R, names)
        CombinatorialFreeModule.__init__(self, R, Words(names), prefix='S',
            category=(AlgebrasWithBasis(R), CommutativeAlgebras(R), CoalgebrasWithBasis(R)))
Example #17
0
    def __classcall_private__(cls, parts=None, from_word=None):
        """
        Create a set partition from ``parts`` with the appropriate parent.

        EXAMPLES::

            sage: s = OrderedSetPartition([[1,3],[2,4]]); s
            [{1, 3}, {2, 4}]
            sage: s.parent()
            Ordered set partitions of {1, 2, 3, 4}
            sage: t = OrderedSetPartition([[2,4],[1,3]]); t
            [{2, 4}, {1, 3}]
            sage: s != t
            True
            sage: OrderedSetPartition()
            []
            sage: OrderedSetPartition([])
            []
            sage: OrderedSetPartition('')
            []
            sage: OrderedSetPartition('bdab') == OrderedSetPartition(from_word='bdab')
            True
            sage: OrderedSetPartition('bdab') == OrderedSetPartition(Word('bdab'))
            True
        """
        if parts is None and from_word is None:
            P = OrderedSetPartitions([])
            return P.element_class(P, [])
        if from_word:
            return OrderedSetPartitions().from_finite_word(Words()(from_word))
        # if `parts` looks like a sequence of "letters" then treat it like a word.
        if parts in Words() or (len(parts) > 0 and
                                (parts[0] in ZZ or isinstance(parts[0], str))):
            return OrderedSetPartitions().from_finite_word(Words()(parts))
        else:
            P = OrderedSetPartitions(
                reduce(lambda x, y: x.union(y), map(Set, parts), Set([])))
            return P.element_class(P, parts)
Example #18
0
    def __init__(self, R, names):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: D = ShuffleAlgebra(QQ, 'ab').dual_pbw_basis()
            sage: TestSuite(D).run()  # long time
        """
        self._alphabet = names
        self._alg = ShuffleAlgebra(R, names)
        cat = GradedHopfAlgebrasWithBasis(R).Commutative().Connected()
        CombinatorialFreeModule.__init__(self, R, Words(names), prefix='S',
                                         category=cat)
Example #19
0
    def to_word_by_row(self):
        """
        Returns a word obtained from a row reading of the ribbon.

        EXAMPLES::

            sage: Ribbon([[1],[2,3]]).to_word_by_row()
            word: 231
            sage: Ribbon([[2, 4], [3], [1]]).to_word_by_row()
            word: 1324
        """
        word = []
        for row in self:
            word = row + word
        return Words(alphabet="positive integers")(word)
    def __init__(self, w=ZZ_1, r=ZZ_2, h1=ZZ_1, h2=ZZ_1):
        from sage.combinat.words.words import Words

        field = Sequence([w, r, h1, h2]).universe()
        if not field.is_field():
            field = field.fraction_field()
        self._w = field(w)
        self._r = field(r)
        self._h1 = field(h1)
        self._h2 = field(h2)
        self._words = Words('LR', finite=True, infinite=False)
        self._wL = self._words('L')
        self._wR = self._words('R')

        base_label = self.polygon_labels()._cartesian_product_of_elements(
            (self._words(''), 0))

        Surface.__init__(self, field, base_label, finite=False)
Example #21
0
    def to_packed_word(self):
        r"""
        Return the packed word on alphabet `\{1,2,3,\ldots\}`
        corresponding to ``self``.

        A *packed word* on alphabet `\{1,2,3,\ldots\}` is any word whose
        maximum letter is the same as its total number of distinct letters.
        Let `P` be an ordered set partition of a set `X`.
        The corresponding packed word `w_1 w_2 \cdots w_n` is constructed
        by having letter `w_i = j` if the `i`-th smallest entry in `X`
        occurs in the `j`-th block of `P`.

        .. SEEALSO::

            :meth:`Word.to_ordered_set_partition`

        .. WARNING::

            This assumes there is a total order on the underlying
            set (``self._base_set``).

        EXAMPLES::

            sage: S = OrderedSetPartitions()
            sage: x = S([[3,5], [2], [1,4,6]])
            sage: x.to_packed_word()
            word: 321313
            sage: x = S([['a', 'c', 'e'], ['b', 'd']])
            sage: x.to_packed_word()
            word: 12121
        """
        X = sorted(self._base_set)
        out = {}
        for i in range(len(self)):
            for letter in self[i]:
                out[letter] = i
        return Words()([out[letter] + 1 for letter in X])
Example #22
0
    def __init__(self, parent=None):
        r"""
        Constructor. See documentation of WordDatatype_Kolakoski for more
        details.

        EXAMPLES::

            sage: from slabbe import KolakoskiWord
            sage: K = KolakoskiWord()
            sage: K
            word: 1221121221221121122121121221121121221221...

        TESTS:

        Pickle is supported::

            sage: K = KolakoskiWord()
            sage: loads(dumps(K))
            word: 1221121221221121122121121221121121221221...
        """
        if parent is None:
            from sage.combinat.words.words import Words
            parent = Words([1, 2])
        WordDatatype_Kolakoski.__init__(self, parent)
Example #23
0
    def Kautz(self, k, D, vertices = 'strings'):
        r"""
        Returns the Kautz digraph of degree `d` and diameter `D`.

        The Kautz digraph has been defined in [Kautz68]_. The Kautz digraph of
        degree `d` and diameter `D` has `d^{D-1}(d+1)` vertices. This digraph is
        build upon a set of vertices equal to the set of words of length `D`
        from an alphabet of `d+1` letters such that consecutive letters are
        differents. There is an arc from vertex `u` to vertex `v` if `v` can be
        obtained from `u` by removing the leftmost letter and adding a new
        letter, distinct from the rightmost letter of `u`, at the right end.

        The Kautz digraph of degree `d` and diameter `D` is isomorphic to the
        digraph of Imase and Itoh [II83]_ of degree `d` and order
        `d^{D-1}(d+1)`.

        See also the
        :wikipedia:`Wikipedia article on Kautz Graphs <Kautz_graph>`.

        INPUTS:

        - ``k`` -- Two possibilities for this parameter :
            - An integer equal to the degree of the digraph to be produced, that
              is the cardinality minus one of the alphabet to use.
            - An iterable object to be used as the set of letters. The degree of
              the resulting digraph is the cardinality of the set of letters
              minus one.

        - ``D`` -- An integer equal to the diameter of the digraph, and also to
              the length of a vertex label when ``vertices == 'strings'``.

        - ``vertices`` -- 'strings' (default) or 'integers', specifying whether
                      the vertices are words build upon an alphabet or integers.


        EXAMPLES::

            sage: K = digraphs.Kautz(2, 3)
            sage: K.is_isomorphic(digraphs.ImaseItoh(12, 2), certify = True)
            (True,
             {'010': 0,
              '012': 1,
              '020': 3,
              '021': 2,
              '101': 11,
              '102': 10,
              '120': 9,
              '121': 8,
              '201': 5,
              '202': 4,
              '210': 6,
              '212': 7})

            sage: K = digraphs.Kautz([1,'a','B'], 2)
            sage: K.edges()
            [('1B', 'B1', '1'), ('1B', 'Ba', 'a'), ('1a', 'a1', '1'), ('1a', 'aB', 'B'), ('B1', '1B', 'B'), ('B1', '1a', 'a'), ('Ba', 'a1', '1'), ('Ba', 'aB', 'B'), ('a1', '1B', 'B'), ('a1', '1a', 'a'), ('aB', 'B1', '1'), ('aB', 'Ba', 'a')]

            sage: K = digraphs.Kautz([1,'aA','BB'], 2)
            sage: K.edges()
            [('1,BB', 'BB,1', '1'), ('1,BB', 'BB,aA', 'aA'), ('1,aA', 'aA,1', '1'), ('1,aA', 'aA,BB', 'BB'), ('BB,1', '1,BB', 'BB'), ('BB,1', '1,aA', 'aA'), ('BB,aA', 'aA,1', '1'), ('BB,aA', 'aA,BB', 'BB'), ('aA,1', '1,BB', 'BB'), ('aA,1', '1,aA', 'aA'), ('aA,BB', 'BB,1', '1'), ('aA,BB', 'BB,aA', 'aA')]


        TESTS:

        An exception is raised when the degree is less than one::

            sage: G = digraphs.Kautz(0, 2)
            Traceback (most recent call last):
            ...
            ValueError: Kautz digraphs are defined for degree at least one.

            sage: G = digraphs.Kautz(['a'], 2)
            Traceback (most recent call last):
            ...
            ValueError: Kautz digraphs are defined for degree at least one.

        An exception is raised when the diameter of the graph is less than one::

            sage: G = digraphs.Kautz(2, 0)
            Traceback (most recent call last):
            ...
            ValueError: Kautz digraphs are defined for diameter at least one.


        REFERENCE:

        .. [Kautz68] W. H. Kautz. Bounds on directed (d, k) graphs. Theory of
          cellular logic networks and machines, AFCRL-68-0668, SRI Project 7258,
          Final Rep., pp. 20-28, 1968.
        """
        if D < 1:
            raise ValueError("Kautz digraphs are defined for diameter at least one.")

        from sage.combinat.words.words import Words
        from sage.rings.integer import Integer

        my_alphabet = Words([str(i) for i in range(k+1)] if isinstance(k, Integer) else k, 1)
        if my_alphabet.size_of_alphabet() < 2:
            raise ValueError("Kautz digraphs are defined for degree at least one.")

        if vertices == 'strings':

            # We start building the set of vertices
            V = [i for i in my_alphabet]
            for i in range(D-1):
                VV = []
                for w in V:
                    VV += [w*a for a in my_alphabet if not w.has_suffix(a) ]
                V = VV

            # We now build the set of arcs
            G = DiGraph()
            for u in V:
                for a in my_alphabet:
                    if not u.has_suffix(a):
                        G.add_edge(u.string_rep(), (u[1:]*a).string_rep(), a.string_rep())

        else:
            d = my_alphabet.size_of_alphabet()-1
            G = digraphs.ImaseItoh( (d+1)*(d**(D-1)), d)

        G.name( "Kautz digraph (k=%s, D=%s)"%(k,D) )
        return G
    def Kautz(self, k, D, vertices='strings'):
        r"""
        Returns the Kautz digraph of degree `d` and diameter `D`.

        The Kautz digraph has been defined in [Kautz68]_. The Kautz digraph of
        degree `d` and diameter `D` has `d^{D-1}(d+1)` vertices. This digraph is
        build upon a set of vertices equal to the set of words of length `D`
        from an alphabet of `d+1` letters such that consecutive letters are
        differents. There is an arc from vertex `u` to vertex `v` if `v` can be
        obtained from `u` by removing the leftmost letter and adding a new
        letter, distinct from the rightmost letter of `u`, at the right end.

        The Kautz digraph of degree `d` and diameter `D` is isomorphic to the
        digraph of Imase and Itoh [II83]_ of degree `d` and order
        `d^{D-1}(d+1)`.

        See also the
        :wikipedia:`Wikipedia article on Kautz Graphs <Kautz_graph>`.

        INPUTS:

        - ``k`` -- Two possibilities for this parameter :
            - An integer equal to the degree of the digraph to be produced, that
              is the cardinality minus one of the alphabet to use.
            - An iterable object to be used as the set of letters. The degree of
              the resulting digraph is the cardinality of the set of letters
              minus one.

        - ``D`` -- An integer equal to the diameter of the digraph, and also to
              the length of a vertex label when ``vertices == 'strings'``.

        - ``vertices`` -- 'strings' (default) or 'integers', specifying whether
                      the vertices are words build upon an alphabet or integers.


        EXAMPLES::

            sage: K = digraphs.Kautz(2, 3)
            sage: K.is_isomorphic(digraphs.ImaseItoh(12, 2), certify = True)
            (True,
             {'010': 0,
              '012': 1,
              '020': 3,
              '021': 2,
              '101': 11,
              '102': 10,
              '120': 9,
              '121': 8,
              '201': 5,
              '202': 4,
              '210': 6,
              '212': 7})

            sage: K = digraphs.Kautz([1,'a','B'], 2)
            sage: K.edges()
            [('1B', 'B1', '1'), ('1B', 'Ba', 'a'), ('1a', 'a1', '1'), ('1a', 'aB', 'B'), ('B1', '1B', 'B'), ('B1', '1a', 'a'), ('Ba', 'a1', '1'), ('Ba', 'aB', 'B'), ('a1', '1B', 'B'), ('a1', '1a', 'a'), ('aB', 'B1', '1'), ('aB', 'Ba', 'a')]

            sage: K = digraphs.Kautz([1,'aA','BB'], 2)
            sage: K.edges()
            [('1,BB', 'BB,1', '1'), ('1,BB', 'BB,aA', 'aA'), ('1,aA', 'aA,1', '1'), ('1,aA', 'aA,BB', 'BB'), ('BB,1', '1,BB', 'BB'), ('BB,1', '1,aA', 'aA'), ('BB,aA', 'aA,1', '1'), ('BB,aA', 'aA,BB', 'BB'), ('aA,1', '1,BB', 'BB'), ('aA,1', '1,aA', 'aA'), ('aA,BB', 'BB,1', '1'), ('aA,BB', 'BB,aA', 'aA')]


        TESTS:

        An exception is raised when the degree is less than one::

            sage: G = digraphs.Kautz(0, 2)
            Traceback (most recent call last):
            ...
            ValueError: Kautz digraphs are defined for degree at least one.

            sage: G = digraphs.Kautz(['a'], 2)
            Traceback (most recent call last):
            ...
            ValueError: Kautz digraphs are defined for degree at least one.

        An exception is raised when the diameter of the graph is less than one::

            sage: G = digraphs.Kautz(2, 0)
            Traceback (most recent call last):
            ...
            ValueError: Kautz digraphs are defined for diameter at least one.


        REFERENCE:

        .. [Kautz68] W. H. Kautz. Bounds on directed (d, k) graphs. Theory of
          cellular logic networks and machines, AFCRL-68-0668, SRI Project 7258,
          Final Rep., pp. 20-28, 1968.
        """
        if D < 1:
            raise ValueError(
                "Kautz digraphs are defined for diameter at least one.")

        from sage.combinat.words.words import Words
        from sage.rings.integer import Integer

        my_alphabet = Words(
            [str(i) for i in range(k + 1)] if isinstance(k, Integer) else k, 1)
        if my_alphabet.size_of_alphabet() < 2:
            raise ValueError(
                "Kautz digraphs are defined for degree at least one.")

        if vertices == 'strings':

            # We start building the set of vertices
            V = [i for i in my_alphabet]
            for i in range(D - 1):
                VV = []
                for w in V:
                    VV += [w * a for a in my_alphabet if not w.has_suffix(a)]
                V = VV

            # We now build the set of arcs
            G = DiGraph()
            for u in V:
                for a in my_alphabet:
                    if not u.has_suffix(a):
                        G.add_edge(u.string_rep(), (u[1:] * a).string_rep(),
                                   a.string_rep())

        else:
            d = my_alphabet.size_of_alphabet() - 1
            G = digraphs.ImaseItoh((d + 1) * (d**(D - 1)), d)

        G.name("Kautz digraph (k=%s, D=%s)" % (k, D))
        return G
Example #25
0
    def DeBruijn(self, k, n, vertices = 'strings'):
        r"""
        Returns the De Bruijn digraph with parameters `k,n`.

        The De Bruijn digraph with parameters `k,n` is built upon a set of
        vertices equal to the set of words of length `n` from a dictionary of
        `k` letters.

        In this digraph, there is an arc `w_1w_2` if `w_2` can be obtained from
        `w_1` by removing the leftmost letter and adding a new letter at its
        right end.  For more information, see the
        :wikipedia:`Wikipedia article on De Bruijn graph <De_Bruijn_graph>`.

        INPUT:

        - ``k`` -- Two possibilities for this parameter :
              - An integer equal to the cardinality of the alphabet to use, that
                is the degree of the digraph to be produced.
              - An iterable object to be used as the set of letters. The degree
                of the resulting digraph is the cardinality of the set of
                letters.

        - ``n`` -- An integer equal to the length of words in the De Bruijn
          digraph when ``vertices == 'strings'``, and also to the diameter of
          the digraph.

        - ``vertices`` -- 'strings' (default) or 'integers', specifying whether
          the vertices are words build upon an alphabet or integers.

        EXAMPLES::

            sage: db=digraphs.DeBruijn(2,2); db
            De Bruijn digraph (k=2, n=2): Looped digraph on 4 vertices
            sage: db.order()
            4
            sage: db.size()
            8

        TESTS::

            sage: digraphs.DeBruijn(5,0)
            De Bruijn digraph (k=5, n=0): Looped multi-digraph on 1 vertex
            sage: digraphs.DeBruijn(0,0)
            De Bruijn digraph (k=0, n=0): Looped multi-digraph on 0 vertices
        """
        from sage.combinat.words.words import Words
        from sage.rings.integer import Integer

        W = Words(range(k) if isinstance(k, Integer) else k, n)
        A = Words(range(k) if isinstance(k, Integer) else k, 1)
        g = DiGraph(loops=True)

        if vertices == 'strings':
            if n == 0 :
                g.allow_multiple_edges(True)
                v = W[0]
                for a in A:
                    g.add_edge(v.string_rep(), v.string_rep(), a.string_rep())
            else:
                for w in W:
                    ww = w[1:]
                    for a in A:
                        g.add_edge(w.string_rep(), (ww*a).string_rep(), a.string_rep())
        else:
            d = W.size_of_alphabet()
            g = digraphs.GeneralizedDeBruijn(d**n, d)

        g.name( "De Bruijn digraph (k=%s, n=%s)"%(k,n) )
        return g
Example #26
0
    def DeBruijn(self,k,n):
        r"""
        Returns the De Bruijn diraph with parameters `k,n`.

        The De Bruijn digraph with parameters `k,n` is built
        upon a set of vertices equal to the set of words of
        length `n` from a dictionary of `k` letters.

        In this digraph, there is an arc `w_1w_2` if `w_2`
        can be obtained from `w_1` by removing the leftmost
        letter and adding a new letter at its right end.
        For more information, see the
        `Wikipedia article on De Bruijn graph
        <http://en.wikipedia.org/wiki/De_Bruijn_graph>`_.

        INPUT:

        - ``k`` -- Two possibilities for this parameter :
              - an integer equal to the cardinality of the
                alphabet to use.
              - An iterable object to be used as the set
                of letters
        - ``n`` -- An integer equal to the length of words in
          the De Bruijn digraph.

        EXAMPLES::

            sage: db=digraphs.DeBruijn(2,2); db
            De Bruijn digraph (k=2, n=2): Looped digraph on 4 vertices
            sage: db.order()
            4
            sage: db.size()
            8

        TESTS::

            sage: digraphs.DeBruijn(5,0)
            De Bruijn digraph (k=5, n=0): Looped multi-digraph on 1 vertex
            sage: digraphs.DeBruijn(0,0)
            De Bruijn digraph (k=0, n=0): Looped multi-digraph on 0 vertices

        """
        from sage.combinat.words.words import Words
        from sage.rings.integer import Integer

        W = Words(range(k) if isinstance(k, Integer) else k, n)
        A = Words(range(k) if isinstance(k, Integer) else k, 1)
        g = DiGraph(loops=True)

        if n == 0 :
            g.allow_multiple_edges(True)
            v = W[0]
            for a in A:
                g.add_edge(v.string_rep(), v.string_rep(), a.string_rep())
        else:
            for w in W:
                ww = w[1:]
                for a in A:
                    g.add_edge(w.string_rep(), (ww*a).string_rep(), a.string_rep())

        g.name( "De Bruijn digraph (k=%s, n=%s)"%(k,n) )
        return g
    def DeBruijn(self, k, n, vertices='strings'):
        r"""
        Returns the De Bruijn digraph with parameters `k,n`.

        The De Bruijn digraph with parameters `k,n` is built upon a set of
        vertices equal to the set of words of length `n` from a dictionary of
        `k` letters.

        In this digraph, there is an arc `w_1w_2` if `w_2` can be obtained from
        `w_1` by removing the leftmost letter and adding a new letter at its
        right end.  For more information, see the
        :wikipedia:`Wikipedia article on De Bruijn graph <De_Bruijn_graph>`.

        INPUT:

        - ``k`` -- Two possibilities for this parameter :
              - An integer equal to the cardinality of the alphabet to use, that
                is the degree of the digraph to be produced.
              - An iterable object to be used as the set of letters. The degree
                of the resulting digraph is the cardinality of the set of
                letters.

        - ``n`` -- An integer equal to the length of words in the De Bruijn
          digraph when ``vertices == 'strings'``, and also to the diameter of
          the digraph.

        - ``vertices`` -- 'strings' (default) or 'integers', specifying whether
          the vertices are words build upon an alphabet or integers.

        EXAMPLES::

            sage: db=digraphs.DeBruijn(2,2); db
            De Bruijn digraph (k=2, n=2): Looped digraph on 4 vertices
            sage: db.order()
            4
            sage: db.size()
            8

        TESTS::

            sage: digraphs.DeBruijn(5,0)
            De Bruijn digraph (k=5, n=0): Looped multi-digraph on 1 vertex
            sage: digraphs.DeBruijn(0,0)
            De Bruijn digraph (k=0, n=0): Looped multi-digraph on 0 vertices
        """
        from sage.combinat.words.words import Words
        from sage.rings.integer import Integer

        W = Words(range(k) if isinstance(k, Integer) else k, n)
        A = Words(range(k) if isinstance(k, Integer) else k, 1)
        g = DiGraph(loops=True)

        if vertices == 'strings':
            if n == 0:
                g.allow_multiple_edges(True)
                v = W[0]
                for a in A:
                    g.add_edge(v.string_rep(), v.string_rep(), a.string_rep())
            else:
                for w in W:
                    ww = w[1:]
                    for a in A:
                        g.add_edge(w.string_rep(), (ww * a).string_rep(),
                                   a.string_rep())
        else:
            d = W.size_of_alphabet()
            g = digraphs.GeneralizedDeBruijn(d**n, d)

        g.name("De Bruijn digraph (k=%s, n=%s)" % (k, n))
        return g
Example #28
0
def Subwords(w, k=None, element_constructor=None):
    """
    Return the set of subwords of ``w``.

    INPUT:

    - ``w`` -- a word (can be a list, a string, a tuple or a word)

    - ``k`` -- an optional integer to specify the length of subwords

    - ``element_constructor`` -- an optional function that will be used
      to build the subwords

    EXAMPLES::

        sage: S = Subwords(['a','b','c']); S
        Subwords of ['a', 'b', 'c']
        sage: S.first()
        []
        sage: S.last()
        ['a', 'b', 'c']
        sage: S.list()
        [[], ['a'], ['b'], ['c'], ['a', 'b'], ['a', 'c'], ['b', 'c'], ['a', 'b', 'c']]

    The same example using string, tuple or a word::

        sage: S = Subwords('abc'); S
        Subwords of 'abc'
        sage: S.list()
        ['', 'a', 'b', 'c', 'ab', 'ac', 'bc', 'abc']

        sage: S = Subwords((1,2,3)); S
        Subwords of (1, 2, 3)
        sage: S.list()
        [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]

        sage: w = Word([1,2,3])
        sage: S = Subwords(w); S
        Subwords of word: 123
        sage: S.list()
        [word: , word: 1, word: 2, word: 3, word: 12, word: 13, word: 23, word: 123]

    Using word with specified length::

        sage: S = Subwords(['a','b','c'], 2); S
        Subwords of ['a', 'b', 'c'] of length 2
        sage: S.list()
        [['a', 'b'], ['a', 'c'], ['b', 'c']]

    An example that uses the ``element_constructor`` argument::

        sage: p = Permutation([3,2,1])
        sage: Subwords(p, element_constructor=tuple).list()
        [(), (3,), (2,), (1,), (3, 2), (3, 1), (2, 1), (3, 2, 1)]
        sage: Subwords(p, 2, element_constructor=tuple).list()
        [(3, 2), (3, 1), (2, 1)]
    """
    if element_constructor is None:
        datatype = type(w)  # 'datatype' is the type of w
        if datatype is list or datatype is tuple:
            element_constructor = datatype
        elif datatype is str:
            element_constructor = _stringification
        else:
            from sage.combinat.words.words import Words
            try:
                alphabet = w.parent().alphabet()
                element_constructor = Words(alphabet)
            except AttributeError:
                element_constructor = list

    if k is None:
        return Subwords_w(w, element_constructor)
    if not isinstance(k, (int, Integer)):
        raise ValueError("k should be an integer")
    if k < 0 or k > len(w):
        return FiniteEnumeratedSet([])
    return Subwords_wk(w, k, element_constructor)