Path: blob/master/sage/groups/abelian_gps/abelian_group_element.py
4079 views
"""1Abelian group elements23AUTHORS:45- David Joyner (2006-02); based on free_abelian_monoid_element.py, written by David Kohel.67- David Joyner (2006-05); bug fix in order89- David Joyner (2006-08); bug fix+new method in pow for negatives+fixed corresponding examples.1011- David Joyner (2009-02): Fixed bug in order.1213EXAMPLES: Recall an example from abelian groups.1415::1617sage: F = AbelianGroup(5,[4,5,5,7,8],names = list("abcde"))18sage: (a,b,c,d,e) = F.gens()19sage: x = a*b^2*e*d^20*e^1220sage: x21a*b^2*d^6*e^522sage: x = a^10*b^12*c^13*d^20*e^1223sage: x24a^2*b^2*c^3*d^6*e^425sage: y = a^13*b^19*c^23*d^27*e^7226sage: y27a*b^4*c^3*d^628sage: x*y29a^3*b*c*d^5*e^430sage: x.list()31[2, 2, 3, 6, 4]3233It is important to note that lists are mutable and the returned34list is not a copy. As a result, reassignment of an element of the35list changes the object.3637::3839sage: x.list()[0] = 340sage: x.list()41[3, 2, 3, 6, 4]42sage: x43a^3*b^2*c^3*d^6*e^444"""4546###########################################################################47# Copyright (C) 2006 William Stein <[email protected]>48# Copyright (C) 2006 David Joyner49#50# Distributed under the terms of the GNU General Public License (GPL)51# http://www.gnu.org/licenses/52###########################################################################535455from sage.rings.integer import Integer56from sage.structure.element import MultiplicativeGroupElement57from sage.rings.infinity import infinity58from sage.rings.arith import LCM, GCD5960def is_AbelianGroupElement(x):61"""62Return true if x is an abelian group element, i.e., an element of63type AbelianGroupElement.6465EXAMPLES: Though the integer 3 is in the integers, and the integers66have an abelian group structure, 3 is not an AbelianGroupElement::6768sage: from sage.groups.abelian_gps.abelian_group_element import is_AbelianGroupElement69sage: is_AbelianGroupElement(3)70False71sage: F = AbelianGroup(5, [3,4,5,8,7], 'abcde')72sage: is_AbelianGroupElement(F.0)73True74"""75return isinstance(x, AbelianGroupElement)7677class AbelianGroupElement(MultiplicativeGroupElement):78def __init__(self, F, x):79"""80Create the element x of the AbelianGroup F.8182EXAMPLES::8384sage: F = AbelianGroup(5, [3,4,5,8,7], 'abcde')85sage: a, b, c, d, e = F.gens()86sage: a^2 * b^3 * a^2 * b^-487a*b^388sage: b^-1189b90sage: a^-1191a92sage: a*b in F93True94"""95MultiplicativeGroupElement.__init__(self, F)96self.__repr = None97n = F.ngens()98if isinstance(x, (int, Integer)) and x == 1:99self.__element_vector = [ 0 for i in range(n) ]100elif isinstance(x, list):101if len(x) != n:102raise IndexError, \103"Argument length (= %s) must be %s."%(len(x), n)104self.__element_vector = x105else:106raise TypeError, "Argument x (= %s) is of wrong type."%x107108def _repr_(self):109"""110EXAMPLES::111112sage: AbelianGroupElement(AbelianGroup(1, [1], names='e'),[0])1131114sage: AbelianGroupElement(AbelianGroup(3, [2,3,4], names='e'),[1,2,3])115e0*e1^2*e2^3116"""117s = ""118A = self.parent()119n = A.ngens()120x = A.variable_names()121v = self.__element_vector122for i in range(n):123if v[i] == 0:124continue125elif v[i] == 1:126if len(s) > 0: s += "*"127s += "%s"%x[i]128else:129if len(s) > 0: s += "*"130s += "%s^%s"%(x[i],v[i])131if len(s) == 0: s = str(1)132return s133134def _div_(self, y):135"""136TESTS::137138sage: G.<a,b> = AbelianGroup(2)139sage: a/b140a*b^-1141"""142return self*y.inverse()143144def _mul_(self, y):145#Same as _mul_ in FreeAbelianMonoidElement except that the146#exponents get reduced mod the invariant.147148M = self.parent()149n = M.ngens()150invs = M.invariants()151z = M(1)152xelt = self.__element_vector153yelt = y.__element_vector154zelt = [ xelt[i]+yelt[i] for i in range(len(xelt)) ]155if len(invs) >= n:156L = []157for i in range(len(xelt)):158if invs[i]!=0:159L.append(zelt[i]%invs[i])160if invs[i]==0:161L.append(zelt[i])162z.__element_vector = L163if len(invs) < n:164L1 = []165for i in range(len(invs)):166if invs[i]!=0:167L1.append(zelt[i]%invs[i])168if invs[i]==0:169L1.append(zelt[i])170L2 = [ zelt[i] for i in range(len(invs),len(xelt)) ]171z.__element_vector = L1+L2172return z173174def __pow__(self, _n):175"""176requires that len(invs) = n177"""178n = int(_n)179if n != _n:180raise TypeError, "Argument n (= %s) must be an integer."%n181M = self.parent()182N = M.ngens()183invs = M.invariants()184z = M(1)185for i in xrange(len(invs)):186if invs[i] == 0:187z.__element_vector[i] = self.__element_vector[i]*n188else:189z.__element_vector[i] = (self.__element_vector[i]*n)%invs[i]190return z191192def inverse(self):193"""194Returns the inverse element.195196EXAMPLE::197198sage: G.<a,b> = AbelianGroup(2)199sage: a^-1200a^-1201sage: a.list()202[1, 0]203sage: a.inverse().list()204[-1, 0]205sage: a.inverse()206a^-1207"""208new_list = [-1*n for n in self.list()]209par_inv = self.parent().invariants()210for i in xrange(len(par_inv)):211if par_inv[i] != 0 and new_list[i] < 0:212while new_list[i] < 0:213new_list[i] += abs(par_inv[i])214return AbelianGroupElement(self.parent(), new_list)215216def as_permutation(self):217r"""218Return the element of the permutation group G (isomorphic to the219abelian group A) associated to a in A.220221EXAMPLES::222223sage: G = AbelianGroup(3,[2,3,4],names="abc"); G224Multiplicative Abelian Group isomorphic to C2 x C3 x C4225sage: a,b,c=G.gens()226sage: Gp = G.permutation_group(); Gp227Permutation Group with generators [(1,3,2,4)(5,7,6,8)(9,11,10,12)(13,15,14,16)(17,19,18,20)(21,23,22,24), (1,5,9)(2,6,10)(3,7,11)(4,8,12)(13,17,21)(14,18,22)(15,19,23)(16,20,24), (1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)]228sage: a.as_permutation()229(1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)230sage: ap = a.as_permutation(); ap231(1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)232sage: ap in Gp233True234"""235from sage.groups.perm_gps.permgroup import PermutationGroup236from sage.interfaces.all import gap237G = self.parent()238invs = G.invariants()239s1 = 'A:=AbelianGroup(%s)'%invs240gap.eval(s1)241s2 = 'phi:=IsomorphismPermGroup(A)'242gap.eval(s2)243s3 = "gens := GeneratorsOfGroup(A)"244gap.eval(s3)245L = self.list()246gap.eval("L1:="+str(L))247s4 = "L2:=List([1..%s], i->gens[i]^L1[i]);"%len(L)248gap.eval(s4)249pg = gap.eval("Image(phi,Product(L2))")250Gp = G.permutation_group()251gp = Gp(pg)252return gp253254def list(self):255"""256Return (a reference to) the underlying list used to represent this257element. If this is a word in an abelian group on `n`258generators, then this is a list of nonnegative integers of length259`n`.260261EXAMPLES::262263sage: F = AbelianGroup(5, [3,4,5,8,7], 'abcde')264sage: (a, b, c, d, e) = F.gens()265sage: a.list()266[1, 0, 0, 0, 0]267"""268return self.__element_vector269270def __cmp__(self,other):271if (self.list() != other.list()):272return -1273return 0274275def order(self):276"""277Returns the (finite) order of this element or Infinity if this278element does not have finite order.279280EXAMPLES::281282sage: F = AbelianGroup(3,[7,8,9]); F283Multiplicative Abelian Group isomorphic to C7 x C8 x C9284sage: F.gens()[2].order()2859286sage: a,b,c = F.gens()287sage: (b*c).order()28872289sage: G = AbelianGroup(3,[7,8,9])290sage: type((G.0 * G.1).order())==Integer291True292"""293M = self.parent()294if self == M(1):295return Integer(1)296invs = M.invariants()297if self in M.gens():298o = invs[list(M.gens()).index(self)]299if o == 0:300return infinity301return o302L = list(self.list())303N = LCM([invs[i]//GCD(invs[i],L[i]) for i in range(len(invs)) if L[i]!=0])304if N == 0:305return infinity306else:307return Integer(N)308309def random_element(self):310"""311Return a random element of this dual group.312"""313if not(self.is_finite()):314raise NotImplementedError, "Only implemented for finite groups"315gens = self.gens()316g = gens[0]**0317for i in range(len(gens)):318g = g*gens[i]**(random(gens[i].order()))319return g320321322323def word_problem(self, words):324"""325TODO - this needs a rewrite - see stuff in the matrix_grp326directory.327328G and H are abelian groups, g in G, H is a subgroup of G generated329by a list (words) of elements of G. If self is in H, return the330expression for self as a word in the elements of (words).331332This function does not solve the word problem in Sage. Rather333it pushes it over to GAP, which has optimized (non-deterministic)334algorithms for the word problem.335336.. warning::337338Don't use E (or other GAP-reserved letters) as a generator339name.340341EXAMPLE::342343sage: G = AbelianGroup(2,[2,3], names="xy")344sage: x,y = G.gens()345sage: x.word_problem([x,y])346[[x, 1]]347sage: y.word_problem([x,y])348[[y, 1]]349sage: v = (y*x).word_problem([x,y]); v #random350[[x, 1], [y, 1]]351sage: prod([x^i for x,i in v]) == y*x352True353354"""355from sage.groups.abelian_gps.abelian_group import AbelianGroup, word_problem356return word_problem(words,self)357358359