Skip to content

Commit

Permalink
Trac #21203: basic element and parent for k-regular sequences
Browse files Browse the repository at this point in the history
Implement minimal element and parent classes for working with k-regular
sequences

See also Meta ticket #21202.

URL: https://trac.sagemath.org/21203
Reported by: dkrenn
Ticket author(s): Daniel Krenn
Reviewer(s): Clemens Heuberger
  • Loading branch information
Release Manager committed May 26, 2021
2 parents 3b414be + d532b56 commit 9f3988d
Show file tree
Hide file tree
Showing 5 changed files with 418 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/doc/en/reference/combinat/module_list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ Comprehensive Module list
sage/combinat/integer_vector_weighted
sage/combinat/integer_vectors_mod_permgroup
sage/combinat/interval_posets
sage/combinat/k_regular_sequence
sage/combinat/k_tableau
sage/combinat/kazhdan_lusztig
sage/combinat/knutson_tao_puzzles
Expand Down
4 changes: 4 additions & 0 deletions src/doc/en/reference/references/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ REFERENCES:
of crystals for the quantum queer superalgebra*.
Preprint (2018). :arxiv:`1803.06317`
.. [AS2003] Jean-Paul Allouche, Jeffrey Shallit,
*Automatic Sequences: Theory, Applications, Generalizations*,
Cambridge University Press, 2003.
.. [As2008b] Sami Assaf. *Dual equivalence graphs and a
combinatorial proof of LLT and Macdonald positivity*.
(2008). :arxiv:`1005.3759v5`.
Expand Down
1 change: 1 addition & 0 deletions src/sage/combinat/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@
lazy_import('sage.combinat.binary_recurrence_sequences',
'BinaryRecurrenceSequence')
lazy_import('sage.combinat.recognizable_series', 'RecognizableSeriesSpace')
lazy_import('sage.combinat.k_regular_sequence', 'kRegularSequenceSpace')

# Six Vertex Model
lazy_import('sage.combinat.six_vertex_model', 'SixVertexModel')
Expand Down
365 changes: 365 additions & 0 deletions src/sage/combinat/k_regular_sequence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,365 @@
r"""
`k`-regular Sequences
An introduction and formal definition of `k`-regular sequences can be
found, for example, on the :wikipedia:`k-regular_sequence` or in
[AS2003]_.
.. WARNING::
As this code is experimental, warnings are thrown when a
`k`-regular sequence space is created for the first time in a
session (see :class:`sage.misc.superseded.experimental`).
TESTS::
sage: Seq2 = kRegularSequenceSpace(2, ZZ)
doctest:...: FutureWarning: This class/method/function is
marked as experimental. It, its functionality or its interface
might change without a formal deprecation.
See http://trac.sagemath.org/21202 for details.
Examples
========
Binary sum of digits
--------------------
The binary sum of digits `S(n)` of a nonnegative integer `n` satisfies
`S(2n) = S(n)` and `S(2n+1) = S(n) + 1`. We model this by the following::
sage: Seq2 = kRegularSequenceSpace(2, ZZ)
sage: S = Seq2((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [1, 1]])),
....: left=vector([0, 1]), right=vector([1, 0]))
sage: S
2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ...
sage: all(S[n] == sum(n.digits(2)) for n in srange(10))
True
Number of odd entries in Pascal's triangle
------------------------------------------
Let us consider the number of odd entries in the first `n` rows
of Pascals's triangle::
sage: @cached_function
....: def u(n):
....: if n <= 1:
....: return n
....: return 2*u(floor(n/2)) + u(ceil(n/2))
sage: tuple(u(n) for n in srange(10))
(0, 1, 3, 5, 9, 11, 15, 19, 27, 29)
There is a `2`-recursive sequence describing the numbers above as well::
sage: U = Seq2((Matrix([[3, 2], [0, 1]]), Matrix([[2, 0], [1, 3]])),
....: left=vector([0, 1]), right=vector([1, 0])).transposed()
sage: all(U[n] == u(n) for n in srange(30))
True
Various
=======
.. SEEALSO::
:mod:`recognizable series <sage.combinat.recognizable_series>`,
:mod:`sage.rings.cfinite_sequence`,
:mod:`sage.combinat.binary_recurrence_sequences`.
AUTHORS:
- Daniel Krenn (2016, 2021)
ACKNOWLEDGEMENT:
- Daniel Krenn is supported by the
Austrian Science Fund (FWF): P 24644-N26.
Classes and Methods
===================
"""
#*****************************************************************************
# Copyright (C) 2016 Daniel Krenn <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# http://www.gnu.org/licenses/
#*****************************************************************************

from .recognizable_series import RecognizableSeries
from .recognizable_series import RecognizableSeriesSpace
from sage.misc.cachefunc import cached_method


class kRegularSequence(RecognizableSeries):
def __init__(self, parent, mu, left=None, right=None):
r"""
A `k`-regular sequence.
INPUT:
- ``parent`` -- an instance of :class:`kRegularSequenceSpace`
- ``mu`` -- a family of square matrices, all of which have the
same dimension. The indices of this family are `0,...,k-1`.
``mu`` may be a list or tuple of cardinality `k`
as well. See also
:meth:`~sage.combinat.recognizable_series.RecognizableSeries.mu`.
- ``left`` -- (default: ``None``) a vector.
When evaluating the sequence, this vector is multiplied
from the left to the matrix product. If ``None``, then this
multiplication is skipped.
- ``right`` -- (default: ``None``) a vector.
When evaluating the sequence, this vector is multiplied
from the right to the matrix product. If ``None``, then this
multiplication is skipped.
EXAMPLES::
sage: Seq2 = kRegularSequenceSpace(2, ZZ)
sage: S = Seq2((Matrix([[3, 6], [0, 1]]), Matrix([[0, -6], [1, 5]])),
....: vector([0, 1]), vector([1, 0])).transposed(); S
2-regular sequence 0, 1, 3, 5, 9, 11, 15, 19, 27, 29, ...
We can access the coefficients of a sequence by
::
sage: S[5]
11
or iterating over the first, say `10`, by
::
sage: from itertools import islice
sage: list(islice(S, 10))
[0, 1, 3, 5, 9, 11, 15, 19, 27, 29]
.. SEEALSO::
:doc:`k-regular sequence <k_regular_sequence>`,
:class:`kRegularSequenceSpace`.
"""
super(kRegularSequence, self).__init__(
parent=parent, mu=mu, left=left, right=right)

def _repr_(self):
r"""
Return a representation string of this `k`-regular sequence.
OUTPUT:
A string
TESTS::
sage: Seq2 = kRegularSequenceSpace(2, ZZ)
sage: s = Seq2((Matrix([[3, 6], [0, 1]]), Matrix([[0, -6], [1, 5]])),
....: vector([0, 1]), vector([1, 0])).transposed()
sage: repr(s) # indirect doctest
'2-regular sequence 0, 1, 3, 5, 9, 11, 15, 19, 27, 29, ...'
"""
from sage.misc.lazy_list import lazy_list_formatter
return lazy_list_formatter(
self,
name='{}-regular sequence'.format(self.parent().k),
opening_delimiter='', closing_delimiter='',
preview=10)

@cached_method
def __getitem__(self, n, **kwds):
r"""
Return the `n`-th entry of this sequence.
INPUT:
- ``n`` -- a nonnegative integer
OUTPUT:
An element of the universe of the sequence
EXAMPLES::
sage: Seq2 = kRegularSequenceSpace(2, ZZ)
sage: S = Seq2((Matrix([[1, 0], [0, 1]]), Matrix([[0, -1], [1, 2]])),
....: left=vector([0, 1]), right=vector([1, 0]))
sage: S[7]
3
TESTS::
sage: S[-1]
Traceback (most recent call last):
...
ValueError: value -1 of index is negative
::
sage: Seq2 = kRegularSequenceSpace(2, ZZ)
sage: W = Seq2.indices()
sage: M0 = Matrix([[1, 0], [0, 1]])
sage: M1 = Matrix([[0, -1], [1, 2]])
sage: S = Seq2((M0, M1), [0, 1], [1, 1])
sage: S._mu_of_word_(W(0.digits(2))) == M0
True
sage: S._mu_of_word_(W(1.digits(2))) == M1
True
sage: S._mu_of_word_(W(3.digits(2))) == M1^2
True
"""
return self.coefficient_of_word(self.parent()._n_to_index_(n), **kwds)

def __iter__(self):
r"""
Return an iterator over the coefficients of this sequence.
EXAMPLES::
sage: Seq2 = kRegularSequenceSpace(2, ZZ)
sage: S = Seq2((Matrix([[1, 0], [0, 1]]), Matrix([[0, -1], [1, 2]])),
....: left=vector([0, 1]), right=vector([1, 0]))
sage: from itertools import islice
sage: tuple(islice(S, 10))
(0, 1, 1, 2, 1, 2, 2, 3, 1, 2)
TESTS::
sage: it = iter(S)
sage: iter(it) is it
True
sage: iter(S) is not it
True
"""
from itertools import count
return iter(self[n] for n in count())


class kRegularSequenceSpace(RecognizableSeriesSpace):
r"""
The space of `k`-regular Sequences over the given ``coefficients``.
INPUT:
- ``k`` -- an integer at least `2` specifying the base
- ``coefficient_ring`` -- a (semi-)ring.
- ``category`` -- (default: ``None``) the category of this
space
EXAMPLES::
sage: kRegularSequenceSpace(2, ZZ)
Space of 2-regular sequences over Integer Ring
sage: kRegularSequenceSpace(3, ZZ)
Space of 3-regular sequences over Integer Ring
.. SEEALSO::
:doc:`k-regular sequence <k_regular_sequence>`,
:class:`kRegularSequence`.
"""
Element = kRegularSequence

@classmethod
def __normalize__(cls, k, coefficient_ring, **kwds):
r"""
Normalizes the input in order to ensure a unique
representation.
For more information see :class:`kRegularSequenceSpace`.
TESTS::
sage: Seq2 = kRegularSequenceSpace(2, ZZ)
sage: Seq2.category()
Category of sets
sage: Seq2.alphabet()
{0, 1}
"""
from sage.arith.srange import srange
nargs = super(kRegularSequenceSpace, cls).__normalize__(
coefficient_ring, alphabet=srange(k), **kwds)
return (k,) + nargs

def __init__(self, k, *args, **kwds):
r"""
See :class:`kRegularSequenceSpace` for details.
INPUT:
- ``k`` -- an integer at least `2` specifying the base
Other input arguments are passed on to
:meth:`~sage.combinat.recognizable_series.RecognizableSeriesSpace.__init__`.
TESTS::
sage: kRegularSequenceSpace(2, ZZ)
Space of 2-regular sequences over Integer Ring
sage: kRegularSequenceSpace(3, ZZ)
Space of 3-regular sequences over Integer Ring
.. SEEALSO::
:doc:`k-regular sequence <k_regular_sequence>`,
:class:`kRegularSequence`.
"""
self.k = k
super(kRegularSequenceSpace, self).__init__(*args, **kwds)

def _repr_(self):
r"""
Return a representation string of this `k`-regular sequence space.
OUTPUT:
A string
TESTS::
sage: repr(kRegularSequenceSpace(2, ZZ)) # indirect doctest
'Space of 2-regular sequences over Integer Ring'
"""
return 'Space of {}-regular sequences over {}'.format(self.k, self.base())

def _n_to_index_(self, n):
r"""
Convert `n` to an index usable by the underlying
recognizable series.
INPUT:
- ``n`` -- a nonnegative integer
OUTPUT:
A word
TESTS::
sage: Seq2 = kRegularSequenceSpace(2, ZZ)
sage: Seq2._n_to_index_(6)
word: 011
sage: Seq2._n_to_index_(-1)
Traceback (most recent call last):
...
ValueError: value -1 of index is negative
"""
from sage.rings.integer_ring import ZZ
n = ZZ(n)
W = self.indices()
try:
return W(n.digits(self.k))
except OverflowError:
raise ValueError('value {} of index is negative'.format(n)) from None
Loading

0 comments on commit 9f3988d

Please sign in to comment.