Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/monoids/free_monoid.py
8815 views
1
r"""
2
Free Monoids
3
4
AUTHORS:
5
6
- David Kohel (2005-09)
7
- Simon King (2011-04): Put free monoids into the category framework
8
9
Sage supports free monoids on any prescribed finite number
10
`n\geq 0` of generators. Use the ``FreeMonoid``
11
function to create a free monoid, and the ``gen`` and
12
``gens`` functions to obtain the corresponding
13
generators. You can print the generators as arbitrary strings using
14
the optional ``names`` argument to the
15
``FreeMonoid`` function.
16
"""
17
18
#*****************************************************************************
19
# Copyright (C) 2005 David Kohel <[email protected]>
20
#
21
# Distributed under the terms of the GNU General Public License (GPL)
22
#
23
# This code is distributed in the hope that it will be useful,
24
# but WITHOUT ANY WARRANTY; without even the implied warranty
25
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26
#
27
# See the GNU General Public License for more details; the full text
28
# is available at:
29
#
30
# http://www.gnu.org/licenses/
31
#*****************************************************************************
32
33
from sage.rings.integer import Integer
34
from sage.structure.parent_gens import normalize_names
35
from free_monoid_element import FreeMonoidElement
36
37
from monoid import Monoid_class
38
39
from sage.combinat.words.finite_word import FiniteWord_class
40
41
from sage.structure.factory import UniqueFactory
42
from sage.misc.cachefunc import cached_method
43
44
class FreeMonoidFactory(UniqueFactory):
45
"""
46
Returns a free monoid on `n` generators.
47
48
INPUT:
49
50
51
- ``n`` - integer
52
53
- ``names`` - names of generators
54
55
56
OUTPUT: free abelian monoid
57
58
EXAMPLES::
59
60
sage: FreeMonoid(0,'')
61
Free monoid on 0 generators ()
62
sage: F.<a,b,c,d,e> = FreeMonoid(5); F
63
Free monoid on 5 generators (a, b, c, d, e)
64
sage: F(1)
65
1
66
sage: mul([ a, b, a, c, b, d, c, d ], F(1))
67
a*b*a*c*b*d*c*d
68
"""
69
def create_key(self, n, names):
70
n = int(n)
71
names = normalize_names(n, names)
72
return (n, names)
73
74
def create_object(self, version, key):
75
return FreeMonoid_class(*key)
76
77
FreeMonoid = FreeMonoidFactory("FreeMonoid")
78
79
80
def is_FreeMonoid(x):
81
"""
82
Return True if `x` is a free monoid.
83
84
EXAMPLES::
85
86
sage: from sage.monoids.free_monoid import is_FreeMonoid
87
sage: is_FreeMonoid(5)
88
False
89
sage: is_FreeMonoid(FreeMonoid(7,'a'))
90
True
91
sage: is_FreeMonoid(FreeAbelianMonoid(7,'a'))
92
False
93
sage: is_FreeMonoid(FreeAbelianMonoid(0,''))
94
False
95
"""
96
return isinstance(x, FreeMonoid_class)
97
98
class FreeMonoid_class(Monoid_class):
99
"""
100
The free monoid on `n` generators.
101
"""
102
Element = FreeMonoidElement
103
def __init__(self, n, names=None):
104
"""
105
Create free monoid on `n` generators.
106
107
INPUT:
108
109
- ``n`` - integer
110
111
- ``names`` - (optional) variable name or list of
112
variable names
113
114
115
EXAMPLES::
116
117
sage: F = FreeMonoid(3,'x'); F
118
Free monoid on 3 generators (x0, x1, x2)
119
sage: x = F.gens()
120
sage: x[0]*x[1]**5 * (x[0]*x[2])
121
x0*x1^5*x0*x2
122
sage: F = FreeMonoid(3, 'a')
123
sage: F
124
Free monoid on 3 generators (a0, a1, a2)
125
126
::
127
128
sage: M = FreeMonoid(3, names=['a','b','c'])
129
sage: TestSuite(M).run()
130
"""
131
if not isinstance(n, (int, long, Integer)):
132
raise TypeError, "n (=%s) must be an integer."%n
133
if n < 0:
134
raise ValueError, "n (=%s) must be nonnegative."%n
135
self.__ngens = int(n)
136
#self._assign_names(names)
137
Monoid_class.__init__(self,names)
138
139
def __cmp__(self, other):
140
if not isinstance(other, FreeMonoid_class):
141
return -1
142
c = cmp(self.__ngens, other.__ngens)
143
if c: return c
144
if self.variable_names() == other.variable_names():
145
return 0
146
return 1
147
148
def _repr_(self):
149
return "Free monoid on %s generators %s"%(self.__ngens,self.gens())
150
151
def _element_constructor_(self, x, check=True):
152
"""
153
Return `x` coerced into this free monoid.
154
155
One can create a free monoid element from the integer 1, from a
156
list of 2-tuples of integers `(i,j)`, where `(i,j)`
157
corresponds to `x_i^j`, where `x_i` is the
158
`i`th generator, and words in teh same alphabet as the generators.
159
160
EXAMPLES::
161
162
sage: F = FreeMonoid(3, 'a')
163
sage: F(1)
164
1
165
sage: F(F.gen(0))
166
a0
167
sage: F(0)
168
Traceback (most recent call last):
169
...
170
TypeError: Argument x (= 0) is of the wrong type.
171
172
An example with a list::
173
174
sage: F([(0,5),(1,2),(0,10),(0,2),(1,2)])
175
a0^5*a1^2*a0^12*a1^2
176
177
An example using words::
178
179
sage: F = FreeMonoid(3, 'a,b,c')
180
sage: w = Word('aabbcabac')
181
sage: F(w)
182
a^2*b^2*c*a*b*a*c
183
sage: F(Word([]))
184
1
185
"""
186
## There should really some careful type checking here...
187
if isinstance(x, FreeMonoidElement) and x.parent() is self:
188
return x
189
if isinstance(x, FreeMonoidElement) and x.parent() == self:
190
return self.element_class(self,x._element_list,check)
191
if isinstance(x, (int, long, Integer)) and x == 1:
192
return self.element_class(self, x, check)
193
if isinstance(x, FiniteWord_class):
194
d = self.gens_dict()
195
return self.prod(map(lambda let: d[let], x))
196
if isinstance(x, list):
197
return self.element_class(self, x, check)
198
199
raise TypeError("Argument x (= %s) is of the wrong type."%x)
200
201
def __contains__(self, x):
202
return isinstance(x, FreeMonoidElement) and x.parent() == self
203
204
def gen(self,i=0):
205
"""
206
The `i`-th generator of the monoid.
207
208
INPUT:
209
210
- ``i`` - integer (default: 0)
211
212
EXAMPLES::
213
214
sage: F = FreeMonoid(3, 'a')
215
sage: F.gen(1)
216
a1
217
sage: F.gen(2)
218
a2
219
sage: F.gen(5)
220
Traceback (most recent call last):
221
...
222
IndexError: Argument i (= 5) must be between 0 and 2.
223
"""
224
n = self.__ngens
225
if i < 0 or not i < n:
226
raise IndexError, "Argument i (= %s) must be between 0 and %s."%(i, n-1)
227
return self.element_class(self,[(Integer(i),Integer(1))])
228
229
def ngens(self):
230
"""
231
The number of free generators of the monoid.
232
233
EXAMPLES::
234
235
sage: F = FreeMonoid(2005, 'a')
236
sage: F.ngens()
237
2005
238
"""
239
return self.__ngens
240
241
@cached_method
242
def one_element(self):
243
"""
244
Returns the identity element in this monoid.
245
246
EXAMPLES::
247
248
sage: F = FreeMonoid(2005, 'a')
249
sage: F.one_element()
250
1
251
"""
252
return self(1)
253
254