Skip to content

Commit ceb3c79

Browse files
committed
k-regular sequences: implement convolution
1 parent a57f92d commit ceb3c79

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

src/sage/combinat/k_regular_sequence.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,91 @@ def forward_differences(self, **kwds):
673673
"""
674674
return self.subsequence(1, {1: 1, 0: -1}, **kwds)
675675

676+
@minimize_result
677+
def _mul_(self, other):
678+
r"""
679+
Return the product of this `k`-regular sequence with ``other``,
680+
where the multiplication is convolution.
681+
682+
INPUT:
683+
684+
- ``other`` -- a :class:`kRegularSequence`
685+
686+
- ``minimize`` -- (default: ``None``) a boolean or ``None``.
687+
If ``True``, then :meth:`~RecognizableSeries.minimized` is called after the operation,
688+
if ``False``, then not. If this argument is ``None``, then
689+
the default specified by the parent's ``minimize_results`` is used.
690+
691+
OUTPUT:
692+
693+
A :class:`kRegularSequence`
694+
695+
EXAMPLES::
696+
697+
sage: Seq2 = kRegularSequenceSpace(2, ZZ)
698+
sage: E = Seq2((Matrix([[0, 1], [0, 1]]), Matrix([[0, 0], [0, 1]])),
699+
....: vector([1, 0]), vector([1, 1]))
700+
sage: E
701+
2-regular sequence 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ...
702+
sage: E * E
703+
2-regular sequence 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, ...
704+
705+
sage: o = Seq2.one_hadamard()
706+
sage: E * o
707+
2-regular sequence 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, ...
708+
sage: E * o == E.partial_sums(include_n=True)
709+
True
710+
sage: E * o == o * E
711+
True
712+
"""
713+
from sage.arith.srange import srange
714+
from sage.matrix.constructor import Matrix
715+
from sage.matrix.special import zero_matrix
716+
from sage.modules.free_module_element import vector
717+
718+
P = self.parent()
719+
k = P.k
720+
721+
def tensor_product(left, right):
722+
T = left.tensor_product(right)
723+
T.subdivide()
724+
return T
725+
726+
matrices_0 = {r: sum(tensor_product(self.mu[s], other.mu[r-s])
727+
for s in srange(0, r+1))
728+
for r in P.alphabet()}
729+
matrices_1 = {r: sum(tensor_product(self.mu[s], other.mu[k+r-s])
730+
for s in srange(r+1, k))
731+
for r in P.alphabet()}
732+
left = vector(tensor_product(Matrix(self.left), Matrix(other.left)))
733+
right = vector(tensor_product(Matrix(self.right), Matrix(other.right)))
734+
735+
def linear_representation_morphism_recurrence_order_1(A, B):
736+
r"""
737+
Return the morphism of a linear representation
738+
for the sequence `z_n` satisfying
739+
`z_{2n+r} = A_r z_n + B_r z_{n-1}`.
740+
"""
741+
Z = zero_matrix(A[0].dimensions()[0])
742+
743+
def blocks(r):
744+
upper = list([A[s], B[s], Z]
745+
for s in reversed(srange(max(0, r-2), r+1)))
746+
lower = list([Z, A[s], B[s]]
747+
for s in reversed(srange(k-3+len(upper), k)))
748+
return upper + lower
749+
750+
return {r: Matrix.block(blocks(r)) for r in P.alphabet()}
751+
752+
result = P.element_class(
753+
P,
754+
linear_representation_morphism_recurrence_order_1(matrices_0,
755+
matrices_1),
756+
vector(list(left) + (2*len(list(left)))*[0]),
757+
vector(list(right) + (2*len(list(right)))*[0]))
758+
759+
return result
760+
676761
@minimize_result
677762
def partial_sums(self, include_n=False):
678763
r"""

0 commit comments

Comments
 (0)