Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
linking morphic.py file to the sage words library
Browse files Browse the repository at this point in the history
  • Loading branch information
seblabbe authored and hedusk committed Feb 16, 2021
1 parent 6587375 commit 20ae22e
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 74 deletions.
98 changes: 95 additions & 3 deletions src/sage/combinat/words/morphic.py
@@ -1,8 +1,25 @@
# -*- coding: utf-8 -*-
r"""
Morphic words
This modules implements morphic words (letter-to-letter coding of fixed
point of a morphism).
AUTHORS:
- Jana Lepsova (January 2021): initial version
EXAMPLES:
Creation of a morphism::
sage: n = WordMorphism(...)
"""

from sage.combinat.words.word_datatypes import WordDatatype
from sage.rings.all import Infinity
from sage.modules.free_module_element import vector
import itertools


class WordDatatype_morphic(WordDatatype):
r"""
Expand Down Expand Up @@ -60,7 +77,6 @@ def __init__(self, parent, morphism, letter, coding=None):
else:
self._coding = coding


def representation(self, n):
"""
EXAMPLES::
Expand Down Expand Up @@ -100,10 +116,86 @@ def representation(self, n):
letter_k = a
k -= 1
return path

def __getitem__(self, key):
"""
EXAMPLES::
sage: print('add doc + examples here')
"""
letter = self._letter
for a in self.representation(key):
letter = (self._morphism(letter))[a]
if key == 0:
return self._coding[letter]
return self._coding[letter]

def __iter__(self):
r"""
Returns an iterator of the letters of the fixed point of ``self``
starting with ``letter``.
If w is the iterated word, then this iterator: outputs the elements
of morphism[ w[i] ], appends morphism[ w[i+1] ] to w, increments i.
INPUT:
- ``self`` - an endomorphism, must be prolongable on
letter
- ``letter`` - a letter in the domain of ``self``
OUTPUT:
- iterator of the fixed point
EXAMPLES::
sage: m = WordMorphism('a->abc,b->,c->')
sage: list(m._fixed_point_iterator('a'))
['a', 'b', 'c']
sage: print('update the examples here')
The morphism must be prolongable on the letter or the iterator will
be empty::
sage: list(m._fixed_point_iterator('b'))
[]
The morphism must be an endomorphism::
sage: m = WordMorphism('a->ac,b->aac')
sage: list(m._fixed_point_iterator('a'))
Traceback (most recent call last):
...
KeyError: 'c'
We check that :trac:`8595` is fixed::
sage: s = WordMorphism({('a', 1):[('a', 1), ('a', 2)], ('a', 2):[('a', 1)]})
sage: it = s._fixed_point_iterator(('a',1))
sage: next(it)
('a', 1)
This shows that ticket :trac:`13668` has been resolved::
sage: s = WordMorphism({1:[1,2],2:[2,3],3:[4],4:[5],5:[6],6:[7],7:[8],8:[9],9:[10],10:[1]})
sage: (s^7).fixed_points()
[word: 1223234234523456234567234567823456789234...,
word: 2,3,4,5,6,7,8,9,10,1,1,2,1,2,2,3,1,2,2,3,2,3,4,1,2,2,3,2,3,4,2,3,4,5,1,2,2,3,2,3,...]
sage: (s^7).reversal().fixed_points()
[]
"""
from itertools import chain
w = iter(self._morphism.image(self._letter))
while True:
try:
for a in self._morphism.image(next(w)):
yield self._coding[a]
else:
next_w = next(w)
w = chain([next_w], w, self._morphism.image(next_w))
except StopIteration:
return


76 changes: 5 additions & 71 deletions src/sage/combinat/words/morphism.py
Expand Up @@ -89,8 +89,6 @@
# https://www.gnu.org/licenses/
# ****************************************************************************

from itertools import chain

from sage.misc.callable_dict import CallableDict
from sage.structure.sage_object import SageObject
from sage.misc.cachefunc import cached_method
Expand Down Expand Up @@ -1729,73 +1727,6 @@ def is_uniform(self, k=None):
else:
return all(w.length() == k for w in self.images())

def _fixed_point_iterator(self, letter):
r"""
Returns an iterator of the letters of the fixed point of ``self``
starting with ``letter``.
If w is the iterated word, then this iterator: outputs the elements
of morphism[ w[i] ], appends morphism[ w[i+1] ] to w, increments i.
INPUT:
- ``self`` - an endomorphism, must be prolongable on
letter
- ``letter`` - a letter in the domain of ``self``
OUTPUT:
- iterator of the fixed point
EXAMPLES::
sage: m = WordMorphism('a->abc,b->,c->')
sage: list(m._fixed_point_iterator('a'))
['a', 'b', 'c']
The morphism must be prolongable on the letter or the iterator will
be empty::
sage: list(m._fixed_point_iterator('b'))
[]
The morphism must be an endomorphism::
sage: m = WordMorphism('a->ac,b->aac')
sage: list(m._fixed_point_iterator('a'))
Traceback (most recent call last):
...
KeyError: 'c'
We check that :trac:`8595` is fixed::
sage: s = WordMorphism({('a', 1):[('a', 1), ('a', 2)], ('a', 2):[('a', 1)]})
sage: it = s._fixed_point_iterator(('a',1))
sage: next(it)
('a', 1)
This shows that ticket :trac:`13668` has been resolved::
sage: s = WordMorphism({1:[1,2],2:[2,3],3:[4],4:[5],5:[6],6:[7],7:[8],8:[9],9:[10],10:[1]})
sage: (s^7).fixed_points()
[word: 1223234234523456234567234567823456789234...,
word: 2,3,4,5,6,7,8,9,10,1,1,2,1,2,2,3,1,2,2,3,2,3,4,1,2,2,3,2,3,4,2,3,4,5,1,2,2,3,2,3,...]
sage: (s^7).reversal().fixed_points()
[]
"""
w = iter(self.image(letter))
while True:
try:
for a in self.image(next(w)):
yield a
else:
next_w = next(w)
w = chain([next_w], w, self.image(next_w))
except StopIteration:
return


def fixed_point(self, letter):
r"""
Returns the fixed point of ``self`` beginning by the given ``letter``.
Expand Down Expand Up @@ -1887,8 +1818,11 @@ def fixed_point(self, letter):

parent = self.codomain()
if self.is_growing(letter):
parent = parent.shift()
return parent(self._fixed_point_iterator(letter))
from sage.combinat.words.word import InfiniteWord_morphic
return InfiniteWord_morphic(parent.shift(), self, letter)
else:
from sage.combinat.words.word import FiniteWord_morphic
return FiniteWord_morphic(parent, self, letter)

def fixed_points(self):
r"""
Expand Down
86 changes: 86 additions & 0 deletions src/sage/combinat/words/word.py
Expand Up @@ -34,6 +34,7 @@
WordDatatype_iter,
WordDatatype_callable_with_caching,
WordDatatype_callable)
from .morphic import WordDatatype_morphic
from sage.monoids.free_monoid_element import FreeMonoidElement

# TODO. Word needs to be replaced by Word. Consider renaming
Expand Down Expand Up @@ -687,3 +688,88 @@ class Word_iter(WordDatatype_iter, Word_class):
"""
pass

##### Morphic Words #####
class Word_morphic(WordDatatype_morphic, Word_class):
r"""
Morphic word of unknown length (finite or infinite).
For such word `w`, type ``w.`` and hit TAB key to see the list of
functions defined on `w`.
Words behave like a Python list : they can be sliced using
square braquets to define for example a prefix or a factor.
EXAMPLES::
sage: w = 34
sage: w
word: 1149114911491149114911491149114911491149...
TESTS:
Pickle is not supported for word of unknown length defined by an iterator::
sage: dumps(w)
sage:
Traceback (most recent call last):
...
TypeError: can...t...pickle...generator...object...
"""
pass

class FiniteWord_morphic(WordDatatype_morphic, FiniteWord_class):
r"""
Finite morphic word.
For such word `w`, type ``w.`` and hit TAB key to see the list of
functions defined on `w`.
EXAMPLES::
sage: print('update')
TESTS::
sage: print('update')
sage: w = 22222
sage: type(w)
<class 'sage.combinat.words.word.FiniteWord_iter'>
sage: z = loads(dumps(w))
sage: w == z
True
sage: type(z)
<class 'sage.combinat.words.word.FiniteWord_list'>
"""
pass

class InfiniteWord_morphic(WordDatatype_morphic, InfiniteWord_class):
r"""
Morphic word of infinite length.
For such word `w`, type ``w.`` and hit TAB key to see the list of
functions defined on `w`.
Infinite words behave like a Python list : they can be sliced using
square braquets to define for example a prefix or a factor.
EXAMPLES::
sage: m = WordMorphism('a->ab,b->a')
sage: w = m.fixed_point('a')
sage: w
TESTS:
Pickle is not supported for infinite word defined by an iterator::
sage: dumps(w)
sage: dumps(w)
Traceback (most recent call last):
...
TypeError: can...t...pickle...generator...object...
"""
pass

0 comments on commit 20ae22e

Please sign in to comment.