Path: blob/master/sage/algebras/free_algebra_element.py
4108 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.46"""47if isinstance(x, FreeAlgebraElement):48x = x.__monomial_coefficients49AlgebraElement.__init__(self, A)50R = A.base_ring()51if isinstance(x, AlgebraElement): #and x.parent() == A.base_ring():52self.__monomial_coefficients = { A.monoid()(1):R(x) }53elif isinstance(x, FreeMonoidElement):54self.__monomial_coefficients = { x:R(1) }55elif True:56self.__monomial_coefficients = dict([ (A.monoid()(e1),R(e2)) for e1,e2 in x.items()])57else:58raise TypeError("Argument x (= %s) is of the wrong type."%x)5960def __iter__(self):61"""62Returns an iterator which yields tuples of coefficient and monomial.6364EXAMPLES::6566sage: a = FreeAlgebra(QQ, 5, 'a').gens()67sage: list(3*a[0]*a[1]*a[4]**3*a[0]+1)68[(1, 1), (3, a0*a1*a4^3*a0)]69"""70for (key,val) in self.__monomial_coefficients.iteritems():71yield (val,key)7273def _repr_(self):74"""75Return string representation of self.7677EXAMPLES::7879sage: A.<x,y,z>=FreeAlgebra(ZZ,3)80sage: repr(-x+3*y*z)81'-x + 3*y*z'8283Trac ticket #11068 enables the use of local variable names::8485sage: from sage.structure.parent_gens import localvars86sage: with localvars(A, ['a','b','c']):87... print -x+3*y*z88...89-a + 3*b*c9091"""92v = sorted(self.__monomial_coefficients.items())93P = self.parent()94M = P.monoid()95from sage.structure.parent_gens import localvars96with localvars(M, P.variable_names(), normalize=False):97x = repr_lincomb(v, strip_one=True)98return x99100def _latex_(self):101r"""102Return latex representation of self.103104EXAMPLES::105106sage: A.<x,y,z>=FreeAlgebra(ZZ,3)107sage: latex(-x+3*y^20*z)108\left(-1\right)x + 3y^{20}z109sage: alpha,beta,gamma=FreeAlgebra(ZZ,3,'alpha,beta,gamma').gens()110sage: latex(alpha-beta)111\alpha + \left(-1\right)\beta112"""113v = sorted(self.__monomial_coefficients.items())114return repr_lincomb(v, strip_one=True, is_latex=True)115116def __call__(self, *x, **kwds):117"""118EXAMPLES::119120sage: A.<x,y,z>=FreeAlgebra(ZZ,3)121sage: (x+3*y).subs(x=1,y=2,z=14)1227123sage: (2*x+y).subs({x:1,y:z})1242 + z125sage: f=x+3*y+z126sage: f(1,2,1/2)12715/2128sage: f(1,2)129Traceback (most recent call last):130...131ValueError: must specify as many values as generators in parent132133AUTHORS:134135- Joel B. Mohler (2007-10-27)136"""137if len(kwds)>0 and len(x)>0:138raise ValueError("must not specify both a keyword and positional argument")139140if len(kwds)>0:141p = self.parent()142def extract_from(kwds,g):143for x in g:144try:145return kwds[x]146except KeyError:147pass148return None149150x = [extract_from(kwds,(p.gen(i),p.variable_name(i))) for i in range(p.ngens())]151elif isinstance(x[0],tuple):152x = x[0]153154if len(x) != self.parent().ngens():155raise ValueError("must specify as many values as generators in parent")156157# I don't start with 0, because I don't want to preclude evaluation with158#arbitrary objects (e.g. matrices) because of funny coercion.159result = None160for m, c in self.__monomial_coefficients.iteritems():161if result is None:162result = c*m(x)163else:164result += c*m(x)165166if result is None:167return self.parent()(0)168return result169170def __cmp__(left, right):171"""172Compare two free algebra elements with the same parents.173174The ordering is the one on the underlying sorted list of175(monomial,coefficients) pairs.176177EXAMPLES::178179sage: R.<x,y> = FreeAlgebra(QQ,2)180sage: x < y181True182sage: x * y < y * x183True184sage: y * x < x * y185False186"""187v = sorted(left.__monomial_coefficients.items())188w = sorted(right.__monomial_coefficients.items())189return cmp(v, w)190191def _add_(self, y):192"""193Return sum of self and y (another free algebra element with the194same parents)195196EXAMPLES::197198sage: R.<x,y> = FreeAlgebra(QQ,2)199sage: x + y200x + y201"""202A = self.parent()203## if isinstance(y, (int, long, Integer)):204## z_elt = dict(self.__monomial_coefficients)205## e = A.monoid()(1)206## if z_elt.has_key(e):207## z_elt[e] += A.base_ring()(y)208## else:209## z_elt[e] = A.base_ring()(y)210## z = A(0)211## z.__monomial_coefficients = z_elt212## return z213## if not isinstance(y, FreeAlgebraElement) or not A == y.parent():214## raise TypeError, "Argument y (= %s) is of the wrong type."%y215z_elt = dict(self.__monomial_coefficients)216for m, c in y.__monomial_coefficients.iteritems():217if m in z_elt:218cm = z_elt[m] + c219if cm == 0:220del z_elt[m]221else:222z_elt[m] = cm223else:224z_elt[m] = c225z = A(0)226z.__monomial_coefficients = z_elt227return z228229def _neg_(self):230"""231Return negation of self232233EXAMPLES::234235sage: R.<x,y> = FreeAlgebra(QQ,2)236sage: -(x+y)237-x - y238"""239y = self.parent()(0)240y_elt = {}241for m, c in self.__monomial_coefficients.iteritems():242y_elt[m] = -c243y.__monomial_coefficients = y_elt244return y245246def _sub_(self, y):247"""248Return self minus y (another free algebra element with the same249parents)250251EXAMPLES::252253sage: R.<x,y> = FreeAlgebra(QQ,2)254sage: x - y255x - y256"""257A = self.parent()258## if isinstance(y, (int, long, Integer)):259## z_elt = dict(self.__monomial_coefficients)260## e = A.monoid()(1)261## if z_elt.has_key(e):262## z_elt[e] += A.base_ring()(-y)263## else:264## z_elt[e] = A.base_ring()(-y)265## z = A(0)266## z.__monomial_coefficients = z_elt267## return z268## if not isinstance(y, FreeAlgebraElement) or not A == y.parent():269## raise TypeError, "Argument y (= %s) is of the wrong type."%y270z_elt = dict(self.__monomial_coefficients)271for m, c in y.__monomial_coefficients.iteritems():272if m in z_elt:273cm = z_elt[m] - c274if cm == 0:275del z_elt[m]276else:277z_elt[m] = cm278else:279z_elt[m] = -c280z = A(0)281z.__monomial_coefficients = z_elt282return z283284def _mul_(self, y):285"""286Return product of self and y (another free algebra element with the287same parents)288289EXAMPLES::290291sage: A.<x,y,z>=FreeAlgebra(ZZ,3)292sage: (x+y+x*y)*(x+y+1)293x + y + x^2 + 2*x*y + y*x + y^2 + x*y*x + x*y^2294"""295A = self.parent()296z_elt = {}297for mx, cx in self.__monomial_coefficients.iteritems():298for my, cy in y.__monomial_coefficients.iteritems():299key = mx*my300if key in z_elt:301z_elt[key] += cx*cy302else:303z_elt[key] = cx*cy304z = A(0)305z.__monomial_coefficients = z_elt306return z307308309