r"""
Free abelian monoids
AUTHORS:
- David Kohel (2005-09)
Sage supports free abelian monoids on any prescribed finite number
`n\geq 0` of generators. Use the
``FreeAbelianMonoid`` function to create a free abelian
monoid, and the ``gen`` and ``gens``
functions to obtain the corresponding generators. You can print the
generators as arbitrary strings using the optional
``names`` argument to the
``FreeAbelianMonoid`` function.
EXAMPLE 1: It is possible to create an abelian monoid in zero or
more variables; the syntax T(1) creates the monoid identity
element even in the rank zero case.
::
sage: T = FreeAbelianMonoid(0, '')
sage: T
Free abelian monoid on 0 generators ()
sage: T.gens()
()
sage: T(1)
1
EXAMPLE 2: A free abelian monoid uses a multiplicative
representation of elements, but the underlying representation is
lists of integer exponents.
::
sage: F = FreeAbelianMonoid(5,names='a,b,c,d,e')
sage: (a,b,c,d,e) = F.gens()
sage: a*b^2*e*d
a*b^2*d*e
sage: x = b^2*e*d*a^7
sage: x
a^7*b^2*d*e
sage: x.list()
[7, 2, 0, 1, 1]
"""
from sage.structure.parent_gens import ParentWithGens, normalize_names
from free_abelian_monoid_element import FreeAbelianMonoidElement
from sage.rings.integer import Integer
from sage.structure.factory import UniqueFactory
class FreeAbelianMonoidFactory(UniqueFactory):
"""
Create the free abelian monoid in `n` generators.
INPUT:
- ``n`` - integer
- ``names`` - names of generators
OUTPUT: free abelian monoid
EXAMPLES::
sage: FreeAbelianMonoid(0, '')
Free abelian monoid on 0 generators ()
sage: F = FreeAbelianMonoid(5,names = list("abcde"))
sage: F
Free abelian monoid on 5 generators (a, b, c, d, e)
sage: F(1)
1
sage: (a, b, c, d, e) = F.gens()
sage: mul([ a, b, a, c, b, d, c, d ], F(1))
a^2*b^2*c^2*d^2
sage: a**2 * b**3 * a**2 * b**4
a^4*b^7
::
sage: loads(dumps(F)) is F
True
"""
def create_key(self, n, names):
n = int(n)
names = normalize_names(n, names)
return (n, names)
def create_object(self, version, key):
return FreeAbelianMonoid_class(*key)
FreeAbelianMonoid = FreeAbelianMonoidFactory("FreeAbelianMonoid")
def is_FreeAbelianMonoid(x):
"""
Return True if `x` is a free abelian monoid.
EXAMPLES::
sage: from sage.monoids.free_abelian_monoid import is_FreeAbelianMonoid
sage: is_FreeAbelianMonoid(5)
False
sage: is_FreeAbelianMonoid(FreeAbelianMonoid(7,'a'))
True
sage: is_FreeAbelianMonoid(FreeMonoid(7,'a'))
False
sage: is_FreeAbelianMonoid(FreeMonoid(0,''))
False
"""
return isinstance(x, FreeAbelianMonoid_class)
class FreeAbelianMonoid_class(ParentWithGens):
"""
Free abelian monoid on `n` generators.
"""
def __init__(self, n, names):
if not isinstance(n, (int, long, Integer)):
raise TypeError, "n (=%s) must be an integer."%n
if n < 0:
raise ValueError, "n (=%s) must be nonnegative."%n
self.__ngens = int(n)
assert not names is None
self._assign_names(names)
def __repr__(self):
n = self.__ngens
return "Free abelian monoid on %s generators %s"%(n,self.gens())
def __call__(self, x):
"""
Create an element of this abelian monoid from `x`.
EXAMPLES::
sage: F = FreeAbelianMonoid(10,'x')
sage: F(F.gen(2))
x2
sage: F(1)
1
"""
if isinstance(x, FreeAbelianMonoidElement) and x.parent() == self:
return x
return FreeAbelianMonoidElement(self, x)
def __contains__(self, x):
"""
Return True if `x` is an element of this abelian monoid.
EXAMPLES::
sage: F = FreeAbelianMonoid(10,'b')
sage: F.gen(2)*F.gen(3) in F
True
Note that a monoid on `9` generators is not considered a
submonoid of one on `10` generators.
::
sage: FreeAbelianMonoid(9,'c').gen(2) in F
False
However, multiple calls to the monoid constructor do *not* return
multiple distinct monoids.
::
sage: FreeAbelianMonoid(10,'b').gen(2) in F
True
"""
return isinstance(x, FreeAbelianMonoidElement) and x.parent() == self
def gen(self, i=0):
"""
The `i`-th generator of the abelian monoid.
EXAMPLES::
sage: F = FreeAbelianMonoid(5,'a')
sage: F.gen(0)
a0
sage: F.gen(2)
a2
"""
n = self.__ngens
if i < 0 or not i < n:
raise IndexError, "Argument i (= %s) must be between 0 and %s."%(i, n-1)
x = [ 0 for j in range(n) ]
x[int(i)] = 1
return FreeAbelianMonoidElement(self,x)
def ngens(self):
"""
The number of free generators of the abelian monoid.
EXAMPLES::
sage: F = FreeAbelianMonoid(3000, 'a')
sage: F.ngens()
3000
"""
return self.__ngens