\(k\)-regular sequences¶
An introduction and formal definition of \(k\)-regular sequences can be found, for example, on the Wikipedia article k-regular_sequence or in [AS2003].
sage: import logging
sage: logging.basicConfig()
>>> from sage.all import *
>>> import logging
>>> logging.basicConfig()
import logging logging.basicConfig()
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 = RegularSequenceRing(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
>>> from sage.all import *
>>> Seq2 = RegularSequenceRing(Integer(2), ZZ)
>>> S = Seq2((Matrix([[Integer(1), Integer(0)], [Integer(0), Integer(1)]]), Matrix([[Integer(1), Integer(0)], [Integer(1), Integer(1)]])),
... left=vector([Integer(0), Integer(1)]), right=vector([Integer(1), Integer(0)]))
>>> S
2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ...
>>> all(S[n] == sum(n.digits(Integer(2))) for n in srange(Integer(10)))
True
Seq2 = RegularSequenceRing(2, ZZ) S = Seq2((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [1, 1]])), left=vector([0, 1]), right=vector([1, 0])) S all(S[n] == sum(n.digits(2)) for n in srange(10))
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(n // 2) + u((n+1) // 2)
sage: tuple(u(n) for n in srange(10))
(0, 1, 3, 5, 9, 11, 15, 19, 27, 29)
>>> from sage.all import *
>>> @cached_function
... def u(n):
... if n <= Integer(1):
... return n
... return Integer(2) * u(n // Integer(2)) + u((n+Integer(1)) // Integer(2))
>>> tuple(u(n) for n in srange(Integer(10)))
(0, 1, 3, 5, 9, 11, 15, 19, 27, 29)
@cached_function def u(n): if n <= 1: return n return 2 * u(n // 2) + u((n+1) // 2) tuple(u(n) for n in srange(10))
There is a \(2\)-regular sequence describing the numbers above as well:
sage: U = Seq2((Matrix([[3, 0], [2, 1]]), Matrix([[2, 1], [0, 3]])),
....: left=vector([1, 0]), right=vector([0, 1]))
sage: all(U[n] == u(n) for n in srange(30))
True
>>> from sage.all import *
>>> U = Seq2((Matrix([[Integer(3), Integer(0)], [Integer(2), Integer(1)]]), Matrix([[Integer(2), Integer(1)], [Integer(0), Integer(3)]])),
... left=vector([Integer(1), Integer(0)]), right=vector([Integer(0), Integer(1)]))
>>> all(U[n] == u(n) for n in srange(Integer(30)))
True
U = Seq2((Matrix([[3, 0], [2, 1]]), Matrix([[2, 1], [0, 3]])), left=vector([1, 0]), right=vector([0, 1])) all(U[n] == u(n) for n in srange(30))
Various¶
See also
recognizable series
,
sage.rings.cfinite_sequence
,
sage.combinat.binary_recurrence_sequences
.
AUTHORS:
Daniel Krenn (2016, 2021)
Gabriel F. Lipnik (2021)
ACKNOWLEDGEMENT:
Daniel Krenn is supported by the Austrian Science Fund (FWF): P 24644-N26.
Gabriel F. Lipnik is supported by the Austrian Science Fund (FWF): W 1230.
Classes and Methods¶
- exception sage.combinat.regular_sequence.DegeneratedSequenceError[source]¶
Bases:
RuntimeError
Exception raised if a degenerated sequence (see
is_degenerated()
) is detected.EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: Seq2((Matrix([2]), Matrix([3])), vector([1]), vector([1])) Traceback (most recent call last): ... DegeneratedSequenceError: degenerated sequence: mu[0]*right != right. Using such a sequence might lead to wrong results. You can use 'allow_degenerated_sequence=True' followed by a call of method .regenerated() for correcting this.
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> Seq2((Matrix([Integer(2)]), Matrix([Integer(3)])), vector([Integer(1)]), vector([Integer(1)])) Traceback (most recent call last): ... DegeneratedSequenceError: degenerated sequence: mu[0]*right != right. Using such a sequence might lead to wrong results. You can use 'allow_degenerated_sequence=True' followed by a call of method .regenerated() for correcting this.
Seq2 = RegularSequenceRing(2, ZZ) Seq2((Matrix([2]), Matrix([3])), vector([1]), vector([1]))
- class sage.combinat.regular_sequence.RecurrenceParser(k, coefficient_ring)[source]¶
Bases:
object
A parser for recurrence relations that allow the construction of a \(k\)-linear representation for the sequence satisfying these recurrence relations.
This is used by
RegularSequenceRing.from_recurrence()
to construct aRegularSequence
.- ind(M, m, ll, uu)[source]¶
Determine the index operator corresponding to the recursive sequence as defined in [HKL2022].
INPUT:
M
,m
– parameters of the recursive sequences, see [HKL2022], Definition 3.1ll
,uu
– parameters of the resulting linear representation, see [HKL2022], Theorem A
OUTPUT:
A dictionary which maps both row numbers to subsequence parameters and vice versa, i.e.,
ind[i]
– a pair(j, d)
representing the sequence \(x(k^j n + d)\) in the \(i\)-th component (0-based) of the resulting linear representationind[(j, d)]
– the (0-based) row number of the sequence \(x(k^j n + d)\) in the linear representation
EXAMPLES:
sage: from sage.combinat.regular_sequence import RecurrenceParser sage: RP = RecurrenceParser(2, ZZ) sage: RP.ind(3, 1, -3, 3) {(0, 0): 0, (1, -1): 3, (1, -2): 2, (1, -3): 1, (1, 0): 4, (1, 1): 5, (1, 2): 6, (1, 3): 7, (2, -1): 10, (2, -2): 9, (2, -3): 8, (2, 0): 11, (2, 1): 12, (2, 2): 13, (2, 3): 14, (2, 4): 15, (2, 5): 16, 0: (0, 0), 1: (1, -3), 10: (2, -1), 11: (2, 0), 12: (2, 1), 13: (2, 2), 14: (2, 3), 15: (2, 4), 16: (2, 5), 2: (1, -2), 3: (1, -1), 4: (1, 0), 5: (1, 1), 6: (1, 2), 7: (1, 3), 8: (2, -3), 9: (2, -2)}
>>> from sage.all import * >>> from sage.combinat.regular_sequence import RecurrenceParser >>> RP = RecurrenceParser(Integer(2), ZZ) >>> RP.ind(Integer(3), Integer(1), -Integer(3), Integer(3)) {(0, 0): 0, (1, -1): 3, (1, -2): 2, (1, -3): 1, (1, 0): 4, (1, 1): 5, (1, 2): 6, (1, 3): 7, (2, -1): 10, (2, -2): 9, (2, -3): 8, (2, 0): 11, (2, 1): 12, (2, 2): 13, (2, 3): 14, (2, 4): 15, (2, 5): 16, 0: (0, 0), 1: (1, -3), 10: (2, -1), 11: (2, 0), 12: (2, 1), 13: (2, 2), 14: (2, 3), 15: (2, 4), 16: (2, 5), 2: (1, -2), 3: (1, -1), 4: (1, 0), 5: (1, 1), 6: (1, 2), 7: (1, 3), 8: (2, -3), 9: (2, -2)}
from sage.combinat.regular_sequence import RecurrenceParser RP = RecurrenceParser(2, ZZ) RP.ind(3, 1, -3, 3)
- left(recurrence_rules)[source]¶
Construct the vector
left
of the linear representation of recursive sequences.INPUT:
recurrence_rules
– a namedtuple generated byparameters()
; it only needs to contain a fielddim
(a positive integer)
OUTPUT: a vector
EXAMPLES:
sage: from collections import namedtuple sage: from sage.combinat.regular_sequence import RecurrenceParser sage: RP = RecurrenceParser(2, ZZ) sage: RRD = namedtuple('recurrence_rules_dim', ....: ['dim', 'inhomogeneities']) sage: recurrence_rules = RRD(dim=5, inhomogeneities={}) sage: RP.left(recurrence_rules) (1, 0, 0, 0, 0)
>>> from sage.all import * >>> from collections import namedtuple >>> from sage.combinat.regular_sequence import RecurrenceParser >>> RP = RecurrenceParser(Integer(2), ZZ) >>> RRD = namedtuple('recurrence_rules_dim', ... ['dim', 'inhomogeneities']) >>> recurrence_rules = RRD(dim=Integer(5), inhomogeneities={}) >>> RP.left(recurrence_rules) (1, 0, 0, 0, 0)
from collections import namedtuple from sage.combinat.regular_sequence import RecurrenceParser RP = RecurrenceParser(2, ZZ) RRD = namedtuple('recurrence_rules_dim', ['dim', 'inhomogeneities']) recurrence_rules = RRD(dim=5, inhomogeneities={}) RP.left(recurrence_rules)
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: RRD = namedtuple('recurrence_rules_dim', ....: ['M', 'm', 'll', 'uu', 'dim', 'inhomogeneities']) sage: recurrence_rules = RRD(M=3, m=2, ll=0, uu=9, dim=5, ....: inhomogeneities={0: Seq2.one_hadamard()}) sage: RP.left(recurrence_rules) (1, 0, 0, 0, 0, 0, 0, 0)
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> RRD = namedtuple('recurrence_rules_dim', ... ['M', 'm', 'll', 'uu', 'dim', 'inhomogeneities']) >>> recurrence_rules = RRD(M=Integer(3), m=Integer(2), ll=Integer(0), uu=Integer(9), dim=Integer(5), ... inhomogeneities={Integer(0): Seq2.one_hadamard()}) >>> RP.left(recurrence_rules) (1, 0, 0, 0, 0, 0, 0, 0)
Seq2 = RegularSequenceRing(2, ZZ) RRD = namedtuple('recurrence_rules_dim', ['M', 'm', 'll', 'uu', 'dim', 'inhomogeneities']) recurrence_rules = RRD(M=3, m=2, ll=0, uu=9, dim=5, inhomogeneities={0: Seq2.one_hadamard()}) RP.left(recurrence_rules)
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> RRD = namedtuple('recurrence_rules_dim', ... ['M', 'm', 'll', 'uu', 'dim', 'inhomogeneities']) >>> recurrence_rules = RRD(M=Integer(3), m=Integer(2), ll=Integer(0), uu=Integer(9), dim=Integer(5), ... inhomogeneities={Integer(0): Seq2.one_hadamard()}) >>> RP.left(recurrence_rules) (1, 0, 0, 0, 0, 0, 0, 0)
Seq2 = RegularSequenceRing(2, ZZ) RRD = namedtuple('recurrence_rules_dim', ['M', 'm', 'll', 'uu', 'dim', 'inhomogeneities']) recurrence_rules = RRD(M=3, m=2, ll=0, uu=9, dim=5, inhomogeneities={0: Seq2.one_hadamard()}) RP.left(recurrence_rules)
- matrix(recurrence_rules, rem, correct_offset=True)[source]¶
Construct the matrix for remainder
rem
of the linear representation of the sequence represented byrecurrence_rules
.INPUT:
recurrence_rules
– a namedtuple generated byparameters()
rem
– integer between \(0\) and \(k - 1\)correct_offset
– boolean (default:True
); ifTrue
, then the resulting linear representation has no offset. See [HKL2022] for more information.
OUTPUT: a matrix
EXAMPLES:
The following example illustrates how the coefficients in the right-hand sides of the recurrence relations correspond to the entries of the matrices.
sage: from sage.combinat.regular_sequence import RecurrenceParser sage: RP = RecurrenceParser(2, ZZ) sage: var('n') n sage: function('f') f sage: M, m, coeffs, initial_values = RP.parse_recurrence([ ....: f(8*n) == -1*f(2*n - 1) + 1*f(2*n + 1), ....: f(8*n + 1) == -11*f(2*n - 1) + 10*f(2*n) + 11*f(2*n + 1), ....: f(8*n + 2) == -21*f(2*n - 1) + 20*f(2*n) + 21*f(2*n + 1), ....: f(8*n + 3) == -31*f(2*n - 1) + 30*f(2*n) + 31*f(2*n + 1), ....: f(8*n + 4) == -41*f(2*n - 1) + 40*f(2*n) + 41*f(2*n + 1), ....: f(8*n + 5) == -51*f(2*n - 1) + 50*f(2*n) + 51*f(2*n + 1), ....: f(8*n + 6) == -61*f(2*n - 1) + 60*f(2*n) + 61*f(2*n + 1), ....: f(8*n + 7) == -71*f(2*n - 1) + 70*f(2*n) + 71*f(2*n + 1), ....: f(0) == 0, f(1) == 1, f(2) == 2, f(3) == 3, f(4) == 4, ....: f(5) == 5, f(6) == 6, f(7) == 7], f, n) sage: rules = RP.parameters( ....: M, m, coeffs, initial_values, 0) sage: RP.matrix(rules, 0, False) [ 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] [ 0 -51 50 51 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 -61 60 61 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 -71 70 71 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -11 10 11 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -21 20 21 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -31 30 31 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -41 40 41 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -51 50 51 0 0 0 0 0 0 0 0 0 0 0] sage: RP.matrix(rules, 1, False) [ 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1] [ 0 0 0 -11 10 11 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -21 20 21 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -31 30 31 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -41 40 41 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -51 50 51 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -61 60 61 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -71 70 71 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 -11 10 11 0 0 0 0 0 0 0 0 0]
>>> from sage.all import * >>> from sage.combinat.regular_sequence import RecurrenceParser >>> RP = RecurrenceParser(Integer(2), ZZ) >>> var('n') n >>> function('f') f >>> M, m, coeffs, initial_values = RP.parse_recurrence([ ... f(Integer(8)*n) == -Integer(1)*f(Integer(2)*n - Integer(1)) + Integer(1)*f(Integer(2)*n + Integer(1)), ... f(Integer(8)*n + Integer(1)) == -Integer(11)*f(Integer(2)*n - Integer(1)) + Integer(10)*f(Integer(2)*n) + Integer(11)*f(Integer(2)*n + Integer(1)), ... f(Integer(8)*n + Integer(2)) == -Integer(21)*f(Integer(2)*n - Integer(1)) + Integer(20)*f(Integer(2)*n) + Integer(21)*f(Integer(2)*n + Integer(1)), ... f(Integer(8)*n + Integer(3)) == -Integer(31)*f(Integer(2)*n - Integer(1)) + Integer(30)*f(Integer(2)*n) + Integer(31)*f(Integer(2)*n + Integer(1)), ... f(Integer(8)*n + Integer(4)) == -Integer(41)*f(Integer(2)*n - Integer(1)) + Integer(40)*f(Integer(2)*n) + Integer(41)*f(Integer(2)*n + Integer(1)), ... f(Integer(8)*n + Integer(5)) == -Integer(51)*f(Integer(2)*n - Integer(1)) + Integer(50)*f(Integer(2)*n) + Integer(51)*f(Integer(2)*n + Integer(1)), ... f(Integer(8)*n + Integer(6)) == -Integer(61)*f(Integer(2)*n - Integer(1)) + Integer(60)*f(Integer(2)*n) + Integer(61)*f(Integer(2)*n + Integer(1)), ... f(Integer(8)*n + Integer(7)) == -Integer(71)*f(Integer(2)*n - Integer(1)) + Integer(70)*f(Integer(2)*n) + Integer(71)*f(Integer(2)*n + Integer(1)), ... f(Integer(0)) == Integer(0), f(Integer(1)) == Integer(1), f(Integer(2)) == Integer(2), f(Integer(3)) == Integer(3), f(Integer(4)) == Integer(4), ... f(Integer(5)) == Integer(5), f(Integer(6)) == Integer(6), f(Integer(7)) == Integer(7)], f, n) >>> rules = RP.parameters( ... M, m, coeffs, initial_values, Integer(0)) >>> RP.matrix(rules, Integer(0), False) [ 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] [ 0 -51 50 51 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 -61 60 61 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 -71 70 71 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -11 10 11 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -21 20 21 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -31 30 31 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -41 40 41 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -51 50 51 0 0 0 0 0 0 0 0 0 0 0] >>> RP.matrix(rules, Integer(1), False) [ 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1] [ 0 0 0 -11 10 11 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -21 20 21 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -31 30 31 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -41 40 41 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -51 50 51 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -61 60 61 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 -71 70 71 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 -11 10 11 0 0 0 0 0 0 0 0 0]
from sage.combinat.regular_sequence import RecurrenceParser RP = RecurrenceParser(2, ZZ) var('n') function('f') M, m, coeffs, initial_values = RP.parse_recurrence([ f(8*n) == -1*f(2*n - 1) + 1*f(2*n + 1), f(8*n + 1) == -11*f(2*n - 1) + 10*f(2*n) + 11*f(2*n + 1), f(8*n + 2) == -21*f(2*n - 1) + 20*f(2*n) + 21*f(2*n + 1), f(8*n + 3) == -31*f(2*n - 1) + 30*f(2*n) + 31*f(2*n + 1), f(8*n + 4) == -41*f(2*n - 1) + 40*f(2*n) + 41*f(2*n + 1), f(8*n + 5) == -51*f(2*n - 1) + 50*f(2*n) + 51*f(2*n + 1), f(8*n + 6) == -61*f(2*n - 1) + 60*f(2*n) + 61*f(2*n + 1), f(8*n + 7) == -71*f(2*n - 1) + 70*f(2*n) + 71*f(2*n + 1), f(0) == 0, f(1) == 1, f(2) == 2, f(3) == 3, f(4) == 4, f(5) == 5, f(6) == 6, f(7) == 7], f, n) rules = RP.parameters( M, m, coeffs, initial_values, 0) RP.matrix(rules, 0, False) RP.matrix(rules, 1, False)
Stern–Brocot Sequence:
sage: SB_rules = RP.parameters( ....: 1, 0, {(0, 0): 1, (1, 0): 1, (1, 1): 1}, ....: {0: 0, 1: 1, 2: 1}, 0) sage: RP.matrix(SB_rules, 0) [1 0 0] [1 1 0] [0 1 0] sage: RP.matrix(SB_rules, 1) [1 1 0] [0 1 0] [0 1 1]
>>> from sage.all import * >>> SB_rules = RP.parameters( ... Integer(1), Integer(0), {(Integer(0), Integer(0)): Integer(1), (Integer(1), Integer(0)): Integer(1), (Integer(1), Integer(1)): Integer(1)}, ... {Integer(0): Integer(0), Integer(1): Integer(1), Integer(2): Integer(1)}, Integer(0)) >>> RP.matrix(SB_rules, Integer(0)) [1 0 0] [1 1 0] [0 1 0] >>> RP.matrix(SB_rules, Integer(1)) [1 1 0] [0 1 0] [0 1 1]
SB_rules = RP.parameters( 1, 0, {(0, 0): 1, (1, 0): 1, (1, 1): 1}, {0: 0, 1: 1, 2: 1}, 0) RP.matrix(SB_rules, 0) RP.matrix(SB_rules, 1)
Number of Unbordered Factors in the Thue–Morse Sequence:
sage: M, m, coeffs, initial_values = RP.parse_recurrence([ ....: f(8*n) == 2*f(4*n), ....: f(8*n + 1) == f(4*n + 1), ....: f(8*n + 2) == f(4*n + 1) + f(4*n + 3), ....: f(8*n + 3) == -f(4*n + 1) + f(4*n + 2), ....: f(8*n + 4) == 2*f(4*n + 2), ....: f(8*n + 5) == f(4*n + 3), ....: f(8*n + 6) == -f(4*n + 1) + f(4*n + 2) + f(4*n + 3), ....: f(8*n + 7) == 2*f(4*n + 1) + f(4*n + 3), ....: f(0) == 1, f(1) == 2, f(2) == 2, f(3) == 4, f(4) == 2, ....: f(5) == 4, f(6) == 6, f(7) == 0, f(8) == 4, f(9) == 4, ....: f(10) == 4, f(11) == 4, f(12) == 12, f(13) == 0, f(14) == 4, ....: f(15) == 4, f(16) == 8, f(17) == 4, f(18) == 8, f(19) == 0, ....: f(20) == 8, f(21) == 4, f(22) == 4, f(23) == 8], f, n) sage: UB_rules = RP.parameters( ....: M, m, coeffs, initial_values, 3) sage: RP.matrix(UB_rules, 0) [ 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 2 0 0 0 0 0 0 0 0 0 -1 0 0] [ 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 1 0 1 0 0 0 0 0 0 -4 0 0] [ 0 0 0 0 -1 1 0 0 0 0 0 0 0 4 2 0] [ 0 0 0 0 0 2 0 0 0 0 0 0 0 -2 0 0] [ 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 -1 1 1 0 0 0 0 0 0 2 2 0] [ 0 0 0 0 2 0 1 0 0 0 0 0 0 -8 -4 -4] [ 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0] sage: RP.matrix(UB_rules, 1) [ 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 2 0 0 0 0 0 0 0 -2 0 0] [ 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 -1 1 1 0 0 0 0 0 0 2 2 0] [ 0 0 0 0 2 0 1 0 0 0 0 0 0 -8 -4 -4] [ 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 -1 1 0 0 0 2 0 0] [ 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
>>> from sage.all import * >>> M, m, coeffs, initial_values = RP.parse_recurrence([ ... f(Integer(8)*n) == Integer(2)*f(Integer(4)*n), ... f(Integer(8)*n + Integer(1)) == f(Integer(4)*n + Integer(1)), ... f(Integer(8)*n + Integer(2)) == f(Integer(4)*n + Integer(1)) + f(Integer(4)*n + Integer(3)), ... f(Integer(8)*n + Integer(3)) == -f(Integer(4)*n + Integer(1)) + f(Integer(4)*n + Integer(2)), ... f(Integer(8)*n + Integer(4)) == Integer(2)*f(Integer(4)*n + Integer(2)), ... f(Integer(8)*n + Integer(5)) == f(Integer(4)*n + Integer(3)), ... f(Integer(8)*n + Integer(6)) == -f(Integer(4)*n + Integer(1)) + f(Integer(4)*n + Integer(2)) + f(Integer(4)*n + Integer(3)), ... f(Integer(8)*n + Integer(7)) == Integer(2)*f(Integer(4)*n + Integer(1)) + f(Integer(4)*n + Integer(3)), ... f(Integer(0)) == Integer(1), f(Integer(1)) == Integer(2), f(Integer(2)) == Integer(2), f(Integer(3)) == Integer(4), f(Integer(4)) == Integer(2), ... f(Integer(5)) == Integer(4), f(Integer(6)) == Integer(6), f(Integer(7)) == Integer(0), f(Integer(8)) == Integer(4), f(Integer(9)) == Integer(4), ... f(Integer(10)) == Integer(4), f(Integer(11)) == Integer(4), f(Integer(12)) == Integer(12), f(Integer(13)) == Integer(0), f(Integer(14)) == Integer(4), ... f(Integer(15)) == Integer(4), f(Integer(16)) == Integer(8), f(Integer(17)) == Integer(4), f(Integer(18)) == Integer(8), f(Integer(19)) == Integer(0), ... f(Integer(20)) == Integer(8), f(Integer(21)) == Integer(4), f(Integer(22)) == Integer(4), f(Integer(23)) == Integer(8)], f, n) >>> UB_rules = RP.parameters( ... M, m, coeffs, initial_values, Integer(3)) >>> RP.matrix(UB_rules, Integer(0)) [ 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 2 0 0 0 0 0 0 0 0 0 -1 0 0] [ 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 1 0 1 0 0 0 0 0 0 -4 0 0] [ 0 0 0 0 -1 1 0 0 0 0 0 0 0 4 2 0] [ 0 0 0 0 0 2 0 0 0 0 0 0 0 -2 0 0] [ 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 -1 1 1 0 0 0 0 0 0 2 2 0] [ 0 0 0 0 2 0 1 0 0 0 0 0 0 -8 -4 -4] [ 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0] >>> RP.matrix(UB_rules, Integer(1)) [ 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 2 0 0 0 0 0 0 0 -2 0 0] [ 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 -1 1 1 0 0 0 0 0 0 2 2 0] [ 0 0 0 0 2 0 1 0 0 0 0 0 0 -8 -4 -4] [ 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 -1 1 0 0 0 2 0 0] [ 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
M, m, coeffs, initial_values = RP.parse_recurrence([ f(8*n) == 2*f(4*n), f(8*n + 1) == f(4*n + 1), f(8*n + 2) == f(4*n + 1) + f(4*n + 3), f(8*n + 3) == -f(4*n + 1) + f(4*n + 2), f(8*n + 4) == 2*f(4*n + 2), f(8*n + 5) == f(4*n + 3), f(8*n + 6) == -f(4*n + 1) + f(4*n + 2) + f(4*n + 3), f(8*n + 7) == 2*f(4*n + 1) + f(4*n + 3), f(0) == 1, f(1) == 2, f(2) == 2, f(3) == 4, f(4) == 2, f(5) == 4, f(6) == 6, f(7) == 0, f(8) == 4, f(9) == 4, f(10) == 4, f(11) == 4, f(12) == 12, f(13) == 0, f(14) == 4, f(15) == 4, f(16) == 8, f(17) == 4, f(18) == 8, f(19) == 0, f(20) == 8, f(21) == 4, f(22) == 4, f(23) == 8], f, n) UB_rules = RP.parameters( M, m, coeffs, initial_values, 3) RP.matrix(UB_rules, 0) RP.matrix(UB_rules, 1)
- parameters(M, m, coeffs, initial_values, offset=0, inhomogeneities={})[source]¶
Determine parameters from recurrence relations as admissible in
RegularSequenceRing.from_recurrence()
.INPUT:
All parameters are explained in the high-level method
RegularSequenceRing.from_recurrence()
.OUTPUT: a namedtuple
recurrence_rules
consisting ofM
,m
,l
,u
,offset
– parameters of the recursive sequences, see [HKL2022], Definition 3.1ll
,uu
,n1
,dim
– parameters and dimension of the resulting linear representation, see [HKL2022], Theorem Acoeffs
– dictionary mapping(r, j)
to the coefficients \(c_{r, j}\) as given in [HKL2022], Equation (3.1). Ifcoeffs[(r, j)]
is not given for somer
andj
, then it is assumed to be zero.initial_values
– dictionary mapping integersn
to then
-th value of the sequenceinhomogeneities
– dictionary mapping integersr
to the inhomogeneity \(g_r\) as given in [HKL2022], Corollary D
EXAMPLES:
sage: from sage.combinat.regular_sequence import RecurrenceParser sage: RP = RecurrenceParser(2, ZZ) sage: RP.parameters(2, 1, ....: {(0, -2): 3, (0, 0): 1, (0, 1): 2, (1, -2): 6, (1, 0): 4, ....: (1, 1): 5, (2, -2): 9, (2, 0): 7, (2, 1): 8, (3, -2): 12, ....: (3, 0): 10, (3, 1): 11}, {0: 1, 1: 2, 2: 1, 3: 4}, 0, {0: 1}) recurrence_rules(M=2, m=1, l=-2, u=1, ll=-6, uu=3, dim=14, coeffs={(0, -2): 3, (0, 0): 1, (0, 1): 2, (1, -2): 6, (1, 0): 4, (1, 1): 5, (2, -2): 9, (2, 0): 7, (2, 1): 8, (3, -2): 12, (3, 0): 10, (3, 1): 11}, initial_values={0: 1, 1: 2, 2: 1, 3: 4, 4: 13, 5: 30, 6: 48, 7: 66, 8: 77, 9: 208, 10: 340, 11: 472, 12: 220, 13: 600, -6: 0, -5: 0, -4: 0, -3: 0, -2: 0, -1: 0}, offset=1, n1=3, inhomogeneities={0: 2-regular sequence 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...})
>>> from sage.all import * >>> from sage.combinat.regular_sequence import RecurrenceParser >>> RP = RecurrenceParser(Integer(2), ZZ) >>> RP.parameters(Integer(2), Integer(1), ... {(Integer(0), -Integer(2)): Integer(3), (Integer(0), Integer(0)): Integer(1), (Integer(0), Integer(1)): Integer(2), (Integer(1), -Integer(2)): Integer(6), (Integer(1), Integer(0)): Integer(4), ... (Integer(1), Integer(1)): Integer(5), (Integer(2), -Integer(2)): Integer(9), (Integer(2), Integer(0)): Integer(7), (Integer(2), Integer(1)): Integer(8), (Integer(3), -Integer(2)): Integer(12), ... (Integer(3), Integer(0)): Integer(10), (Integer(3), Integer(1)): Integer(11)}, {Integer(0): Integer(1), Integer(1): Integer(2), Integer(2): Integer(1), Integer(3): Integer(4)}, Integer(0), {Integer(0): Integer(1)}) recurrence_rules(M=2, m=1, l=-2, u=1, ll=-6, uu=3, dim=14, coeffs={(0, -2): 3, (0, 0): 1, (0, 1): 2, (1, -2): 6, (1, 0): 4, (1, 1): 5, (2, -2): 9, (2, 0): 7, (2, 1): 8, (3, -2): 12, (3, 0): 10, (3, 1): 11}, initial_values={0: 1, 1: 2, 2: 1, 3: 4, 4: 13, 5: 30, 6: 48, 7: 66, 8: 77, 9: 208, 10: 340, 11: 472, 12: 220, 13: 600, -6: 0, -5: 0, -4: 0, -3: 0, -2: 0, -1: 0}, offset=1, n1=3, inhomogeneities={0: 2-regular sequence 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...})
from sage.combinat.regular_sequence import RecurrenceParser RP = RecurrenceParser(2, ZZ) RP.parameters(2, 1, {(0, -2): 3, (0, 0): 1, (0, 1): 2, (1, -2): 6, (1, 0): 4, (1, 1): 5, (2, -2): 9, (2, 0): 7, (2, 1): 8, (3, -2): 12, (3, 0): 10, (3, 1): 11}, {0: 1, 1: 2, 2: 1, 3: 4}, 0, {0: 1})
- parse_direct_arguments(M, m, coeffs, initial_values)[source]¶
Check whether the direct arguments as admissible in
RegularSequenceRing.from_recurrence()
are valid.INPUT:
All parameters are explained in the high-level method
RegularSequenceRing.from_recurrence()
.OUTPUT: a tuple consisting of the input parameters
EXAMPLES:
sage: from sage.combinat.regular_sequence import RecurrenceParser sage: RP = RecurrenceParser(2, ZZ) sage: RP.parse_direct_arguments(2, 1, ....: {(0, -2): 3, (0, 0): 1, (0, 1): 2, ....: (1, -2): 6, (1, 0): 4, (1, 1): 5, ....: (2, -2): 9, (2, 0): 7, (2, 1): 8, ....: (3, -2): 12, (3, 0): 10, (3, 1): 11}, ....: {0: 1, 1: 2, 2: 1}) (2, 1, {(0, -2): 3, (0, 0): 1, (0, 1): 2, (1, -2): 6, (1, 0): 4, (1, 1): 5, (2, -2): 9, (2, 0): 7, (2, 1): 8, (3, -2): 12, (3, 0): 10, (3, 1): 11}, {0: 1, 1: 2, 2: 1})
>>> from sage.all import * >>> from sage.combinat.regular_sequence import RecurrenceParser >>> RP = RecurrenceParser(Integer(2), ZZ) >>> RP.parse_direct_arguments(Integer(2), Integer(1), ... {(Integer(0), -Integer(2)): Integer(3), (Integer(0), Integer(0)): Integer(1), (Integer(0), Integer(1)): Integer(2), ... (Integer(1), -Integer(2)): Integer(6), (Integer(1), Integer(0)): Integer(4), (Integer(1), Integer(1)): Integer(5), ... (Integer(2), -Integer(2)): Integer(9), (Integer(2), Integer(0)): Integer(7), (Integer(2), Integer(1)): Integer(8), ... (Integer(3), -Integer(2)): Integer(12), (Integer(3), Integer(0)): Integer(10), (Integer(3), Integer(1)): Integer(11)}, ... {Integer(0): Integer(1), Integer(1): Integer(2), Integer(2): Integer(1)}) (2, 1, {(0, -2): 3, (0, 0): 1, (0, 1): 2, (1, -2): 6, (1, 0): 4, (1, 1): 5, (2, -2): 9, (2, 0): 7, (2, 1): 8, (3, -2): 12, (3, 0): 10, (3, 1): 11}, {0: 1, 1: 2, 2: 1})
from sage.combinat.regular_sequence import RecurrenceParser RP = RecurrenceParser(2, ZZ) RP.parse_direct_arguments(2, 1, {(0, -2): 3, (0, 0): 1, (0, 1): 2, (1, -2): 6, (1, 0): 4, (1, 1): 5, (2, -2): 9, (2, 0): 7, (2, 1): 8, (3, -2): 12, (3, 0): 10, (3, 1): 11}, {0: 1, 1: 2, 2: 1})
Stern–Brocot Sequence:
sage: RP.parse_direct_arguments(1, 0, ....: {(0, 0): 1, (1, 0): 1, (1, 1): 1}, ....: {0: 0, 1: 1}) (1, 0, {(0, 0): 1, (1, 0): 1, (1, 1): 1}, {0: 0, 1: 1})
>>> from sage.all import * >>> RP.parse_direct_arguments(Integer(1), Integer(0), ... {(Integer(0), Integer(0)): Integer(1), (Integer(1), Integer(0)): Integer(1), (Integer(1), Integer(1)): Integer(1)}, ... {Integer(0): Integer(0), Integer(1): Integer(1)}) (1, 0, {(0, 0): 1, (1, 0): 1, (1, 1): 1}, {0: 0, 1: 1})
RP.parse_direct_arguments(1, 0, {(0, 0): 1, (1, 0): 1, (1, 1): 1}, {0: 0, 1: 1})
- parse_recurrence(equations, function, var)[source]¶
Parse recurrence relations as admissible in
RegularSequenceRing.from_recurrence()
.INPUT:
All parameters are explained in the high-level method
RegularSequenceRing.from_recurrence()
.OUTPUT: a tuple consisting of
M
,m
– seeRegularSequenceRing.from_recurrence()
coeffs
– seeRegularSequenceRing.from_recurrence()
initial_values
– seeRegularSequenceRing.from_recurrence()
EXAMPLES:
sage: from sage.combinat.regular_sequence import RecurrenceParser sage: RP = RecurrenceParser(2, ZZ) sage: var('n') n sage: function('f') f sage: RP.parse_recurrence([ ....: f(4*n) == f(2*n) + 2*f(2*n + 1) + 3*f(2*n - 2), ....: f(4*n + 1) == 4*f(2*n) + 5*f(2*n + 1) + 6*f(2*n - 2), ....: f(4*n + 2) == 7*f(2*n) + 8*f(2*n + 1) + 9*f(2*n - 2), ....: f(4*n + 3) == 10*f(2*n) + 11*f(2*n + 1) + 12*f(2*n - 2), ....: f(0) == 1, f(1) == 2, f(2) == 1], f, n) (2, 1, {(0, -2): 3, (0, 0): 1, (0, 1): 2, (1, -2): 6, (1, 0): 4, (1, 1): 5, (2, -2): 9, (2, 0): 7, (2, 1): 8, (3, -2): 12, (3, 0): 10, (3, 1): 11}, {0: 1, 1: 2, 2: 1})
>>> from sage.all import * >>> from sage.combinat.regular_sequence import RecurrenceParser >>> RP = RecurrenceParser(Integer(2), ZZ) >>> var('n') n >>> function('f') f >>> RP.parse_recurrence([ ... f(Integer(4)*n) == f(Integer(2)*n) + Integer(2)*f(Integer(2)*n + Integer(1)) + Integer(3)*f(Integer(2)*n - Integer(2)), ... f(Integer(4)*n + Integer(1)) == Integer(4)*f(Integer(2)*n) + Integer(5)*f(Integer(2)*n + Integer(1)) + Integer(6)*f(Integer(2)*n - Integer(2)), ... f(Integer(4)*n + Integer(2)) == Integer(7)*f(Integer(2)*n) + Integer(8)*f(Integer(2)*n + Integer(1)) + Integer(9)*f(Integer(2)*n - Integer(2)), ... f(Integer(4)*n + Integer(3)) == Integer(10)*f(Integer(2)*n) + Integer(11)*f(Integer(2)*n + Integer(1)) + Integer(12)*f(Integer(2)*n - Integer(2)), ... f(Integer(0)) == Integer(1), f(Integer(1)) == Integer(2), f(Integer(2)) == Integer(1)], f, n) (2, 1, {(0, -2): 3, (0, 0): 1, (0, 1): 2, (1, -2): 6, (1, 0): 4, (1, 1): 5, (2, -2): 9, (2, 0): 7, (2, 1): 8, (3, -2): 12, (3, 0): 10, (3, 1): 11}, {0: 1, 1: 2, 2: 1})
from sage.combinat.regular_sequence import RecurrenceParser RP = RecurrenceParser(2, ZZ) var('n') function('f') RP.parse_recurrence([ f(4*n) == f(2*n) + 2*f(2*n + 1) + 3*f(2*n - 2), f(4*n + 1) == 4*f(2*n) + 5*f(2*n + 1) + 6*f(2*n - 2), f(4*n + 2) == 7*f(2*n) + 8*f(2*n + 1) + 9*f(2*n - 2), f(4*n + 3) == 10*f(2*n) + 11*f(2*n + 1) + 12*f(2*n - 2), f(0) == 1, f(1) == 2, f(2) == 1], f, n)
Stern–Brocot Sequence:
sage: RP.parse_recurrence([ ....: f(2*n) == f(n), f(2*n + 1) == f(n) + f(n + 1), ....: f(0) == 0, f(1) == 1], f, n) (1, 0, {(0, 0): 1, (1, 0): 1, (1, 1): 1}, {0: 0, 1: 1})
>>> from sage.all import * >>> RP.parse_recurrence([ ... f(Integer(2)*n) == f(n), f(Integer(2)*n + Integer(1)) == f(n) + f(n + Integer(1)), ... f(Integer(0)) == Integer(0), f(Integer(1)) == Integer(1)], f, n) (1, 0, {(0, 0): 1, (1, 0): 1, (1, 1): 1}, {0: 0, 1: 1})
RP.parse_recurrence([ f(2*n) == f(n), f(2*n + 1) == f(n) + f(n + 1), f(0) == 0, f(1) == 1], f, n)
- right(recurrence_rules)[source]¶
Construct the vector
right
of the linear representation of the sequence induced byrecurrence_rules
.INPUT:
recurrence_rules
– a namedtuple generated byparameters()
OUTPUT: a vector
- shifted_inhomogeneities(recurrence_rules)[source]¶
Return a dictionary of all needed shifted inhomogeneities as described in the proof of Corollary D in [HKL2022].
INPUT:
recurrence_rules
– a namedtuple generated byparameters()
OUTPUT:
A dictionary mapping \(r\) to the regular sequence \(\sum_i g_r(n + i)\) for \(g_r\) as given in [HKL2022], Corollary D, and \(i\) between \(\lfloor\ell'/k^{M}\rfloor\) and \(\lfloor (k^{M-1} - k^{m} + u')/k^{M}\rfloor + 1\); see [HKL2022], proof of Corollary D. The first blocks of the corresponding vector-valued sequence (obtained from its linear representation) correspond to the sequences \(g_r(n + i)\) where \(i\) is as in the sum above; the remaining blocks consist of other shifts which are required for the regular sequence.
EXAMPLES:
sage: from collections import namedtuple sage: from sage.combinat.regular_sequence import RecurrenceParser sage: RP = RecurrenceParser(2, ZZ) sage: Seq2 = RegularSequenceRing(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: RR = namedtuple('recurrence_rules', ....: ['M', 'm', 'll', 'uu', 'inhomogeneities']) sage: recurrence_rules = RR(M=3, m=0, ll=-14, uu=14, ....: inhomogeneities={0: S, 1: S}) sage: SI = RP.shifted_inhomogeneities(recurrence_rules) sage: SI {0: 2-regular sequence 4, 5, 7, 9, 11, 11, 11, 12, 13, 13, ..., 1: 2-regular sequence 4, 5, 7, 9, 11, 11, 11, 12, 13, 13, ...}
>>> from sage.all import * >>> from collections import namedtuple >>> from sage.combinat.regular_sequence import RecurrenceParser >>> RP = RecurrenceParser(Integer(2), ZZ) >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> S = Seq2((Matrix([[Integer(1), Integer(0)], [Integer(0), Integer(1)]]), Matrix([[Integer(1), Integer(0)], [Integer(1), Integer(1)]])), ... left=vector([Integer(0), Integer(1)]), right=vector([Integer(1), Integer(0)])) >>> S 2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ... >>> RR = namedtuple('recurrence_rules', ... ['M', 'm', 'll', 'uu', 'inhomogeneities']) >>> recurrence_rules = RR(M=Integer(3), m=Integer(0), ll=-Integer(14), uu=Integer(14), ... inhomogeneities={Integer(0): S, Integer(1): S}) >>> SI = RP.shifted_inhomogeneities(recurrence_rules) >>> SI {0: 2-regular sequence 4, 5, 7, 9, 11, 11, 11, 12, 13, 13, ..., 1: 2-regular sequence 4, 5, 7, 9, 11, 11, 11, 12, 13, 13, ...}
from collections import namedtuple from sage.combinat.regular_sequence import RecurrenceParser RP = RecurrenceParser(2, ZZ) Seq2 = RegularSequenceRing(2, ZZ) S = Seq2((Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [1, 1]])), left=vector([0, 1]), right=vector([1, 0])) S RR = namedtuple('recurrence_rules', ['M', 'm', 'll', 'uu', 'inhomogeneities']) recurrence_rules = RR(M=3, m=0, ll=-14, uu=14, inhomogeneities={0: S, 1: S}) SI = RP.shifted_inhomogeneities(recurrence_rules) SI
The first blocks of the corresponding vector-valued sequence correspond to the corresponding shifts of the inhomogeneity. In this particular case, there are no other blocks:
sage: lower = -2 sage: upper = 3 sage: SI[0].dimension() == S.dimension() * (upper - lower + 1) True sage: all( ....: Seq2( ....: SI[0].mu, ....: vector((i - lower)*[0, 0] + list(S.left) + (upper - i)*[0, 0]), ....: SI[0].right) ....: == S.subsequence(1, i) ....: for i in range(lower, upper+1)) True
>>> from sage.all import * >>> lower = -Integer(2) >>> upper = Integer(3) >>> SI[Integer(0)].dimension() == S.dimension() * (upper - lower + Integer(1)) True >>> all( ... Seq2( ... SI[Integer(0)].mu, ... vector((i - lower)*[Integer(0), Integer(0)] + list(S.left) + (upper - i)*[Integer(0), Integer(0)]), ... SI[Integer(0)].right) ... == S.subsequence(Integer(1), i) ... for i in range(lower, upper+Integer(1))) True
lower = -2 upper = 3 SI[0].dimension() == S.dimension() * (upper - lower + 1) all( Seq2( SI[0].mu, vector((i - lower)*[0, 0] + list(S.left) + (upper - i)*[0, 0]), SI[0].right) == S.subsequence(1, i) for i in range(lower, upper+1))
- v_eval_n(recurrence_rules, n)[source]¶
Return the vector \(v(n)\) as given in [HKL2022], Theorem A.
INPUT:
recurrence_rules
– a namedtuple generated byparameters()
n
– integer
OUTPUT: a vector
EXAMPLES:
Stern–Brocot Sequence:
sage: from sage.combinat.regular_sequence import RecurrenceParser sage: RP = RecurrenceParser(2, ZZ) sage: SB_rules = RP.parameters( ....: 1, 0, {(0, 0): 1, (1, 0): 1, (1, 1): 1}, ....: {0: 0, 1: 1, 2: 1}, 0) sage: RP.v_eval_n(SB_rules, 0) (0, 1, 1)
>>> from sage.all import * >>> from sage.combinat.regular_sequence import RecurrenceParser >>> RP = RecurrenceParser(Integer(2), ZZ) >>> SB_rules = RP.parameters( ... Integer(1), Integer(0), {(Integer(0), Integer(0)): Integer(1), (Integer(1), Integer(0)): Integer(1), (Integer(1), Integer(1)): Integer(1)}, ... {Integer(0): Integer(0), Integer(1): Integer(1), Integer(2): Integer(1)}, Integer(0)) >>> RP.v_eval_n(SB_rules, Integer(0)) (0, 1, 1)
from sage.combinat.regular_sequence import RecurrenceParser RP = RecurrenceParser(2, ZZ) SB_rules = RP.parameters( 1, 0, {(0, 0): 1, (1, 0): 1, (1, 1): 1}, {0: 0, 1: 1, 2: 1}, 0) RP.v_eval_n(SB_rules, 0)
- values(M, m, l, u, ll, coeffs, initial_values, last_value_needed, offset, inhomogeneities)[source]¶
Determine enough values of the corresponding recursive sequence by applying the recurrence relations given in
RegularSequenceRing.from_recurrence()
to the values given ininitial_values
.INPUT:
M
,m
,l
,u
,offset
– parameters of the recursive sequences, see [HKL2022], Definition 3.1ll
– parameter of the resulting linear representation, see [HKL2022], Theorem Acoeffs
– dictionary wherecoeffs[(r, j)]
is the coefficient \(c_{r,j}\) as given inRegularSequenceRing.from_recurrence()
. Ifcoeffs[(r, j)]
is not given for somer
andj
, then it is assumed to be zero.initial_values
– dictionary mapping integersn
to then
-th value of the sequencelast_value_needed
– last initial value which is needed to determine the linear representationinhomogeneities
– dictionary mapping integersr
to the inhomogeneity \(g_r\) as given in [HKL2022], Corollary D
OUTPUT:
A dictionary mapping integers
n
to then
-th value of the sequence for alln
up tolast_value_needed
.EXAMPLES:
Stern–Brocot Sequence:
sage: from sage.combinat.regular_sequence import RecurrenceParser sage: RP = RecurrenceParser(2, ZZ) sage: RP.values(M=1, m=0, l=0, u=1, ll=0, ....: coeffs={(0, 0): 1, (1, 0): 1, (1, 1): 1}, ....: initial_values={0: 0, 1: 1, 2: 1}, last_value_needed=20, ....: offset=0, inhomogeneities={}) {0: 0, 1: 1, 2: 1, 3: 2, 4: 1, 5: 3, 6: 2, 7: 3, 8: 1, 9: 4, 10: 3, 11: 5, 12: 2, 13: 5, 14: 3, 15: 4, 16: 1, 17: 5, 18: 4, 19: 7, 20: 3}
>>> from sage.all import * >>> from sage.combinat.regular_sequence import RecurrenceParser >>> RP = RecurrenceParser(Integer(2), ZZ) >>> RP.values(M=Integer(1), m=Integer(0), l=Integer(0), u=Integer(1), ll=Integer(0), ... coeffs={(Integer(0), Integer(0)): Integer(1), (Integer(1), Integer(0)): Integer(1), (Integer(1), Integer(1)): Integer(1)}, ... initial_values={Integer(0): Integer(0), Integer(1): Integer(1), Integer(2): Integer(1)}, last_value_needed=Integer(20), ... offset=Integer(0), inhomogeneities={}) {0: 0, 1: 1, 2: 1, 3: 2, 4: 1, 5: 3, 6: 2, 7: 3, 8: 1, 9: 4, 10: 3, 11: 5, 12: 2, 13: 5, 14: 3, 15: 4, 16: 1, 17: 5, 18: 4, 19: 7, 20: 3}
from sage.combinat.regular_sequence import RecurrenceParser RP = RecurrenceParser(2, ZZ) RP.values(M=1, m=0, l=0, u=1, ll=0, coeffs={(0, 0): 1, (1, 0): 1, (1, 1): 1}, initial_values={0: 0, 1: 1, 2: 1}, last_value_needed=20, offset=0, inhomogeneities={})
- class sage.combinat.regular_sequence.RegularSequence(parent, mu, left=None, right=None)[source]¶
Bases:
RecognizableSeries
A \(k\)-regular sequence.
INPUT:
parent
– an instance ofRegularSequenceRing
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 alsomu()
.left
– (default:None
) a vector. When evaluating the sequence, this vector is multiplied from the left to the matrix product. IfNone
, 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. IfNone
, then this multiplication is skipped.
When created via the parent
RegularSequenceRing
, then the following option is available.allow_degenerated_sequence
– boolean (default:False
); if set, then there will be no check if the input is a degenerated sequence (seeis_degenerated()
). Otherwise the input is checked and aDegeneratedSequenceError
is raised if such a sequence is detected.
EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: S = Seq2((Matrix([[3, 0], [6, 1]]), Matrix([[0, 1], [-6, 5]])), ....: vector([1, 0]), vector([0, 1])); S 2-regular sequence 0, 1, 3, 5, 9, 11, 15, 19, 27, 29, ...
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> S = Seq2((Matrix([[Integer(3), Integer(0)], [Integer(6), Integer(1)]]), Matrix([[Integer(0), Integer(1)], [-Integer(6), Integer(5)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(0), Integer(1)])); S 2-regular sequence 0, 1, 3, 5, 9, 11, 15, 19, 27, 29, ...
Seq2 = RegularSequenceRing(2, ZZ) S = Seq2((Matrix([[3, 0], [6, 1]]), Matrix([[0, 1], [-6, 5]])), vector([1, 0]), vector([0, 1])); S
We can access the coefficients of a sequence by
sage: S[5] 11
>>> from sage.all import * >>> S[Integer(5)] 11
S[5]
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]
>>> from sage.all import * >>> from itertools import islice >>> list(islice(S, Integer(10))) [0, 1, 3, 5, 9, 11, 15, 19, 27, 29]
from itertools import islice list(islice(S, 10))
See also
- backward_differences(**kwds)[source]¶
Return the sequence of backward differences of this \(k\)-regular sequence.
INPUT:
minimize
– (default:None
) a boolean orNone
. IfTrue
, thenminimized()
is called after the operation, ifFalse
, then not. If this argument isNone
, then the default specified by the parent’sminimize_results
is used.
OUTPUT: a
RegularSequence
Note
The coefficient to the index \(-1\) is \(0\).
EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: C = Seq2((Matrix([[2, 0], [2, 1]]), Matrix([[0, 1], [-2, 3]])), ....: vector([1, 0]), vector([0, 1])) sage: C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... sage: C.backward_differences() 2-regular sequence 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> C = Seq2((Matrix([[Integer(2), Integer(0)], [Integer(2), Integer(1)]]), Matrix([[Integer(0), Integer(1)], [-Integer(2), Integer(3)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(0), Integer(1)])) >>> C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... >>> C.backward_differences() 2-regular sequence 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
Seq2 = RegularSequenceRing(2, ZZ) C = Seq2((Matrix([[2, 0], [2, 1]]), Matrix([[0, 1], [-2, 3]])), vector([1, 0]), vector([0, 1])) C C.backward_differences()
sage: E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])), ....: vector([1, 0]), vector([1, 1])) sage: E 2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ... sage: E.backward_differences() 2-regular sequence 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, ...
>>> from sage.all import * >>> E = Seq2((Matrix([[Integer(0), Integer(1)], [Integer(0), Integer(1)]]), Matrix([[Integer(0), Integer(0)], [Integer(0), Integer(1)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(1), Integer(1)])) >>> E 2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ... >>> E.backward_differences() 2-regular sequence 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, ...
E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])), vector([1, 0]), vector([1, 1])) E E.backward_differences()
>>> from sage.all import * >>> E = Seq2((Matrix([[Integer(0), Integer(1)], [Integer(0), Integer(1)]]), Matrix([[Integer(0), Integer(0)], [Integer(0), Integer(1)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(1), Integer(1)])) >>> E 2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ... >>> E.backward_differences() 2-regular sequence 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, ...
E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])), vector([1, 0]), vector([1, 1])) E E.backward_differences()
- coefficient_of_n(n, **kwds)[source]¶
Return the \(n\)-th entry of this sequence.
INPUT:
n
– nonnegative integer
OUTPUT: an element of the universe of the sequence
EXAMPLES:
sage: Seq2 = RegularSequenceRing(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
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> S = Seq2((Matrix([[Integer(1), Integer(0)], [Integer(0), Integer(1)]]), Matrix([[Integer(0), -Integer(1)], [Integer(1), Integer(2)]])), ... left=vector([Integer(0), Integer(1)]), right=vector([Integer(1), Integer(0)])) >>> S[Integer(7)] 3
Seq2 = RegularSequenceRing(2, ZZ) S = Seq2((Matrix([[1, 0], [0, 1]]), Matrix([[0, -1], [1, 2]])), left=vector([0, 1]), right=vector([1, 0])) S[7]
This is equivalent to:
sage: S.coefficient_of_n(7) 3
>>> from sage.all import * >>> S.coefficient_of_n(Integer(7)) 3
S.coefficient_of_n(7)
- convolution(*args, **kwds)[source]¶
Return the product of this \(k\)-regular sequence with
other
, where the multiplication is convolution of power series.The operator \(*\) is mapped to
convolution()
.INPUT:
other
– aRegularSequence
minimize
– (default:None
) a boolean orNone
. IfTrue
, thenminimized()
is called after the operation, ifFalse
, then not. If this argument isNone
, then the default specified by the parent’sminimize_results
is used.
OUTPUT: a
RegularSequence
ALGORITHM:
See pdf attached to github pull request #35894 which contains a draft describing the details of the used algorithm.
EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])), ....: vector([1, 0]), vector([1, 1])) sage: E 2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ...
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> E = Seq2((Matrix([[Integer(0), Integer(1)], [Integer(0), Integer(1)]]), Matrix([[Integer(0), Integer(0)], [Integer(0), Integer(1)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(1), Integer(1)])) >>> E 2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ...
Seq2 = RegularSequenceRing(2, ZZ) E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])), vector([1, 0]), vector([1, 1])) E
We can build the convolution (in the sense of power-series) of \(E\) by itself via:
sage: E.convolution(E) 2-regular sequence 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, ...
>>> from sage.all import * >>> E.convolution(E) 2-regular sequence 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, ...
E.convolution(E)
This is the same as using multiplication operator:
sage: E * E 2-regular sequence 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, ...
>>> from sage.all import * >>> E * E 2-regular sequence 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, ...
E * E
Building
partial_sums()
can also be seen as a convolution:sage: o = Seq2.one_hadamard() sage: E * o 2-regular sequence 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, ... sage: E * o == E.partial_sums(include_n=True) True
>>> from sage.all import * >>> o = Seq2.one_hadamard() >>> E * o 2-regular sequence 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, ... >>> E * o == E.partial_sums(include_n=True) True
o = Seq2.one_hadamard() E * o E * o == E.partial_sums(include_n=True)
- forward_differences(**kwds)[source]¶
Return the sequence of forward differences of this \(k\)-regular sequence.
INPUT:
minimize
– (default:None
) a boolean orNone
. IfTrue
, thenminimized()
is called after the operation, ifFalse
, then not. If this argument isNone
, then the default specified by the parent’sminimize_results
is used.
OUTPUT: a
RegularSequence
EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: C = Seq2((Matrix([[2, 0], [2, 1]]), Matrix([[0, 1], [-2, 3]])), ....: vector([1, 0]), vector([0, 1])) sage: C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... sage: C.forward_differences() 2-regular sequence 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> C = Seq2((Matrix([[Integer(2), Integer(0)], [Integer(2), Integer(1)]]), Matrix([[Integer(0), Integer(1)], [-Integer(2), Integer(3)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(0), Integer(1)])) >>> C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... >>> C.forward_differences() 2-regular sequence 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
Seq2 = RegularSequenceRing(2, ZZ) C = Seq2((Matrix([[2, 0], [2, 1]]), Matrix([[0, 1], [-2, 3]])), vector([1, 0]), vector([0, 1])) C C.forward_differences()
sage: E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])), ....: vector([1, 0]), vector([1, 1])) sage: E 2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ... sage: E.forward_differences() 2-regular sequence -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, ...
>>> from sage.all import * >>> E = Seq2((Matrix([[Integer(0), Integer(1)], [Integer(0), Integer(1)]]), Matrix([[Integer(0), Integer(0)], [Integer(0), Integer(1)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(1), Integer(1)])) >>> E 2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ... >>> E.forward_differences() 2-regular sequence -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, ...
E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])), vector([1, 0]), vector([1, 1])) E E.forward_differences()
>>> from sage.all import * >>> E = Seq2((Matrix([[Integer(0), Integer(1)], [Integer(0), Integer(1)]]), Matrix([[Integer(0), Integer(0)], [Integer(0), Integer(1)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(1), Integer(1)])) >>> E 2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ... >>> E.forward_differences() 2-regular sequence -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, ...
E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])), vector([1, 0]), vector([1, 1])) E E.forward_differences()
- is_degenerated()[source]¶
Return whether this \(k\)-regular sequence is degenerated, i.e., whether this \(k\)-regular sequence does not satisfiy \(\mu[0] \mathit{right} = \mathit{right}\).
EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: Seq2((Matrix([2]), Matrix([3])), vector([1]), vector([1])) # indirect doctest Traceback (most recent call last): ... DegeneratedSequenceError: degenerated sequence: mu[0]*right != right. Using such a sequence might lead to wrong results. You can use 'allow_degenerated_sequence=True' followed by a call of method .regenerated() for correcting this. sage: S = Seq2((Matrix([2]), Matrix([3])), vector([1]), vector([1]), ....: allow_degenerated_sequence=True) sage: S 2-regular sequence 1, 3, 6, 9, 12, 18, 18, 27, 24, 36, ... sage: S.is_degenerated() True
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> Seq2((Matrix([Integer(2)]), Matrix([Integer(3)])), vector([Integer(1)]), vector([Integer(1)])) # indirect doctest Traceback (most recent call last): ... DegeneratedSequenceError: degenerated sequence: mu[0]*right != right. Using such a sequence might lead to wrong results. You can use 'allow_degenerated_sequence=True' followed by a call of method .regenerated() for correcting this. >>> S = Seq2((Matrix([Integer(2)]), Matrix([Integer(3)])), vector([Integer(1)]), vector([Integer(1)]), ... allow_degenerated_sequence=True) >>> S 2-regular sequence 1, 3, 6, 9, 12, 18, 18, 27, 24, 36, ... >>> S.is_degenerated() True
Seq2 = RegularSequenceRing(2, ZZ) Seq2((Matrix([2]), Matrix([3])), vector([1]), vector([1])) # indirect doctest S = Seq2((Matrix([2]), Matrix([3])), vector([1]), vector([1]), allow_degenerated_sequence=True) S S.is_degenerated()
sage: C = Seq2((Matrix([[2, 0], [2, 1]]), Matrix([[0, 1], [-2, 3]])), ....: vector([1, 0]), vector([0, 1])) sage: C.is_degenerated() False
>>> from sage.all import * >>> C = Seq2((Matrix([[Integer(2), Integer(0)], [Integer(2), Integer(1)]]), Matrix([[Integer(0), Integer(1)], [-Integer(2), Integer(3)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(0), Integer(1)])) >>> C.is_degenerated() False
C = Seq2((Matrix([[2, 0], [2, 1]]), Matrix([[0, 1], [-2, 3]])), vector([1, 0]), vector([0, 1])) C.is_degenerated()
>>> from sage.all import * >>> C = Seq2((Matrix([[Integer(2), Integer(0)], [Integer(2), Integer(1)]]), Matrix([[Integer(0), Integer(1)], [-Integer(2), Integer(3)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(0), Integer(1)])) >>> C.is_degenerated() False
C = Seq2((Matrix([[2, 0], [2, 1]]), Matrix([[0, 1], [-2, 3]])), vector([1, 0]), vector([0, 1])) C.is_degenerated()
- partial_sums(*args, **kwds)[source]¶
Return the sequence of partial sums of this \(k\)-regular sequence. That is, the \(n\)-th entry of the result is the sum of the first \(n\) entries in the original sequence.
INPUT:
include_n
– boolean (default:False
); if set, then the \(n\)-th entry of the result is the sum of the entries up to index \(n\) (included)minimize
– (default:None
) a boolean orNone
. IfTrue
, thenminimized()
is called after the operation, ifFalse
, then not. If this argument isNone
, then the default specified by the parent’sminimize_results
is used.
OUTPUT: a
RegularSequence
EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])), ....: vector([1, 0]), vector([1, 1])) sage: E 2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ... sage: E.partial_sums() 2-regular sequence 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, ... sage: E.partial_sums(include_n=True) 2-regular sequence 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, ...
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> E = Seq2((Matrix([[Integer(0), Integer(1)], [Integer(0), Integer(1)]]), Matrix([[Integer(0), Integer(0)], [Integer(0), Integer(1)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(1), Integer(1)])) >>> E 2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ... >>> E.partial_sums() 2-regular sequence 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, ... >>> E.partial_sums(include_n=True) 2-regular sequence 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, ...
Seq2 = RegularSequenceRing(2, ZZ) E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])), vector([1, 0]), vector([1, 1])) E E.partial_sums() E.partial_sums(include_n=True)
sage: C = Seq2((Matrix([[2, 0], [2, 1]]), Matrix([[0, 1], [-2, 3]])), ....: vector([1, 0]), vector([0, 1])) sage: C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... sage: C.partial_sums() 2-regular sequence 0, 0, 1, 3, 6, 10, 15, 21, 28, 36, ... sage: C.partial_sums(include_n=True) 2-regular sequence 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, ...
>>> from sage.all import * >>> C = Seq2((Matrix([[Integer(2), Integer(0)], [Integer(2), Integer(1)]]), Matrix([[Integer(0), Integer(1)], [-Integer(2), Integer(3)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(0), Integer(1)])) >>> C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... >>> C.partial_sums() 2-regular sequence 0, 0, 1, 3, 6, 10, 15, 21, 28, 36, ... >>> C.partial_sums(include_n=True) 2-regular sequence 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, ...
C = Seq2((Matrix([[2, 0], [2, 1]]), Matrix([[0, 1], [-2, 3]])), vector([1, 0]), vector([0, 1])) C C.partial_sums() C.partial_sums(include_n=True)
>>> from sage.all import * >>> C = Seq2((Matrix([[Integer(2), Integer(0)], [Integer(2), Integer(1)]]), Matrix([[Integer(0), Integer(1)], [-Integer(2), Integer(3)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(0), Integer(1)])) >>> C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... >>> C.partial_sums() 2-regular sequence 0, 0, 1, 3, 6, 10, 15, 21, 28, 36, ... >>> C.partial_sums(include_n=True) 2-regular sequence 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, ...
C = Seq2((Matrix([[2, 0], [2, 1]]), Matrix([[0, 1], [-2, 3]])), vector([1, 0]), vector([0, 1])) C C.partial_sums() C.partial_sums(include_n=True)
The following linear representation of \(S\) is chosen badly (is degenerated, see
is_degenerated()
), as \(\mu(0)\) applied on \(\mathit{right}\) does not equal \(\mathit{right}\):sage: S = Seq2((Matrix([2]), Matrix([3])), vector([1]), vector([1]), ....: allow_degenerated_sequence=True) sage: S 2-regular sequence 1, 3, 6, 9, 12, 18, 18, 27, 24, 36, ...
>>> from sage.all import * >>> S = Seq2((Matrix([Integer(2)]), Matrix([Integer(3)])), vector([Integer(1)]), vector([Integer(1)]), ... allow_degenerated_sequence=True) >>> S 2-regular sequence 1, 3, 6, 9, 12, 18, 18, 27, 24, 36, ...
S = Seq2((Matrix([2]), Matrix([3])), vector([1]), vector([1]), allow_degenerated_sequence=True) S
Therefore, building partial sums produces a wrong result:
sage: H = S.partial_sums(include_n=True, minimize=False) sage: H 2-regular sequence 1, 5, 16, 25, 62, 80, 98, 125, 274, 310, ... sage: H = S.partial_sums(minimize=False) sage: H 2-regular sequence 0, 2, 10, 16, 50, 62, 80, 98, 250, 274, ...
>>> from sage.all import * >>> H = S.partial_sums(include_n=True, minimize=False) >>> H 2-regular sequence 1, 5, 16, 25, 62, 80, 98, 125, 274, 310, ... >>> H = S.partial_sums(minimize=False) >>> H 2-regular sequence 0, 2, 10, 16, 50, 62, 80, 98, 250, 274, ...
H = S.partial_sums(include_n=True, minimize=False) H H = S.partial_sums(minimize=False) H
We can
guess()
the correct representation:sage: from itertools import islice sage: L = []; ps = 0 sage: for s in islice(S, 110): ....: ps += s ....: L.append(ps) sage: G = Seq2.guess(lambda n: L[n]) sage: G 2-regular sequence 1, 4, 10, 19, 31, 49, 67, 94, 118, 154, ... sage: G.linear_representation() ((1, 0, 0, 0), Finite family {0: [ 0 1 0 0] [ 0 0 0 1] [ -5 5 1 0] [ 10 -17 0 8], 1: [ 0 0 1 0] [ -5 3 3 0] [ -5 0 6 0] [-30 21 10 0]}, (1, 1, 4, 1)) sage: G.minimized().dimension() == G.dimension() True
>>> from sage.all import * >>> from itertools import islice >>> L = []; ps = Integer(0) >>> for s in islice(S, Integer(110)): ... ps += s ... L.append(ps) >>> G = Seq2.guess(lambda n: L[n]) >>> G 2-regular sequence 1, 4, 10, 19, 31, 49, 67, 94, 118, 154, ... >>> G.linear_representation() ((1, 0, 0, 0), Finite family {0: [ 0 1 0 0] [ 0 0 0 1] [ -5 5 1 0] [ 10 -17 0 8], 1: [ 0 0 1 0] [ -5 3 3 0] [ -5 0 6 0] [-30 21 10 0]}, (1, 1, 4, 1)) >>> G.minimized().dimension() == G.dimension() True
from itertools import islice L = []; ps = 0 for s in islice(S, 110): ps += s L.append(ps) G = Seq2.guess(lambda n: L[n]) G G.linear_representation() G.minimized().dimension() == G.dimension()
Or we regenerate the sequence \(S\) first:
sage: S.regenerated().partial_sums(include_n=True, minimize=False) 2-regular sequence 1, 4, 10, 19, 31, 49, 67, 94, 118, 154, ... sage: S.regenerated().partial_sums(minimize=False) 2-regular sequence 0, 1, 4, 10, 19, 31, 49, 67, 94, 118, ...
>>> from sage.all import * >>> S.regenerated().partial_sums(include_n=True, minimize=False) 2-regular sequence 1, 4, 10, 19, 31, 49, 67, 94, 118, 154, ... >>> S.regenerated().partial_sums(minimize=False) 2-regular sequence 0, 1, 4, 10, 19, 31, 49, 67, 94, 118, ...
S.regenerated().partial_sums(include_n=True, minimize=False) S.regenerated().partial_sums(minimize=False)
- regenerated(*args, **kwds)[source]¶
Return a \(k\)-regular sequence that satisfies \(\mu[0] \mathit{right} = \mathit{right}\) with the same values as this sequence.
INPUT:
minimize
– (default:None
) a boolean orNone
. IfTrue
, thenminimized()
is called after the operation, ifFalse
, then not. If this argument isNone
, then the default specified by the parent’sminimize_results
is used.
OUTPUT: a
RegularSequence
ALGORITHM:
Theorem B of [HKL2022] with \(n_0 = 1\).
EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ)
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ)
Seq2 = RegularSequenceRing(2, ZZ)
The following linear representation of \(S\) is chosen badly (is degenerated, see
is_degenerated()
), as \(\mu(0)\) applied on \(\mathit{right}\) does not equal \(\mathit{right}\):sage: S = Seq2((Matrix([2]), Matrix([3])), vector([1]), vector([1]), ....: allow_degenerated_sequence=True) sage: S 2-regular sequence 1, 3, 6, 9, 12, 18, 18, 27, 24, 36, ... sage: S.is_degenerated() True
>>> from sage.all import * >>> S = Seq2((Matrix([Integer(2)]), Matrix([Integer(3)])), vector([Integer(1)]), vector([Integer(1)]), ... allow_degenerated_sequence=True) >>> S 2-regular sequence 1, 3, 6, 9, 12, 18, 18, 27, 24, 36, ... >>> S.is_degenerated() True
S = Seq2((Matrix([2]), Matrix([3])), vector([1]), vector([1]), allow_degenerated_sequence=True) S S.is_degenerated()
However, we can regenerate the sequence \(S\):
sage: H = S.regenerated() sage: H 2-regular sequence 1, 3, 6, 9, 12, 18, 18, 27, 24, 36, ... sage: H.linear_representation() ((1, 0), Finite family {0: [ 0 1] [-2 3], 1: [3 0] [6 0]}, (1, 1)) sage: H.is_degenerated() False
>>> from sage.all import * >>> H = S.regenerated() >>> H 2-regular sequence 1, 3, 6, 9, 12, 18, 18, 27, 24, 36, ... >>> H.linear_representation() ((1, 0), Finite family {0: [ 0 1] [-2 3], 1: [3 0] [6 0]}, (1, 1)) >>> H.is_degenerated() False
H = S.regenerated() H H.linear_representation() H.is_degenerated()
- shift_left(b=1, **kwds)[source]¶
Return the sequence obtained by shifting this \(k\)-regular sequence \(b\) steps to the left.
INPUT:
b
– integerminimize
– (default:None
) a boolean orNone
. IfTrue
, thenminimized()
is called after the operation, ifFalse
, then not. If this argument isNone
, then the default specified by the parent’sminimize_results
is used.
OUTPUT: a
RegularSequence
Note
If \(b\) is negative (i.e., actually a right-shift), then the coefficients when accessing negative indices are \(0\).
EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: C = Seq2((Matrix([[2, 0], [0, 1]]), Matrix([[2, 1], [0, 1]])), ....: vector([1, 0]), vector([0, 1])); C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... sage: C.shift_left() 2-regular sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ... sage: C.shift_left(3) 2-regular sequence 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, ... sage: C.shift_left(-2) 2-regular sequence 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, ...
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> C = Seq2((Matrix([[Integer(2), Integer(0)], [Integer(0), Integer(1)]]), Matrix([[Integer(2), Integer(1)], [Integer(0), Integer(1)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(0), Integer(1)])); C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... >>> C.shift_left() 2-regular sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ... >>> C.shift_left(Integer(3)) 2-regular sequence 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, ... >>> C.shift_left(-Integer(2)) 2-regular sequence 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, ...
Seq2 = RegularSequenceRing(2, ZZ) C = Seq2((Matrix([[2, 0], [0, 1]]), Matrix([[2, 1], [0, 1]])), vector([1, 0]), vector([0, 1])); C C.shift_left() C.shift_left(3) C.shift_left(-2)
- shift_right(b=1, **kwds)[source]¶
Return the sequence obtained by shifting this \(k\)-regular sequence \(b\) steps to the right.
INPUT:
b
– integerminimize
– (default:None
) a boolean orNone
. IfTrue
, thenminimized()
is called after the operation, ifFalse
, then not. If this argument isNone
, then the default specified by the parent’sminimize_results
is used.
OUTPUT: a
RegularSequence
Note
If \(b\) is positive (i.e., indeed a right-shift), then the coefficients when accessing negative indices are \(0\).
EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: C = Seq2((Matrix([[2, 0], [0, 1]]), Matrix([[2, 1], [0, 1]])), ....: vector([1, 0]), vector([0, 1])); C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... sage: C.shift_right() 2-regular sequence 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, ... sage: C.shift_right(3) 2-regular sequence 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, ... sage: C.shift_right(-2) 2-regular sequence 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> C = Seq2((Matrix([[Integer(2), Integer(0)], [Integer(0), Integer(1)]]), Matrix([[Integer(2), Integer(1)], [Integer(0), Integer(1)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(0), Integer(1)])); C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... >>> C.shift_right() 2-regular sequence 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, ... >>> C.shift_right(Integer(3)) 2-regular sequence 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, ... >>> C.shift_right(-Integer(2)) 2-regular sequence 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...
Seq2 = RegularSequenceRing(2, ZZ) C = Seq2((Matrix([[2, 0], [0, 1]]), Matrix([[2, 1], [0, 1]])), vector([1, 0]), vector([0, 1])); C C.shift_right() C.shift_right(3) C.shift_right(-2)
- subsequence(*args, **kwds)[source]¶
Return the subsequence with indices \(an+b\) of this \(k\)-regular sequence.
INPUT:
a
– nonnegative integerb
– integerAlternatively, this is allowed to be a dictionary \(b_j \mapsto c_j\). If so and applied on \(f(n)\), the result will be the sum of all \(c_j \cdot f(an+b_j)\).
minimize
– (default:None
) a boolean orNone
. IfTrue
, thenminimized()
is called after the operation, ifFalse
, then not. If this argument isNone
, then the default specified by the parent’sminimize_results
is used.
OUTPUT: a
RegularSequence
Note
If \(b\) is negative (i.e., right-shift), then the coefficients when accessing negative indices are \(0\).
EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ)
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ)
Seq2 = RegularSequenceRing(2, ZZ)
We consider the sequence \(C\) with \(C(n) = n\) and the following linear representation corresponding to the vector \((n, 1)\):
sage: C = Seq2((Matrix([[2, 0], [0, 1]]), Matrix([[2, 1], [0, 1]])), ....: vector([1, 0]), vector([0, 1])); C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...
>>> from sage.all import * >>> C = Seq2((Matrix([[Integer(2), Integer(0)], [Integer(0), Integer(1)]]), Matrix([[Integer(2), Integer(1)], [Integer(0), Integer(1)]])), ... vector([Integer(1), Integer(0)]), vector([Integer(0), Integer(1)])); C 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...
C = Seq2((Matrix([[2, 0], [0, 1]]), Matrix([[2, 1], [0, 1]])), vector([1, 0]), vector([0, 1])); C
We now extract various subsequences of \(C\):
sage: C.subsequence(2, 0) 2-regular sequence 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, ... sage: S31 = C.subsequence(3, 1); S31 2-regular sequence 1, 4, 7, 10, 13, 16, 19, 22, 25, 28, ... sage: S31.linear_representation() ((1, 0), Finite family {0: [ 0 1] [-2 3], 1: [ 6 -2] [10 -3]}, (1, 1)) sage: C.subsequence(3, 2) 2-regular sequence 2, 5, 8, 11, 14, 17, 20, 23, 26, 29, ...
>>> from sage.all import * >>> C.subsequence(Integer(2), Integer(0)) 2-regular sequence 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, ... >>> S31 = C.subsequence(Integer(3), Integer(1)); S31 2-regular sequence 1, 4, 7, 10, 13, 16, 19, 22, 25, 28, ... >>> S31.linear_representation() ((1, 0), Finite family {0: [ 0 1] [-2 3], 1: [ 6 -2] [10 -3]}, (1, 1)) >>> C.subsequence(Integer(3), Integer(2)) 2-regular sequence 2, 5, 8, 11, 14, 17, 20, 23, 26, 29, ...
C.subsequence(2, 0) S31 = C.subsequence(3, 1); S31 S31.linear_representation() C.subsequence(3, 2)
sage: Srs = C.subsequence(1, -1); Srs 2-regular sequence 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, ... sage: Srs.linear_representation() ((1, 0, 0), Finite family {0: [ 0 1 0] [-2 3 0] [-4 4 1], 1: [ -2 2 0] [ 0 0 1] [ 12 -12 5]}, (0, 0, 1))
>>> from sage.all import * >>> Srs = C.subsequence(Integer(1), -Integer(1)); Srs 2-regular sequence 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, ... >>> Srs.linear_representation() ((1, 0, 0), Finite family {0: [ 0 1 0] [-2 3 0] [-4 4 1], 1: [ -2 2 0] [ 0 0 1] [ 12 -12 5]}, (0, 0, 1))
Srs = C.subsequence(1, -1); Srs Srs.linear_representation()
>>> from sage.all import * >>> Srs = C.subsequence(Integer(1), -Integer(1)); Srs 2-regular sequence 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, ... >>> Srs.linear_representation() ((1, 0, 0), Finite family {0: [ 0 1 0] [-2 3 0] [-4 4 1], 1: [ -2 2 0] [ 0 0 1] [ 12 -12 5]}, (0, 0, 1))
Srs = C.subsequence(1, -1); Srs Srs.linear_representation()
We can build
backward_differences()
manually by passing a dictionary for the parameterb
:sage: Sbd = C.subsequence(1, {0: 1, -1: -1}); Sbd 2-regular sequence 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
>>> from sage.all import * >>> Sbd = C.subsequence(Integer(1), {Integer(0): Integer(1), -Integer(1): -Integer(1)}); Sbd 2-regular sequence 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
Sbd = C.subsequence(1, {0: 1, -1: -1}); Sbd
- transposed(allow_degenerated_sequence=False)[source]¶
Return the transposed sequence.
INPUT:
allow_degenerated_sequence
– boolean (default:False
); if set, then there will be no check if the transposed sequence is a degenerated sequence (seeis_degenerated()
). Otherwise the transposed sequence is checked and aDegeneratedSequenceError
is raised if such a sequence is detected.
OUTPUT: a
RegularSequence
Each of the matrices in
mu
is transposed. Additionally the vectorsleft
andright
are switched.EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: U = Seq2((Matrix([[3, 2], [0, 1]]), Matrix([[2, 0], [1, 3]])), ....: left=vector([0, 1]), right=vector([1, 0]), ....: allow_degenerated_sequence=True) sage: U.is_degenerated() True sage: Ut = U.transposed() sage: Ut.linear_representation() ((1, 0), Finite family {0: [3 0] [2 1], 1: [2 1] [0 3]}, (0, 1)) sage: Ut.is_degenerated() False sage: Ut.transposed() Traceback (most recent call last): ... DegeneratedSequenceError: degenerated sequence: mu[0]*right != right. Using such a sequence might lead to wrong results. You can use 'allow_degenerated_sequence=True' followed by a call of method .regenerated() for correcting this. sage: Utt = Ut.transposed(allow_degenerated_sequence=True) sage: Utt.is_degenerated() True
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> U = Seq2((Matrix([[Integer(3), Integer(2)], [Integer(0), Integer(1)]]), Matrix([[Integer(2), Integer(0)], [Integer(1), Integer(3)]])), ... left=vector([Integer(0), Integer(1)]), right=vector([Integer(1), Integer(0)]), ... allow_degenerated_sequence=True) >>> U.is_degenerated() True >>> Ut = U.transposed() >>> Ut.linear_representation() ((1, 0), Finite family {0: [3 0] [2 1], 1: [2 1] [0 3]}, (0, 1)) >>> Ut.is_degenerated() False >>> Ut.transposed() Traceback (most recent call last): ... DegeneratedSequenceError: degenerated sequence: mu[0]*right != right. Using such a sequence might lead to wrong results. You can use 'allow_degenerated_sequence=True' followed by a call of method .regenerated() for correcting this. >>> Utt = Ut.transposed(allow_degenerated_sequence=True) >>> Utt.is_degenerated() True
Seq2 = RegularSequenceRing(2, ZZ) U = Seq2((Matrix([[3, 2], [0, 1]]), Matrix([[2, 0], [1, 3]])), left=vector([0, 1]), right=vector([1, 0]), allow_degenerated_sequence=True) U.is_degenerated() Ut = U.transposed() Ut.linear_representation() Ut.is_degenerated() Ut.transposed() Utt = Ut.transposed(allow_degenerated_sequence=True) Utt.is_degenerated()
See also
- class sage.combinat.regular_sequence.RegularSequenceRing(k, *args, **kwds)[source]¶
Bases:
RecognizableSeriesSpace
The space of \(k\)-regular Sequences over the given
coefficient_ring
.INPUT:
k
– integer at least \(2\) specifying the basecoefficient_ring
– a (semi-)ringcategory
– (default:None
) the category of this space
EXAMPLES:
sage: RegularSequenceRing(2, ZZ) Space of 2-regular sequences over Integer Ring sage: RegularSequenceRing(3, ZZ) Space of 3-regular sequences over Integer Ring
>>> from sage.all import * >>> RegularSequenceRing(Integer(2), ZZ) Space of 2-regular sequences over Integer Ring >>> RegularSequenceRing(Integer(3), ZZ) Space of 3-regular sequences over Integer Ring
RegularSequenceRing(2, ZZ) RegularSequenceRing(3, ZZ)
See also
- Element[source]¶
alias of
RegularSequence
- from_recurrence(*args, **kwds)[source]¶
Construct the unique \(k\)-regular sequence which fulfills the given recurrence relations and initial values. The recurrence relations have to have the specific shape of \(k\)-recursive sequences as described in [HKL2022], and are either given as symbolic equations, e.g.,
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: var('n') n sage: function('f') f sage: Seq2.from_recurrence([ ....: f(2*n) == 2*f(n), f(2*n + 1) == 3*f(n) + 4*f(n - 1), ....: f(0) == 0, f(1) == 1], f, n) 2-regular sequence 0, 0, 0, 1, 2, 3, 4, 10, 6, 17, ...
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> var('n') n >>> function('f') f >>> Seq2.from_recurrence([ ... f(Integer(2)*n) == Integer(2)*f(n), f(Integer(2)*n + Integer(1)) == Integer(3)*f(n) + Integer(4)*f(n - Integer(1)), ... f(Integer(0)) == Integer(0), f(Integer(1)) == Integer(1)], f, n) 2-regular sequence 0, 0, 0, 1, 2, 3, 4, 10, 6, 17, ...
Seq2 = RegularSequenceRing(2, ZZ) var('n') function('f') Seq2.from_recurrence([ f(2*n) == 2*f(n), f(2*n + 1) == 3*f(n) + 4*f(n - 1), f(0) == 0, f(1) == 1], f, n)
or via the parameters of the \(k\)-recursive sequence as described in the input block below:
sage: Seq2.from_recurrence(M=1, m=0, ....: coeffs={(0, 0): 2, (1, 0): 3, (1, -1): 4}, ....: initial_values={0: 0, 1: 1}) 2-regular sequence 0, 0, 0, 1, 2, 3, 4, 10, 6, 17, ...
>>> from sage.all import * >>> Seq2.from_recurrence(M=Integer(1), m=Integer(0), ... coeffs={(Integer(0), Integer(0)): Integer(2), (Integer(1), Integer(0)): Integer(3), (Integer(1), -Integer(1)): Integer(4)}, ... initial_values={Integer(0): Integer(0), Integer(1): Integer(1)}) 2-regular sequence 0, 0, 0, 1, 2, 3, 4, 10, 6, 17, ...
Seq2.from_recurrence(M=1, m=0, coeffs={(0, 0): 2, (1, 0): 3, (1, -1): 4}, initial_values={0: 0, 1: 1})
INPUT:
Positional arguments:
If the recurrence relations are represented by symbolic equations, then the following arguments are required:
equations
– list of equations where the elements have either the form\(f(k^M n + r) = c_{r,l} f(k^m n + l) + c_{r,l + 1} f(k^m n + l + 1) + ... + c_{r,u} f(k^m n + u)\) for some integers \(0 \leq r < k^M\), \(M > m \geq 0\) and \(l \leq u\), and some coefficients \(c_{r,j}\) from the (semi)ring
coefficients
of the correspondingRegularSequenceRing
, valid for all integers \(n \geq \text{offset}\) for some integer \(\text{offset} \geq \max(-l/k^m, 0)\) (default:0
), and there is an equation of this form (with the same parameters \(M\) and \(m\)) for all \(r\)
or the form
f(k) == t
for some integerk
and somet
from the (semi)ringcoefficient_ring
.
The recurrence relations above uniquely determine a \(k\)-regular sequence; see [HKL2022] for further information.
function
– symbolic functionf
occurring in the equationsvar
– symbolic variable (n
in the above description ofequations
)
The following second representation of the recurrence relations is particularly useful for cases where
coefficient_ring
is not compatible withsage.symbolic.ring.SymbolicRing
. Then the following arguments are required:M
– parameter of the recursive sequences, see [HKL2022], Definition 3.1, as well as in the description ofequations
abovem
– parameter of the recursive sequences, see [HKL2022], Definition 3.1, as well as in the description ofequations
abovecoeffs
– dictionary wherecoeffs[(r, j)]
is the coefficient \(c_{r,j}\) as given in the description ofequations
above. Ifcoeffs[(r, j)]
is not given for somer
andj
, then it is assumed to be zero.initial_values
– dictionary mapping integersn
to then
-th value of the sequence
Optional keyword-only argument:
offset
– integer (default: \(0\)); see explanation ofequations
aboveinhomogeneities
– (default:{}
) a dictionary mapping integersr
to the inhomogeneity \(g_r\) as given in [HKL2022], Corollary D. All inhomogeneities have to be regular sequences fromself
or elements ofcoefficient_ring
.
OUTPUT: a
RegularSequence
EXAMPLES:
Stern–Brocot Sequence:
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: var('n') n sage: function('f') f sage: SB = Seq2.from_recurrence([ ....: f(2*n) == f(n), f(2*n + 1) == f(n) + f(n + 1), ....: f(0) == 0, f(1) == 1], f, n) sage: SB 2-regular sequence 0, 1, 1, 2, 1, 3, 2, 3, 1, 4, ...
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> var('n') n >>> function('f') f >>> SB = Seq2.from_recurrence([ ... f(Integer(2)*n) == f(n), f(Integer(2)*n + Integer(1)) == f(n) + f(n + Integer(1)), ... f(Integer(0)) == Integer(0), f(Integer(1)) == Integer(1)], f, n) >>> SB 2-regular sequence 0, 1, 1, 2, 1, 3, 2, 3, 1, 4, ...
Seq2 = RegularSequenceRing(2, ZZ) var('n') function('f') SB = Seq2.from_recurrence([ f(2*n) == f(n), f(2*n + 1) == f(n) + f(n + 1), f(0) == 0, f(1) == 1], f, n) SB
Number of Odd Entries in Pascal’s Triangle:
sage: Seq2.from_recurrence([ ....: f(2*n) == 3*f(n), f(2*n + 1) == 2*f(n) + f(n + 1), ....: f(0) == 0, f(1) == 1], f, n) 2-regular sequence 0, 1, 3, 5, 9, 11, 15, 19, 27, 29, ...
>>> from sage.all import * >>> Seq2.from_recurrence([ ... f(Integer(2)*n) == Integer(3)*f(n), f(Integer(2)*n + Integer(1)) == Integer(2)*f(n) + f(n + Integer(1)), ... f(Integer(0)) == Integer(0), f(Integer(1)) == Integer(1)], f, n) 2-regular sequence 0, 1, 3, 5, 9, 11, 15, 19, 27, 29, ...
Seq2.from_recurrence([ f(2*n) == 3*f(n), f(2*n + 1) == 2*f(n) + f(n + 1), f(0) == 0, f(1) == 1], f, n)
Number of Unbordered Factors in the Thue–Morse Sequence:
sage: UB = Seq2.from_recurrence([ ....: f(8*n) == 2*f(4*n), ....: f(8*n + 1) == f(4*n + 1), ....: f(8*n + 2) == f(4*n + 1) + f(4*n + 3), ....: f(8*n + 3) == -f(4*n + 1) + f(4*n + 2), ....: f(8*n + 4) == 2*f(4*n + 2), ....: f(8*n + 5) == f(4*n + 3), ....: f(8*n + 6) == -f(4*n + 1) + f(4*n + 2) + f(4*n + 3), ....: f(8*n + 7) == 2*f(4*n + 1) + f(4*n + 3), ....: f(0) == 1, f(1) == 2, f(2) == 2, f(3) == 4, f(4) == 2, ....: f(5) == 4, f(6) == 6, f(7) == 0, f(8) == 4, f(9) == 4, ....: f(10) == 4, f(11) == 4, f(12) == 12, f(13) == 0, f(14) == 4, ....: f(15) == 4, f(16) == 8, f(17) == 4, f(18) == 8, f(19) == 0, ....: f(20) == 8, f(21) == 4, f(22) == 4, f(23) == 8], f, n, offset=3) sage: UB 2-regular sequence 1, 2, 2, 4, 2, 4, 6, 0, 4, 4, ...
>>> from sage.all import * >>> UB = Seq2.from_recurrence([ ... f(Integer(8)*n) == Integer(2)*f(Integer(4)*n), ... f(Integer(8)*n + Integer(1)) == f(Integer(4)*n + Integer(1)), ... f(Integer(8)*n + Integer(2)) == f(Integer(4)*n + Integer(1)) + f(Integer(4)*n + Integer(3)), ... f(Integer(8)*n + Integer(3)) == -f(Integer(4)*n + Integer(1)) + f(Integer(4)*n + Integer(2)), ... f(Integer(8)*n + Integer(4)) == Integer(2)*f(Integer(4)*n + Integer(2)), ... f(Integer(8)*n + Integer(5)) == f(Integer(4)*n + Integer(3)), ... f(Integer(8)*n + Integer(6)) == -f(Integer(4)*n + Integer(1)) + f(Integer(4)*n + Integer(2)) + f(Integer(4)*n + Integer(3)), ... f(Integer(8)*n + Integer(7)) == Integer(2)*f(Integer(4)*n + Integer(1)) + f(Integer(4)*n + Integer(3)), ... f(Integer(0)) == Integer(1), f(Integer(1)) == Integer(2), f(Integer(2)) == Integer(2), f(Integer(3)) == Integer(4), f(Integer(4)) == Integer(2), ... f(Integer(5)) == Integer(4), f(Integer(6)) == Integer(6), f(Integer(7)) == Integer(0), f(Integer(8)) == Integer(4), f(Integer(9)) == Integer(4), ... f(Integer(10)) == Integer(4), f(Integer(11)) == Integer(4), f(Integer(12)) == Integer(12), f(Integer(13)) == Integer(0), f(Integer(14)) == Integer(4), ... f(Integer(15)) == Integer(4), f(Integer(16)) == Integer(8), f(Integer(17)) == Integer(4), f(Integer(18)) == Integer(8), f(Integer(19)) == Integer(0), ... f(Integer(20)) == Integer(8), f(Integer(21)) == Integer(4), f(Integer(22)) == Integer(4), f(Integer(23)) == Integer(8)], f, n, offset=Integer(3)) >>> UB 2-regular sequence 1, 2, 2, 4, 2, 4, 6, 0, 4, 4, ...
UB = Seq2.from_recurrence([ f(8*n) == 2*f(4*n), f(8*n + 1) == f(4*n + 1), f(8*n + 2) == f(4*n + 1) + f(4*n + 3), f(8*n + 3) == -f(4*n + 1) + f(4*n + 2), f(8*n + 4) == 2*f(4*n + 2), f(8*n + 5) == f(4*n + 3), f(8*n + 6) == -f(4*n + 1) + f(4*n + 2) + f(4*n + 3), f(8*n + 7) == 2*f(4*n + 1) + f(4*n + 3), f(0) == 1, f(1) == 2, f(2) == 2, f(3) == 4, f(4) == 2, f(5) == 4, f(6) == 6, f(7) == 0, f(8) == 4, f(9) == 4, f(10) == 4, f(11) == 4, f(12) == 12, f(13) == 0, f(14) == 4, f(15) == 4, f(16) == 8, f(17) == 4, f(18) == 8, f(19) == 0, f(20) == 8, f(21) == 4, f(22) == 4, f(23) == 8], f, n, offset=3) UB
Binary sum of digits \(S(n)\), characterized by the recurrence relations \(S(4n) = S(2n)\), \(S(4n + 1) = S(2n + 1)\), \(S(4n + 2) = S(2n + 1)\) and \(S(4n + 3) = -S(2n) + 2S(2n + 1)\):
sage: S = Seq2.from_recurrence([ ....: f(4*n) == f(2*n), ....: f(4*n + 1) == f(2*n + 1), ....: f(4*n + 2) == f(2*n + 1), ....: f(4*n + 3) == -f(2*n) + 2*f(2*n + 1), ....: f(0) == 0, f(1) == 1], f, n) sage: S 2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ...
>>> from sage.all import * >>> S = Seq2.from_recurrence([ ... f(Integer(4)*n) == f(Integer(2)*n), ... f(Integer(4)*n + Integer(1)) == f(Integer(2)*n + Integer(1)), ... f(Integer(4)*n + Integer(2)) == f(Integer(2)*n + Integer(1)), ... f(Integer(4)*n + Integer(3)) == -f(Integer(2)*n) + Integer(2)*f(Integer(2)*n + Integer(1)), ... f(Integer(0)) == Integer(0), f(Integer(1)) == Integer(1)], f, n) >>> S 2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ...
S = Seq2.from_recurrence([ f(4*n) == f(2*n), f(4*n + 1) == f(2*n + 1), f(4*n + 2) == f(2*n + 1), f(4*n + 3) == -f(2*n) + 2*f(2*n + 1), f(0) == 0, f(1) == 1], f, n) S
In order to check if this sequence is indeed the binary sum of digits, we construct it directly via its linear representation and compare it with
S
:sage: S2 = Seq2( ....: (Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [1, 1]])), ....: left=vector([0, 1]), right=vector([1, 0])) sage: (S - S2).is_trivial_zero() True
>>> from sage.all import * >>> S2 = Seq2( ... (Matrix([[Integer(1), Integer(0)], [Integer(0), Integer(1)]]), Matrix([[Integer(1), Integer(0)], [Integer(1), Integer(1)]])), ... left=vector([Integer(0), Integer(1)]), right=vector([Integer(1), Integer(0)])) >>> (S - S2).is_trivial_zero() True
S2 = Seq2( (Matrix([[1, 0], [0, 1]]), Matrix([[1, 0], [1, 1]])), left=vector([0, 1]), right=vector([1, 0])) (S - S2).is_trivial_zero()
Alternatively, we can also use the simpler but inhomogeneous recurrence relations \(S(2n) = S(n)\) and \(S(2n+1) = S(n) + 1\) via direct parameters:
sage: S3 = Seq2.from_recurrence(M=1, m=0, ....: coeffs={(0, 0): 1, (1, 0): 1}, ....: initial_values={0: 0, 1: 1}, ....: inhomogeneities={1: 1}) sage: S3 2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ... sage: (S3 - S2).is_trivial_zero() True
>>> from sage.all import * >>> S3 = Seq2.from_recurrence(M=Integer(1), m=Integer(0), ... coeffs={(Integer(0), Integer(0)): Integer(1), (Integer(1), Integer(0)): Integer(1)}, ... initial_values={Integer(0): Integer(0), Integer(1): Integer(1)}, ... inhomogeneities={Integer(1): Integer(1)}) >>> S3 2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ... >>> (S3 - S2).is_trivial_zero() True
S3 = Seq2.from_recurrence(M=1, m=0, coeffs={(0, 0): 1, (1, 0): 1}, initial_values={0: 0, 1: 1}, inhomogeneities={1: 1}) S3 (S3 - S2).is_trivial_zero()
Number of Non-Zero Elements in the Generalized Pascal’s Triangle (see [LRS2017]):
sage: Seq2 = RegularSequenceRing(2, QQ) sage: P = Seq2.from_recurrence([ ....: f(4*n) == 5/3*f(2*n) - 1/3*f(2*n + 1), ....: f(4*n + 1) == 4/3*f(2*n) + 1/3*f(2*n + 1), ....: f(4*n + 2) == 1/3*f(2*n) + 4/3*f(2*n + 1), ....: f(4*n + 3) == -1/3*f(2*n) + 5/3*f(2*n + 1), ....: f(0) == 1, f(1) == 2], f, n) sage: P 2-regular sequence 1, 2, 3, 3, 4, 5, 5, 4, 5, 7, ...
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), QQ) >>> P = Seq2.from_recurrence([ ... f(Integer(4)*n) == Integer(5)/Integer(3)*f(Integer(2)*n) - Integer(1)/Integer(3)*f(Integer(2)*n + Integer(1)), ... f(Integer(4)*n + Integer(1)) == Integer(4)/Integer(3)*f(Integer(2)*n) + Integer(1)/Integer(3)*f(Integer(2)*n + Integer(1)), ... f(Integer(4)*n + Integer(2)) == Integer(1)/Integer(3)*f(Integer(2)*n) + Integer(4)/Integer(3)*f(Integer(2)*n + Integer(1)), ... f(Integer(4)*n + Integer(3)) == -Integer(1)/Integer(3)*f(Integer(2)*n) + Integer(5)/Integer(3)*f(Integer(2)*n + Integer(1)), ... f(Integer(0)) == Integer(1), f(Integer(1)) == Integer(2)], f, n) >>> P 2-regular sequence 1, 2, 3, 3, 4, 5, 5, 4, 5, 7, ...
Seq2 = RegularSequenceRing(2, QQ) P = Seq2.from_recurrence([ f(4*n) == 5/3*f(2*n) - 1/3*f(2*n + 1), f(4*n + 1) == 4/3*f(2*n) + 1/3*f(2*n + 1), f(4*n + 2) == 1/3*f(2*n) + 4/3*f(2*n + 1), f(4*n + 3) == -1/3*f(2*n) + 5/3*f(2*n + 1), f(0) == 1, f(1) == 2], f, n) P
Finally, the same sequence can also be obtained via direct parameters without symbolic equations:
sage: Seq2.from_recurrence(M=2, m=1, ....: coeffs={(0, 0): 5/3, (0, 1): -1/3, ....: (1, 0): 4/3, (1, 1): 1/3, ....: (2, 0): 1/3, (2, 1): 4/3, ....: (3, 0): -1/3, (3, 1): 5/3}, ....: initial_values={0: 1, 1: 2}) 2-regular sequence 1, 2, 3, 3, 4, 5, 5, 4, 5, 7, ...
>>> from sage.all import * >>> Seq2.from_recurrence(M=Integer(2), m=Integer(1), ... coeffs={(Integer(0), Integer(0)): Integer(5)/Integer(3), (Integer(0), Integer(1)): -Integer(1)/Integer(3), ... (Integer(1), Integer(0)): Integer(4)/Integer(3), (Integer(1), Integer(1)): Integer(1)/Integer(3), ... (Integer(2), Integer(0)): Integer(1)/Integer(3), (Integer(2), Integer(1)): Integer(4)/Integer(3), ... (Integer(3), Integer(0)): -Integer(1)/Integer(3), (Integer(3), Integer(1)): Integer(5)/Integer(3)}, ... initial_values={Integer(0): Integer(1), Integer(1): Integer(2)}) 2-regular sequence 1, 2, 3, 3, 4, 5, 5, 4, 5, 7, ...
Seq2.from_recurrence(M=2, m=1, coeffs={(0, 0): 5/3, (0, 1): -1/3, (1, 0): 4/3, (1, 1): 1/3, (2, 0): 1/3, (2, 1): 4/3, (3, 0): -1/3, (3, 1): 5/3}, initial_values={0: 1, 1: 2})
- guess(f, n_verify=100, max_exponent=10, sequence=None)[source]¶
Guess a \(k\)-regular sequence whose first terms coincide with \((f(n))_{n\geq0}\).
INPUT:
f
– a function (callable) which determines the sequence. It takes nonnegative integers as an inputn_verify
– (default:100
) a positive integer. The resulting \(k\)-regular sequence coincides with \(f\) on the firstn_verify
terms.max_exponent
– (default:10
) a positive integer specifying the maximum exponent of \(k\) which is tried when guessing the sequence, i.e., relations between \(f(k^t n+r)\) are used for \(0\le t\le \mathtt{max\_exponent}\) and \(0\le r < k^j\)sequence
– (default:None
) a \(k\)-regular sequence used for bootstrapping the guessing by adding information of the linear representation ofsequence
to the guessed representation
OUTPUT: a
RegularSequence
ALGORITHM:
For the purposes of this description, the right vector valued sequence associated with a regular sequence consists of the corresponding matrix product multiplied by the right vector, but without the left vector of the regular sequence.
The algorithm maintains a right vector valued sequence consisting of the right vector valued sequence of the argument
sequence
(replaced by an empty tuple ifsequence
isNone
) plus several components of the shape \(m \mapsto f(k^t\cdot m +r)\) for suitablet
andr
.Implicitly, the algorithm also maintains a \(d \times n_\mathrm{verify}\) matrix
A
(whered
is the dimension of the right vector valued sequence) whose columns are the current right vector valued sequence evaluated at the nonnegative integers less than \(n_\mathrm{verify}\) and ensures that this matrix has full row rank.EXAMPLES:
Binary sum of digits:
sage: @cached_function ....: def s(n): ....: if n == 0: ....: return 0 ....: return s(n//2) + ZZ(is_odd(n)) sage: all(s(n) == sum(n.digits(2)) for n in srange(10)) True sage: [s(n) for n in srange(10)] [0, 1, 1, 2, 1, 2, 2, 3, 1, 2]
>>> from sage.all import * >>> @cached_function ... def s(n): ... if n == Integer(0): ... return Integer(0) ... return s(n//Integer(2)) + ZZ(is_odd(n)) >>> all(s(n) == sum(n.digits(Integer(2))) for n in srange(Integer(10))) True >>> [s(n) for n in srange(Integer(10))] [0, 1, 1, 2, 1, 2, 2, 3, 1, 2]
@cached_function def s(n): if n == 0: return 0 return s(n//2) + ZZ(is_odd(n)) all(s(n) == sum(n.digits(2)) for n in srange(10)) [s(n) for n in srange(10)]
Let us guess a \(2\)-linear representation for \(s(n)\):
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: import logging sage: logging.getLogger().setLevel(logging.INFO) sage: S1 = Seq2.guess(s); S1 INFO:...:including f_{1*m+0} INFO:...:including f_{2*m+1} 2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ... sage: S1.linear_representation() ((1, 0), Finite family {0: [1 0] [0 1], 1: [ 0 1] [-1 2]}, (0, 1))
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> import logging >>> logging.getLogger().setLevel(logging.INFO) >>> S1 = Seq2.guess(s); S1 INFO:...:including f_{1*m+0} INFO:...:including f_{2*m+1} 2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ... >>> S1.linear_representation() ((1, 0), Finite family {0: [1 0] [0 1], 1: [ 0 1] [-1 2]}, (0, 1))
Seq2 = RegularSequenceRing(2, ZZ) import logging logging.getLogger().setLevel(logging.INFO) S1 = Seq2.guess(s); S1 S1.linear_representation()
The
INFO
messages mean that the right vector valued sequence is the sequence \((s(n), s(2n+1))^\top\).We guess again, but this time, we use a constant sequence for bootstrapping the guessing process:
sage: C = Seq2.one_hadamard(); C 2-regular sequence 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ... sage: S2 = Seq2.guess(s, sequence=C); S2 INFO:...:including 2-regular sequence 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ... INFO:...:including f_{1*m+0} 2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ... sage: S2.linear_representation() ((0, 1), Finite family {0: [1 0] [0 1], 1: [1 0] [1 1]}, (1, 0)) sage: S1 == S2 True
>>> from sage.all import * >>> C = Seq2.one_hadamard(); C 2-regular sequence 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ... >>> S2 = Seq2.guess(s, sequence=C); S2 INFO:...:including 2-regular sequence 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ... INFO:...:including f_{1*m+0} 2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ... >>> S2.linear_representation() ((0, 1), Finite family {0: [1 0] [0 1], 1: [1 0] [1 1]}, (1, 0)) >>> S1 == S2 True
C = Seq2.one_hadamard(); C S2 = Seq2.guess(s, sequence=C); S2 S2.linear_representation() S1 == S2
The sequence of all natural numbers:
sage: S = Seq2.guess(lambda n: n); S INFO:...:including f_{1*m+0} INFO:...:including f_{2*m+1} 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... sage: S.linear_representation() ((1, 0), Finite family {0: [2 0] [2 1], 1: [ 0 1] [-2 3]}, (0, 1))
>>> from sage.all import * >>> S = Seq2.guess(lambda n: n); S INFO:...:including f_{1*m+0} INFO:...:including f_{2*m+1} 2-regular sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... >>> S.linear_representation() ((1, 0), Finite family {0: [2 0] [2 1], 1: [ 0 1] [-2 3]}, (0, 1))
S = Seq2.guess(lambda n: n); S S.linear_representation()
The indicator function of the even integers:
sage: S = Seq2.guess(lambda n: ZZ(is_even(n))); S INFO:...:including f_{1*m+0} INFO:...:including f_{2*m+0} 2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ... sage: S.linear_representation() ((1, 0), Finite family {0: [0 1] [0 1], 1: [0 0] [0 1]}, (1, 1))
>>> from sage.all import * >>> S = Seq2.guess(lambda n: ZZ(is_even(n))); S INFO:...:including f_{1*m+0} INFO:...:including f_{2*m+0} 2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ... >>> S.linear_representation() ((1, 0), Finite family {0: [0 1] [0 1], 1: [0 0] [0 1]}, (1, 1))
S = Seq2.guess(lambda n: ZZ(is_even(n))); S S.linear_representation()
The indicator function of the odd integers:
sage: S = Seq2.guess(lambda n: ZZ(is_odd(n))); S INFO:...:including f_{1*m+0} INFO:...:including f_{2*m+1} 2-regular sequence 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ... sage: S.linear_representation() ((1, 0), Finite family {0: [0 0] [0 1], 1: [0 1] [0 1]}, (0, 1)) sage: logging.getLogger().setLevel(logging.WARN)
>>> from sage.all import * >>> S = Seq2.guess(lambda n: ZZ(is_odd(n))); S INFO:...:including f_{1*m+0} INFO:...:including f_{2*m+1} 2-regular sequence 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ... >>> S.linear_representation() ((1, 0), Finite family {0: [0 0] [0 1], 1: [0 1] [0 1]}, (0, 1)) >>> logging.getLogger().setLevel(logging.WARN)
S = Seq2.guess(lambda n: ZZ(is_odd(n))); S S.linear_representation() logging.getLogger().setLevel(logging.WARN)
The following linear representation of \(S\) is chosen badly (is degenerated, see
is_degenerated()
), as \(\mu(0)\) applied on \(\mathit{right}\) does not equal \(\mathit{right}\):sage: S = Seq2((Matrix([2]), Matrix([3])), vector([1]), vector([1]), ....: allow_degenerated_sequence=True) sage: S 2-regular sequence 1, 3, 6, 9, 12, 18, 18, 27, 24, 36, ... sage: S.is_degenerated() True
>>> from sage.all import * >>> S = Seq2((Matrix([Integer(2)]), Matrix([Integer(3)])), vector([Integer(1)]), vector([Integer(1)]), ... allow_degenerated_sequence=True) >>> S 2-regular sequence 1, 3, 6, 9, 12, 18, 18, 27, 24, 36, ... >>> S.is_degenerated() True
S = Seq2((Matrix([2]), Matrix([3])), vector([1]), vector([1]), allow_degenerated_sequence=True) S S.is_degenerated()
However, we can
guess()
a \(2\)-regular sequence of dimension \(2\):sage: G = Seq2.guess(lambda n: S[n]) sage: G 2-regular sequence 1, 3, 6, 9, 12, 18, 18, 27, 24, 36, ... sage: G.linear_representation() ((1, 0), Finite family {0: [ 0 1] [-2 3], 1: [3 0] [6 0]}, (1, 1)) sage: G == S.regenerated() True
>>> from sage.all import * >>> G = Seq2.guess(lambda n: S[n]) >>> G 2-regular sequence 1, 3, 6, 9, 12, 18, 18, 27, 24, 36, ... >>> G.linear_representation() ((1, 0), Finite family {0: [ 0 1] [-2 3], 1: [3 0] [6 0]}, (1, 1)) >>> G == S.regenerated() True
G = Seq2.guess(lambda n: S[n]) G G.linear_representation() G == S.regenerated()
- one()[source]¶
Return the one element of this
RegularSequenceRing
, i.e. the unique neutral element for \(*\) and also the embedding of the one of the coefficient ring into thisRegularSequenceRing
.EXAMPLES:
sage: Seq2 = RegularSequenceRing(2, ZZ) sage: O = Seq2.one(); O 2-regular sequence 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... sage: O.linear_representation() ((1), Finite family {0: [1], 1: [0]}, (1))
>>> from sage.all import * >>> Seq2 = RegularSequenceRing(Integer(2), ZZ) >>> O = Seq2.one(); O 2-regular sequence 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... >>> O.linear_representation() ((1), Finite family {0: [1], 1: [0]}, (1))
Seq2 = RegularSequenceRing(2, ZZ) O = Seq2.one(); O O.linear_representation()
- some_elements()[source]¶
Return some elements of this \(k\)-regular sequence.
See
TestSuite
for a typical use case.OUTPUT: an iterator
EXAMPLES:
sage: tuple(RegularSequenceRing(2, ZZ).some_elements()) (2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ..., 2-regular sequence 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, ..., 2-regular sequence 1, 1, 0, 1, -1, 0, 0, 1, -2, -1, ..., 2-regular sequence 2, -1, 0, 0, 0, -1, 0, 0, 0, 0, ..., 2-regular sequence 1, 1, 0, 1, 5, 0, 0, 1, -33, 5, ..., 2-regular sequence -5, 0, 0, 0, 0, 0, 0, 0, 0, 0, ..., 2-regular sequence -59, -20, 0, -20, 0, 0, 0, -20, 0, 0, ..., ... 2-regular sequence 2210, 170, 0, 0, 0, 0, 0, 0, 0, 0, ...)
>>> from sage.all import * >>> tuple(RegularSequenceRing(Integer(2), ZZ).some_elements()) (2-regular sequence 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ..., 2-regular sequence 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, ..., 2-regular sequence 1, 1, 0, 1, -1, 0, 0, 1, -2, -1, ..., 2-regular sequence 2, -1, 0, 0, 0, -1, 0, 0, 0, 0, ..., 2-regular sequence 1, 1, 0, 1, 5, 0, 0, 1, -33, 5, ..., 2-regular sequence -5, 0, 0, 0, 0, 0, 0, 0, 0, 0, ..., 2-regular sequence -59, -20, 0, -20, 0, 0, 0, -20, 0, 0, ..., ... 2-regular sequence 2210, 170, 0, 0, 0, 0, 0, 0, 0, 0, ...)
tuple(RegularSequenceRing(2, ZZ).some_elements())
- sage.combinat.regular_sequence.pad_right(T, length, zero=0)[source]¶
Pad
T
to the right by usingzero
to have at least the givenlength
.INPUT:
T
– tuple, list or other iterablelength
– nonnegative integerzero
– (default:0
) the elements to pad with
OUTPUT: an object of the same type as
T
EXAMPLES:
sage: from sage.combinat.regular_sequence import pad_right sage: pad_right((1, 2, 3), 10) (1, 2, 3, 0, 0, 0, 0, 0, 0, 0) sage: pad_right((1, 2, 3), 2) (1, 2, 3) sage: pad_right([(1, 2), (3, 4)], 4, (0, 0)) [(1, 2), (3, 4), (0, 0), (0, 0)]
>>> from sage.all import * >>> from sage.combinat.regular_sequence import pad_right >>> pad_right((Integer(1), Integer(2), Integer(3)), Integer(10)) (1, 2, 3, 0, 0, 0, 0, 0, 0, 0) >>> pad_right((Integer(1), Integer(2), Integer(3)), Integer(2)) (1, 2, 3) >>> pad_right([(Integer(1), Integer(2)), (Integer(3), Integer(4))], Integer(4), (Integer(0), Integer(0))) [(1, 2), (3, 4), (0, 0), (0, 0)]
from sage.combinat.regular_sequence import pad_right pad_right((1, 2, 3), 10) pad_right((1, 2, 3), 2) pad_right([(1, 2), (3, 4)], 4, (0, 0))
- sage.combinat.regular_sequence.value(D, k)[source]¶
Return the value of the expansion with digits \(D\) in base \(k\), i.e.
\[\sum_{0\leq j < \operatorname{len}D} D[j] k^j.\]INPUT:
D
– tuple or other iterablek
– the base
OUTPUT:
An element in the common parent of the base \(k\) and of the entries of \(D\)
EXAMPLES:
sage: from sage.combinat.regular_sequence import value sage: value(42.digits(7), 7) 42
>>> from sage.all import * >>> from sage.combinat.regular_sequence import value >>> value(Integer(42).digits(Integer(7)), Integer(7)) 42
from sage.combinat.regular_sequence import value value(42.digits(7), 7)