Path: blob/master/src/sage/algebras/free_algebra_element.py
8818 views
"""1Free algebra elements23AUTHORS:45- David Kohel (2005-09)67TESTS::89sage: R.<x,y> = FreeAlgebra(QQ,2)10sage: x == loads(dumps(x))11True12sage: x*y13x*y14sage: (x*y)^015116sage: (x*y)^317x*y*x*y*x*y18"""1920#*****************************************************************************21# Copyright (C) 2005 David Kohel <[email protected]>22#23# Distributed under the terms of the GNU General Public License (GPL)24#25# This code is distributed in the hope that it will be useful,26# but WITHOUT ANY WARRANTY; without even the implied warranty27# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.28#29# See the GNU General Public License for more details; the full text30# is available at:31#32# http://www.gnu.org/licenses/33#*****************************************************************************3435from sage.misc.misc import repr_lincomb36from sage.monoids.free_monoid_element import FreeMonoidElement37from sage.algebras.algebra_element import AlgebraElement3839class FreeAlgebraElement(AlgebraElement):40"""41A free algebra element.42"""43def __init__(self, A, x):44"""45Create the element ``x`` of the FreeAlgebra ``A``.4647TESTS::4849sage: F.<x,y,z> = FreeAlgebra(QQ, 3)50sage: elt = x^3 * y - z^2*x51sage: TestSuite(elt).run()52"""53if isinstance(x, FreeAlgebraElement):54x = x.__monomial_coefficients55AlgebraElement.__init__(self, A)56R = A.base_ring()57if isinstance(x, AlgebraElement): #and x.parent() == A.base_ring():58self.__monomial_coefficients = { A.monoid()(1):R(x) }59elif isinstance(x, FreeMonoidElement):60self.__monomial_coefficients = { x:R(1) }61elif True:62self.__monomial_coefficients = dict([ (A.monoid()(e1),R(e2)) for e1,e2 in x.items()])63else:64raise TypeError("Argument x (= %s) is of the wrong type."%x)6566def __iter__(self):67"""68Returns an iterator which yields tuples of coefficient and monomial.6970EXAMPLES::7172sage: a = FreeAlgebra(QQ, 5, 'a').gens()73sage: list(3*a[0]*a[1]*a[4]**3*a[0]+1)74[(1, 1), (3, a0*a1*a4^3*a0)]75"""76for (key,val) in self.__monomial_coefficients.iteritems():77yield (val,key)7879def _repr_(self):80"""81Return string representation of self.8283EXAMPLES::8485sage: A.<x,y,z>=FreeAlgebra(ZZ,3)86sage: repr(-x+3*y*z) # indirect doctest87'-x + 3*y*z'8889Trac ticket #11068 enables the use of local variable names::9091sage: from sage.structure.parent_gens import localvars92sage: with localvars(A, ['a','b','c']):93... print -x+3*y*z94...95-a + 3*b*c9697"""98v = sorted(self.__monomial_coefficients.items())99P = self.parent()100M = P.monoid()101from sage.structure.parent_gens import localvars102with localvars(M, P.variable_names(), normalize=False):103x = repr_lincomb(v, strip_one=True)104return x105106def _latex_(self):107r"""108Return latex representation of self.109110EXAMPLES::111112sage: A.<x,y,z>=FreeAlgebra(ZZ,3)113sage: latex(-x+3*y^20*z) # indirect doctest114-x + 3y^{20}z115sage: alpha,beta,gamma=FreeAlgebra(ZZ,3,'alpha,beta,gamma').gens()116sage: latex(alpha-beta)117\alpha - \beta118"""119v = sorted(self.__monomial_coefficients.items())120return repr_lincomb(v, strip_one=True, is_latex=True)121122def __call__(self, *x, **kwds):123"""124EXAMPLES::125126sage: A.<x,y,z>=FreeAlgebra(ZZ,3)127sage: (x+3*y).subs(x=1,y=2,z=14)1287129sage: (2*x+y).subs({x:1,y:z})1302 + z131sage: f=x+3*y+z132sage: f(1,2,1/2)13315/2134sage: f(1,2)135Traceback (most recent call last):136...137ValueError: must specify as many values as generators in parent138139AUTHORS:140141- Joel B. Mohler (2007-10-27)142"""143if len(kwds)>0 and len(x)>0:144raise ValueError("must not specify both a keyword and positional argument")145146if len(kwds)>0:147p = self.parent()148def extract_from(kwds,g):149for x in g:150try:151return kwds[x]152except KeyError:153pass154return None155156x = [extract_from(kwds,(p.gen(i),p.variable_name(i))) for i in range(p.ngens())]157elif isinstance(x[0],tuple):158x = x[0]159160if len(x) != self.parent().ngens():161raise ValueError("must specify as many values as generators in parent")162163# I don't start with 0, because I don't want to preclude evaluation with164#arbitrary objects (e.g. matrices) because of funny coercion.165result = None166for m, c in self.__monomial_coefficients.iteritems():167if result is None:168result = c*m(x)169else:170result += c*m(x)171172if result is None:173return self.parent()(0)174return result175176def __cmp__(left, right):177"""178Compare two free algebra elements with the same parents.179180The ordering is the one on the underlying sorted list of181(monomial,coefficients) pairs.182183EXAMPLES::184185sage: R.<x,y> = FreeAlgebra(QQ,2)186sage: x < y187True188sage: x * y < y * x189True190sage: y * x < x * y191False192"""193v = sorted(left.__monomial_coefficients.items())194w = sorted(right.__monomial_coefficients.items())195return cmp(v, w)196197def _add_(self, y):198"""199Return sum of self and y (another free algebra element with the200same parents)201202EXAMPLES::203204sage: R.<x,y> = FreeAlgebra(QQ,2)205sage: x + y # indirect doctest206x + y207"""208A = self.parent()209## if isinstance(y, (int, long, Integer)):210## z_elt = dict(self.__monomial_coefficients)211## e = A.monoid()(1)212## if z_elt.has_key(e):213## z_elt[e] += A.base_ring()(y)214## else:215## z_elt[e] = A.base_ring()(y)216## z = A(0)217## z.__monomial_coefficients = z_elt218## return z219## if not isinstance(y, FreeAlgebraElement) or not A == y.parent():220## raise TypeError, "Argument y (= %s) is of the wrong type."%y221z_elt = dict(self.__monomial_coefficients)222for m, c in y.__monomial_coefficients.iteritems():223if m in z_elt:224cm = z_elt[m] + c225if cm == 0:226del z_elt[m]227else:228z_elt[m] = cm229else:230z_elt[m] = c231z = A(0)232z.__monomial_coefficients = z_elt233return z234235def _neg_(self):236"""237Return negation of self238239EXAMPLES::240241sage: R.<x,y> = FreeAlgebra(QQ,2)242sage: -(x+y) # indirect doctest243-x - y244"""245y = self.parent()(0)246y_elt = {}247for m, c in self.__monomial_coefficients.iteritems():248y_elt[m] = -c249y.__monomial_coefficients = y_elt250return y251252def _sub_(self, y):253"""254Return self minus y (another free algebra element with the same255parents)256257EXAMPLES::258259sage: R.<x,y> = FreeAlgebra(QQ,2)260sage: x - y # indirect doctest261x - y262"""263A = self.parent()264## if isinstance(y, (int, long, Integer)):265## z_elt = dict(self.__monomial_coefficients)266## e = A.monoid()(1)267## if z_elt.has_key(e):268## z_elt[e] += A.base_ring()(-y)269## else:270## z_elt[e] = A.base_ring()(-y)271## z = A(0)272## z.__monomial_coefficients = z_elt273## return z274## if not isinstance(y, FreeAlgebraElement) or not A == y.parent():275## raise TypeError, "Argument y (= %s) is of the wrong type."%y276z_elt = dict(self.__monomial_coefficients)277for m, c in y.__monomial_coefficients.iteritems():278if m in z_elt:279cm = z_elt[m] - c280if cm == 0:281del z_elt[m]282else:283z_elt[m] = cm284else:285z_elt[m] = -c286z = A(0)287z.__monomial_coefficients = z_elt288return z289290def _mul_(self, y):291"""292Return product of self and y (another free algebra element with the293same parents)294295EXAMPLES::296297sage: A.<x,y,z>=FreeAlgebra(ZZ,3)298sage: (x+y+x*y)*(x+y+1) # indirect doctest299x + y + x^2 + 2*x*y + y*x + y^2 + x*y*x + x*y^2300"""301A = self.parent()302z_elt = {}303for mx, cx in self.__monomial_coefficients.iteritems():304for my, cy in y.__monomial_coefficients.iteritems():305key = mx*my306if key in z_elt:307z_elt[key] += cx*cy308else:309z_elt[key] = cx*cy310z = A(0)311z.__monomial_coefficients = z_elt312return z313314def to_pbw_basis(self):315"""316Return ``self`` in the Poincare-Birkhoff-Witt (PBW) basis.317318EXAMPLES::319320sage: F.<x,y,z> = FreeAlgebra(ZZ, 3)321sage: p = x^2*y + 3*y*x + 2322sage: p.to_pbw_basis()3232*PBW[1] + 3*PBW[y]*PBW[x] + PBW[x^2*y] + PBW[x*y]*PBW[x] + PBW[y]*PBW[x]^2324"""325return self.parent().pbw_element(self)326327328329