def free(index_set=None, names=None, **kwds): r""" Return the free commutative group. INPUT: - ``index_set`` -- (optional) an index set for the generators; if an integer, then this represents `\{0, 1, \ldots, n-1\}` - ``names`` -- a string or list/tuple/iterable of strings (default: ``'x'``); the generator names or name prefix EXAMPLES:: sage: Groups.Commutative.free(index_set=ZZ) Free abelian group indexed by Integer Ring sage: Groups().Commutative().free(ZZ) Free abelian group indexed by Integer Ring sage: Groups().Commutative().free(5) Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z sage: F.<x,y,z> = Groups().Commutative().free(); F Multiplicative Abelian group isomorphic to Z x Z x Z """ from sage.rings.all import ZZ if names is not None: if isinstance(names, str): if ',' not in names and index_set in ZZ: names = [names + repr(i) for i in range(index_set)] else: names = names.split(',') names = tuple(names) if index_set is None: index_set = ZZ(len(names)) if index_set in ZZ: from sage.groups.abelian_gps.abelian_group import AbelianGroup return AbelianGroup(index_set, names=names, **kwds) if index_set in ZZ: from sage.groups.abelian_gps.abelian_group import AbelianGroup return AbelianGroup(index_set, **kwds) from sage.groups.indexed_free_group import IndexedFreeAbelianGroup return IndexedFreeAbelianGroup(index_set, names=names, **kwds)
def FreeGroup(n=None, names='x', index_set=None, abelian=False, **kwds): """ Construct a Free Group. INPUT: - ``n`` -- integer or ``None`` (default). The number of generators. If not specified the ``names`` are counted. - ``names`` -- string or list/tuple/iterable of strings (default: ``'x'``). The generator names or name prefix. - ``index_set`` -- (optional) an index set for the generators; if specified then the optional keyword ``abelian`` can be used - ``abelian`` -- (default: ``False``) whether to construct a free abelian group or a free group .. NOTE:: If you want to create a free group, it is currently preferential to use ``Groups().free(...)`` as that does not load GAP. EXAMPLES:: sage: from train_track import * sage: G.<a,b> = FreeGroup(); G Free Group on generators {a, b} sage: H = FreeGroup('a, b') sage: G is H True sage: FreeGroup(0) Free Group on generators {} The entry can be either a string with the names of the generators, or the number of generators and the prefix of the names to be given. The default prefix is ``'x'`` :: sage: FreeGroup(3) Free Group on generators {x0, x1, x2} sage: FreeGroup(3, 'g') Free Group on generators {g0, g1, g2} sage: FreeGroup() Free Group on generators {x} We give two examples using the ``index_set`` option:: sage: FreeGroup(index_set=ZZ) Free group indexed by Integer Ring sage: FreeGroup(index_set=ZZ, abelian=True) Free abelian group indexed by Integer Ring TESTS:: sage: G1 = FreeGroup(2, 'a,b') sage: G2 = FreeGroup('a,b') sage: G3.<a,b> = FreeGroup() sage: G1 is G2, G2 is G3 (True, True) """ # Support Freegroup('a,b') syntax if n is not None: try: n = Integer(n) except TypeError: names = n n = None # derive n from counting names if n is None: if isinstance(names, six.string_types): n = len(names.split(',')) else: names = list(names) n = len(names) from sage.structure.category_object import normalize_names names = normalize_names(n, names) if index_set is not None or abelian: if abelian: from sage.groups.indexed_free_group import IndexedFreeAbelianGroup return IndexedFreeAbelianGroup(index_set, names=names, **kwds) from sage.groups.indexed_free_group import IndexedFreeGroup return IndexedFreeGroup(index_set, names=names, **kwds) from train_track.free_group import FreeGroup_class return FreeGroup_class(names)