De Bruijn sequences - Combinatorics

Skip to content
Back to top
View this page
Edit this page

# De Bruijn sequences

A De Bruijn sequence is defined as the shortest cyclic sequence that incorporates all substrings of a certain length of an alphabet.

For instance, the \(2^3=8\) binary strings of length 3 are all included in the following string:

Sage

    sage: DeBruijnSequences(2,3).an_element()
    [0, 0, 0, 1, 0, 1, 1, 1]

Python

    >>> from sage.all import *
    >>> DeBruijnSequences(Integer(2),Integer(3)).an_element()
    [0, 0, 0, 1, 0, 1, 1, 1]

They can be obtained as a subsequence of the cyclic De Bruijn sequence of parameters \(k=2\) and \(n=3\):

Sage

    sage: seq = DeBruijnSequences(2,3).an_element()
    sage: print(Word(seq).string_rep())
    00010111
    sage: shift = lambda i: [(i+j)%2**3 for j in range(3)]
    sage: for i in range(2**3):
    ....:    w = Word([b if j in shift(i) else '*' for j, b in enumerate(seq)])
    ....:    print(w.string_rep())
    000*****
    *001****
    **010***
    ***101**
    ****011*
    *****111
    0*****11
    00*****1

[Python]

    >>> from sage.all import *
    >>> seq = DeBruijnSequences(Integer(2),Integer(3)).an_element()
    >>> print(Word(seq).string_rep())
    00010111
    >>> shift = lambda i: [(i+j)%Integer(2)**Integer(3) for j in range(Integer(3))]
    >>> for i in range(Integer(2)**Integer(3)):
    ...    w = Word([b if j in shift(i) else '*' for j, b in enumerate(seq)])
    ...    print(w.string_rep())
    000*****
    *001****
    **010***
    ***101**
    ****011*
    *****111
    0*****11
    00*****1

This sequence is of length \(k^n\), which is best possible as it is the number of \(k\)-ary strings of length \(n\). One can equivalently define a De Bruijn sequence of parameters \(k\) and \(n\) as a cyclic sequence of length \(k^n\) in which all substring of length \(n\) are different.

See also Wikipedia article De_Bruijn_sequence.

AUTHOR:

- Eviatar Bach (2011): initial version

- Nathann Cohen (2011): Some work on the documentation and defined the `__contain__` method

class sage.combinat.debruijn_sequence.DeBruijnSequences(k, n)

  Bases: `UniqueRepresentation`, `Parent`

  Represent the De Bruijn sequences of given parameters \(k\) and \(n\).

  A De Bruijn sequence of parameters \(k\) and \(n\) is defined as the shortest cyclic sequence that incorporates all substrings of length \(n\) a \(k\)-ary alphabet.

  This class can be used to generate the lexicographically smallest De Bruijn sequence, to count the number of existing De Bruijn sequences or to test whether a given sequence is De Bruijn.

  INPUT:

  - `k` – a natural number to define arity; the letters used are the integers \(0, \ldots, k-1\)

  - `n` – a natural number that defines the length of the substring

  EXAMPLES:

  Obtaining a De Bruijn sequence:

  Sage

      sage: seq = DeBruijnSequences(2, 3).an_element()
      sage: seq
      [0, 0, 0, 1, 0, 1, 1, 1]

  Python

      >>> from sage.all import *
      >>> seq = DeBruijnSequences(Integer(2), Integer(3)).an_element()
      >>> seq
      [0, 0, 0, 1, 0, 1, 1, 1]

  Testing whether it is indeed one:

  Sage

      sage: seq in DeBruijnSequences(2, 3)
      True

  [Python]

      >>> from sage.all import *
      >>> seq in DeBruijnSequences(Integer(2), Integer(3))
      True

  The total number for these parameters:

  Sage

      sage: DeBruijnSequences(2, 3).cardinality()
      2

  Python

      >>> from sage.all import *
      >>> DeBruijnSequences(Integer(2), Integer(3)).cardinality()
      2

  Note

  This function only generates one De Bruijn sequence (the smallest lexicographically). Support for generating all possible ones may be added in the future.

  cardinality()

    Return the number of distinct De Bruijn sequences for the object’s parameters.

    EXAMPLES:

    Sage

        sage: DeBruijnSequences(2, 5).cardinality()
        2048

    Python

        >>> from sage.all import *
        >>> DeBruijnSequences(Integer(2), Integer(5)).cardinality()
        2048

    ALGORITHM:

    The formula for cardinality is \(k!^{k^{n-1}}/k^n\) [Ros2002].

sage.combinat.debruijn_sequence.debruijn_sequence(k, n)

  The generating function for De Bruijn sequences. This avoids the object creation, so is significantly faster than accessing from DeBruijnSequence. For more information, see the documentation there. The algorithm used is from Frank Ruskey’s “Combinatorial Generation”.

  INPUT:

  - `k` – arity; must be an integer

  - `n` – substring length; must be an integer

  EXAMPLES:

  Sage

      sage: from sage.combinat.debruijn_sequence import debruijn_sequence
      sage: debruijn_sequence(3, 1)
      [0, 1, 2]

  Python

      >>> from sage.all import *
      >>> from sage.combinat.debruijn_sequence import debruijn_sequence
      >>> debruijn_sequence(Integer(3), Integer(1))
      [0, 1, 2]

sage.combinat.debruijn_sequence.is_debruijn_sequence(seq, k, n)

  Given a sequence of integer elements in \(0, \ldots, k-1\), tests whether it corresponds to a De Bruijn sequence of parameters \(k\) and \(n\).

  INPUT:

  - `seq` – sequence of elements in \(0, \ldots, k-1\)

  - `n`, `k` – integers

  EXAMPLES:

  Sage

      sage: from sage.combinat.debruijn_sequence import is_debruijn_sequence
      sage: s = DeBruijnSequences(2, 3).an_element()
      sage: is_debruijn_sequence(s, 2, 3)
      True
      sage: is_debruijn_sequence(s + [0], 2, 3)
      False
      sage: is_debruijn_sequence([1] + s[1:], 2, 3)
      False

  Python

      >>> from sage.all import *
      >>> from sage.combinat.debruijn_sequence import is_debruijn_sequence
      >>> s = DeBruijnSequences(Integer(2), Integer(3)).an_element()
      >>> is_debruijn_sequence(s, Integer(2), Integer(3))
      True
      >>> is_debruijn_sequence(s + [Integer(0)], Integer(2), Integer(3))
      False
      >>> is_debruijn_sequence([Integer(1)] + s[Integer(1):], Integer(2), Integer(3))
      False