[docs]defflatten(cls,seq):"""Return commutative, noncommutative and order arguments by combining related terms. Notes ===== * In an expression like ``a*b*c``, python process this through sympy as ``Mul(Mul(a, b), c)``. This can have undesirable consequences. - Sometimes terms are not combined as one would like: {c.f. http://code.google.com/p/sympy/issues/detail?id=1497} >>> from sympy import Mul, sqrt >>> from sympy.abc import x, y, z >>> 2*(x + 1) # this is the 2-arg Mul behavior 2*x + 2 >>> y*(x + 1)*2 2*y*(x + 1) >>> 2*(x + 1)*y # 2-arg result will be obtained first y*(2*x + 2) >>> Mul(2, x + 1, y) # all 3 args simultaneously processed 2*y*(x + 1) >>> 2*((x + 1)*y) # parentheses can control this behavior 2*y*(x + 1) Powers with compound bases may not find a single base to combine with unless all arguments are processed at once. Post-processing may be necessary in such cases. {c.f. http://code.google.com/p/sympy/issues/detail?id=2629} >>> a = sqrt(x*sqrt(y)) >>> a**3 (x*sqrt(y))**(3/2) >>> Mul(a,a,a) (x*sqrt(y))**(3/2) >>> a*a*a x*sqrt(y)*sqrt(x*sqrt(y)) >>> _.subs(a.base, z).subs(z, a.base) (x*sqrt(y))**(3/2) - If more than two terms are being multiplied then all the previous terms will be re-processed for each new argument. So if each of ``a``, ``b`` and ``c`` were :class:`Mul` expression, then ``a*b*c`` (or building up the product with ``*=``) will process all the arguments of ``a`` and ``b`` twice: once when ``a*b`` is computed and again when ``c`` is multiplied. Using ``Mul(a, b, c)`` will process all arguments once. * The results of Mul are cached according to arguments, so flatten will only be called once for ``Mul(a, b, c)``. If you can structure a calculation so the arguments are most likely to be repeats then this can save time in computing the answer. For example, say you had a Mul, M, that you wished to divide by ``d[i]`` and multiply by ``n[i]`` and you suspect there are many repeats in ``n``. It would be better to compute ``M*n[i]/d[i]`` rather than ``M/d[i]*n[i]`` since every time n[i] is a repeat, the product, ``M*n[i]`` will be returned without flattening -- the cached value will be returned. If you divide by the ``d[i]`` first (and those are more unique than the ``n[i]``) then that will create a new Mul, ``M/d[i]`` the args of which will be traversed again when it is multiplied by ``n[i]``. {c.f. http://code.google.com/p/sympy/issues/detail?id=2607} This consideration is moot if the cache is turned off. NB -- The validity of the above notes depends on the implementation details of Mul and flatten which may change at any time. Therefore, you should only consider them when your code is highly performance sensitive. Removal of 1 from the sequence is already handled by AssocOp.__new__. """rv=Noneiflen(seq)==2:a,b=seqifb.is_Rational:a,b=b,aassertnotaisS.Oneifnota.is_zeroanda.is_Rational:r,b=b.as_coeff_Mul()ifb.is_Add:ifrisnotS.One:# 2-arg hack# leave the Mul as a Mulrv=[cls(a*r,b,evaluate=False)],[],Noneelifb.is_commutative:ifaisS.One:rv=[b],[],Noneelse:r,b=b.as_coeff_Add()bargs=[_keep_coeff(a,bi)forbiinAdd.make_args(b)]_addsort(bargs)ar=a*rifar:bargs.insert(0,ar)bargs=[Add._from_args(bargs)]rv=bargs,[],Noneifrv:returnrv# apply associativity, separate commutative part of seqc_part=[]# out: commutative factorsnc_part=[]# out: non-commutative factorsnc_seq=[]coeff=S.One# standalone term# e.g. 3 * ...c_powers=[]# (base,exp) n# e.g. (x,n) for xnum_exp=[]# (num-base, exp) y# e.g. (3, y) for ... * 3 * ...neg1e=S.Zero# exponent on -1 extracted from Number-based Pow and Ipnum_rat={}# (num-base, Rat-exp) 1/2# e.g. (3, 1/2) for ... * 3 * ...order_symbols=None# --- PART 1 ---## "collect powers and coeff":## o coeff# o c_powers# o num_exp# o neg1e# o pnum_rat## NOTE: this is optimized for all-objects-are-commutative caseforoinseq:# O(x)ifo.is_Order:o,order_symbols=o.as_expr_variables(order_symbols)# Mul([...])ifo.is_Mul:ifo.is_commutative:seq.extend(o.args)# XXX zerocopy?else:# NCMul can have commutative parts as wellforqino.args:ifq.is_commutative:seq.append(q)else:nc_seq.append(q)# append non-commutative marker, so we don't forget to# process scheduled non-commutative objectsseq.append(NC_Marker)continue# 3elifo.is_Number:ifoisS.NaNorcoeffisS.ComplexInfinityandoisS.Zero:# we know for sure the result will be nanreturn[S.NaN],[],Noneelifcoeff.is_Number:# it could be zoocoeff*=oifcoeffisS.NaN:# we know for sure the result will be nanreturn[S.NaN],[],NonecontinueelifoisS.ComplexInfinity:ifnotcoeff:# 0 * zoo = NaNreturn[S.NaN],[],NoneifcoeffisS.ComplexInfinity:# zoo * zoo = zooreturn[S.ComplexInfinity],[],Nonecoeff=S.ComplexInfinitycontinueelifoisS.ImaginaryUnit:neg1e+=S.Halfcontinueelifo.is_commutative:# e# o = bb,e=o.as_base_exp()# y# 3ifo.is_Pow:ifb.is_Number:# get all the factors with numeric base so they can be# combined below, but don't combine negatives unless# the exponent is an integerife.is_Rational:ife.is_Integer:coeff*=Pow(b,e)# it is an unevaluated powercontinueelife.is_negative:# also a sign of an unevaluated powerseq.append(Pow(b,e))continueelifb.is_negative:neg1e+=eb=-bifbisnotS.One:pnum_rat.setdefault(b,[]).append(e)continueelifb.is_positiveore.is_integer:num_exp.append((b,e))continueelifbisS.ImaginaryUnitande.is_Rational:neg1e+=e/2continuec_powers.append((b,e))# NON-COMMUTATIVE# TODO: Make non-commutative exponents not combine automaticallyelse:ifoisnotNC_Marker:nc_seq.append(o)# process nc_seq (if any)whilenc_seq:o=nc_seq.pop(0)ifnotnc_part:nc_part.append(o)continue# b c b+c# try to combine last terms: a * a -> ao1=nc_part.pop()b1,e1=o1.as_base_exp()b2,e2=o.as_base_exp()new_exp=e1+e2# Only allow powers to combine if the new exponent is# not an Add. This allow things like a**2*b**3 == a**5# if a.is_commutative == False, but prohibits# a**x*a**y and x**a*x**b from combining (x,y commute).ifb1==b2and(notnew_exp.is_Add):o12=b1**new_exp# now o12 could be a commutative objectifo12.is_commutative:seq.append(o12)continueelse:nc_seq.insert(0,o12)else:nc_part.append(o1)nc_part.append(o)# We do want a combined exponent if it would not be an Add, such as# y 2y 3y# x * x -> x# We determine if two exponents have the same term by using# as_coeff_Mul.## Unfortunately, this isn't smart enough to consider combining into# exponents that might already be adds, so things like:# z - y y# x * x will be left alone. This is because checking every possible# combination can slow things down.# gather exponents of common bases...def_gather(c_powers):new_c_powers=[]common_b={}# b:eforb,einc_powers:co=e.as_coeff_Mul()common_b.setdefault(b,{}).setdefault(co[1],[]).append(co[0])forb,dincommon_b.items():fordi,liind.items():d[di]=Add(*li)forb,eincommon_b.items():fort,cine.items():new_c_powers.append((b,c*t))returnnew_c_powers# in c_powersc_powers=_gather(c_powers)# and in num_expnum_exp=_gather(num_exp)# --- PART 2 ---## o process collected powers (x**0 -> 1; x**1 -> x; otherwise Pow)# o combine collected powers (2**x * 3**x -> 6**x)# with numeric base# ................................# now we have:# - coeff:# - c_powers: (b, e)# - num_exp: (2, e)# - pnum_rat: {(1/3, [1/3, 2/3, 1/4])}# 0 1# x -> 1 x -> xforb,einc_powers:ifeisS.One:ifb.is_Number:coeff*=belse:c_part.append(b)elifeisnotS.Zero:c_part.append(Pow(b,e))# x x x# 2 * 3 -> 6inv_exp_dict={}# exp:Mul(num-bases) x x# e.g. x:6 for ... * 2 * 3 * ...forb,einnum_exp:inv_exp_dict.setdefault(e,[]).append(b)fore,bininv_exp_dict.items():inv_exp_dict[e]=cls(*b)c_part.extend([Pow(b,e)fore,bininv_exp_dict.items()ife])# b, e -> e' = sum(e), b# {(1/5, [1/3]), (1/2, [1/12, 1/4]} -> {(1/3, [1/5, 1/2])}comb_e={}forb,einpnum_rat.items():comb_e.setdefault(Add(*e),[]).append(b)delpnum_rat# process them, reducing exponents to values less than 1# and updating coeff if necessary else adding them to# num_rat for further processingnum_rat=[]fore,bincomb_e.items():b=cls(*b)ife.q==1:coeff*=Pow(b,e)continueife.p>e.q:e_i,ep=divmod(e.p,e.q)coeff*=Pow(b,e_i)e=Rational(ep,e.q)num_rat.append((b,e))delcomb_e# extract gcd of bases in num_rat# 2**(1/3)*6**(1/4) -> 2**(1/3+1/4)*3**(1/4)pnew=defaultdict(list)i=0# steps through num_rat which may growwhilei<len(num_rat):bi,ei=num_rat[i]grow=[]forjinrange(i+1,len(num_rat)):bj,ej=num_rat[j]g=bi.gcd(bj)ifgisnotS.One:# 4**r1*6**r2 -> 2**(r1+r2) * 2**r1 * 3**r2# this might have a gcd with something elsee=ei+ejife.q==1:coeff*=Pow(g,e)else:ife.p>e.q:e_i,ep=divmod(e.p,e.q)# change e in placecoeff*=Pow(g,e_i)e=Rational(ep,e.q)grow.append((g,e))# update the jth itemnum_rat[j]=(bj/g,ej)# update bi that we are checking withbi=bi/gifbiisS.One:breakifbiisnotS.One:obj=Pow(bi,ei)ifobj.is_Number:coeff*=objelse:# changes like sqrt(12) -> 2*sqrt(3)forobjinMul.make_args(obj):ifobj.is_Number:coeff*=objelse:assertobj.is_Powbi,ei=obj.argspnew[ei].append(bi)num_rat.extend(grow)i+=1# combine bases of the new powersfore,binpnew.items():pnew[e]=cls(*b)# handle -1 and Iifneg1e:# treat I as (-1)**(1/2) and compute -1's total exponentp,q=neg1e.as_numer_denom()# if the integer part is odd, extract -1n,p=divmod(p,q)ifn%2:coeff=-coeff# if it's a multiple of 1/2 extract Iifq==2:c_part.append(S.ImaginaryUnit)elifp:# see if there is any positive base this power of# -1 can joinneg1e=Rational(p,q)fore,binpnew.items():ife==neg1eandb.is_positive:pnew[e]=-bbreakelse:# keep it separate; we've already evaluated it as# much as possible so evaluate=Falsec_part.append(Pow(S.NegativeOne,neg1e,evaluate=False))# add all the pnew powersc_part.extend([Pow(b,e)fore,binpnew.items()])# oo, -ooif(coeffisS.Infinity)or(coeffisS.NegativeInfinity):def_handle_for_oo(c_part,coeff_sign):new_c_part=[]fortinc_part:ift.is_positive:continueift.is_negative:coeff_sign*=-1continuenew_c_part.append(t)returnnew_c_part,coeff_signc_part,coeff_sign=_handle_for_oo(c_part,1)nc_part,coeff_sign=_handle_for_oo(nc_part,coeff_sign)coeff*=coeff_sign# zooifcoeffisS.ComplexInfinity:# zoo might be# unbounded_real + bounded_im# bounded_real + unbounded_im# unbounded_real + unbounded_im# and non-zero real or imaginary will not change that status.c_part=[cforcinc_partifnot(c.is_nonzeroandc.is_realisnotNone)]nc_part=[cforcinnc_partifnot(c.is_nonzeroandc.is_realisnotNone)]# 0elifcoeffisS.Zero:# we know for sure the result will be 0return[coeff],[],order_symbols# order commutative part canonically_mulsort(c_part)# current code expects coeff to be always in slot-0ifcoeffisnotS.One:c_part.insert(0,coeff)# we are doneif(notnc_partandlen(c_part)==2andc_part[0].is_Numberandc_part[1].is_Add):# 2*(1+a) -> 2 + 2 * acoeff=c_part[0]c_part=[Add(*[coeff*fforfinc_part[1].args])]returnc_part,nc_part,order_symbols

[docs]defas_two_terms(self):"""Return head and tail of self. This is the most efficient way to get the head and tail of an expression. - if you want only the head, use self.args[0]; - if you want to process the arguments of the tail then use self.as_coef_mul() which gives the head and a tuple containing the arguments of the tail when treated as a Mul. - if you want the coefficient when self is treated as an Add then use self.as_coeff_add()[0] >>> from sympy.abc import x, y >>> (3*x*y).as_two_terms() (3, x*y) """args=self.argsiflen(args)==1:returnS.One,selfeliflen(args)==2:returnargselse:returnargs[0],self._new_rawargs(*args[1:])

[docs]defas_coeff_Mul(self,rational=False):"""Efficiently extract the coefficient of a product. """coeff,args=self.args[0],self.args[1:]ifcoeff.is_Numberandnot(rationalandnotcoeff.is_Rational):iflen(args)==1:returncoeff,args[0]else:returncoeff,self._new_rawargs(*args)else:returnS.One,self

defas_real_imag(self,deep=True,**hints):fromsympyimportexpand_mulother=[]coeff=S.Oneaddterms=S.Oneforainself.args:ifa.is_realora.is_imaginary:coeff*=aelifa.is_commutative:# search for complex conjugate pairs:fori,xinenumerate(other):ifx==a.conjugate():coeff*=C.Abs(x)**2delother[i]breakelse:ifa.is_Add:addterms*=aelse:other.append(a)else:other.append(a)m=self.func(*other)ifhints.get('ignore')==m:returnNoneifaddterms==1:ifm==1:return(C.re(coeff),C.im(coeff))rem,imm=(C.re(m),C.im(m))ifcoeff.is_real:return(coeff*rem,coeff*imm)imco=C.im(coeff)return(-imco*imm,imco*rem)addre,addim=expand_mul(addterms,deep=False).as_real_imag()ifcoeff.is_real:return(coeff*(C.re(m)*addre-C.im(m)*addim),coeff*(C.im(m)*addre+C.re(m)*addim))else:re=-C.im(coeff)*C.im(m)im=C.im(coeff)*C.re(m)return(re*addre-im*addim,re*addim+im*addre)@staticmethoddef_expandsums(sums):""" Helper function for _eval_expand_mul. sums must be a list of instances of Basic. """L=len(sums)ifL==1:returnsums[0].argsterms=[]left=Mul._expandsums(sums[:L//2])right=Mul._expandsums(sums[L//2:])terms=[Mul(a,b)forainleftforbinright]added=Add(*terms)returnAdd.make_args(added)# it may have collapsed down to one termdef_eval_expand_mul(self,**hints):fromsympyimportfraction# Handle things like 1/(x*(x + 1)), which are automatically converted# to 1/x*1/(x + 1)expr=selfn,d=fraction(expr)ifd.is_Mul:n,d=[i._eval_expand_mul(**hints)ifi.is_Mulelseiforiin(n,d)]expr=n/difnotexpr.is_Mul:returnexprplain,sums,rewrite=[],[],Falseforfactorinexpr.args:iffactor.is_Add:sums.append(factor)rewrite=Trueelse:iffactor.is_commutative:plain.append(factor)else:sums.append(Basic(factor))# Wrapperifnotrewrite:returnexprelse:plain=self.func(*plain)ifsums:terms=self.func._expandsums(sums)args=[]forterminterms:t=self.func(plain,term)ift.is_Mulandany(a.is_Addforaint.args):t=t._eval_expand_mul()args.append(t)returnAdd(*args)else:returnplaindef_eval_derivative(self,s):terms=list(self.args)factors=[]foriinxrange(len(terms)):t=terms[i].diff(s)iftisS.Zero:continuefactors.append(self.func(*(terms[:i]+[t]+terms[i+1:])))returnAdd(*factors)def_matches_simple(self,expr,repl_dict):# handle (w*3).matches('x*5') -> {w: x*5/3}coeff,terms=self.as_coeff_Mul()terms=Mul.make_args(terms)iflen(terms)==1:newexpr=self.__class__._combine_inverse(expr,coeff)returnterms[0].matches(newexpr,repl_dict)returndefmatches(self,expr,repl_dict={},old=False):expr=sympify(expr)ifself.is_commutativeandexpr.is_commutative:returnAssocOp._matches_commutative(self,expr,repl_dict,old)elifself.is_commutativeisnotexpr.is_commutative:returnNonec1,nc1=self.args_cnc()c2,nc2=expr.args_cnc()repl_dict=repl_dict.copy()ifc1:ifnotc2:c2=[1]a=self.func(*c1)ifisinstance(a,AssocOp):repl_dict=a._matches_commutative(self.func(*c2),repl_dict,old)else:repl_dict=a.matches(self.func(*c2),repl_dict)ifrepl_dict:a=self.func(*nc1)ifisinstance(a,self.func):repl_dict=a._matches(self.func(*nc2),repl_dict)else:repl_dict=a.matches(self.func(*nc2),repl_dict)returnrepl_dictorNonedef_matches(self,expr,repl_dict={}):# weed out negative one prefixessign=1a,b=self.as_two_terms()ifaisS.NegativeOne:ifb.is_Mul:sign=-signelse:# the remainder, b, is not a Mul anymorereturnb.matches(-expr,repl_dict)expr=sympify(expr)ifexpr.is_Mulandexpr.args[0]isS.NegativeOne:expr=-exprsign=-signifnotexpr.is_Mul:# expr can only match if it matches b and a matches +/- 1iflen(self.args)==2:# quickly test for equalityifb==expr:returna.matches(Rational(sign),repl_dict)# do more expensive matchdd=b.matches(expr,repl_dict)ifddisNone:returnNonedd=a.matches(Rational(sign),dd)returnddreturnNoned=repl_dict.copy()# weed out identical termspp=list(self.args)ee=list(expr.args)forpinself.args:ifpinexpr.args:ee.remove(p)pp.remove(p)# only one symbol left in pattern -> match the remaining expressioniflen(pp)==1andisinstance(pp[0],C.Wild):iflen(ee)==1:d[pp[0]]=sign*ee[0]else:d[pp[0]]=sign*expr.func(*ee)returndiflen(ee)!=len(pp):returnNoneforp,einzip(pp,ee):d=p.xreplace(d).matches(e,d)ifdisNone:returnNonereturnd@staticmethoddef_combine_inverse(lhs,rhs):""" Returns lhs/rhs, but treats arguments like symbols, so things like oo/oo return 1, instead of a nan. """iflhs==rhs:returnS.Onedefcheck(l,r):ifl.is_Floatandr.is_comparable:# if both objects are added to 0 they will share the same "normalization"# and are more likely to compare the same. Since Add(foo, 0) will not allow# the 0 to pass, we use __add__ directly.returnl.__add__(0)==r.evalf().__add__(0)returnFalseifcheck(lhs,rhs)orcheck(rhs,lhs):returnS.Oneiflhs.is_Mulandrhs.is_Mul:a=list(lhs.args)b=[1]forxinrhs.args:ifxina:a.remove(x)elif-xina:a.remove(-x)b.append(-1)else:b.append(x)returnlhs.func(*a)/rhs.func(*b)returnlhs/rhsdefas_powers_dict(self):d=defaultdict(int)forterminself.args:b,e=term.as_base_exp()d[b]+=ereturnddefas_numer_denom(self):# don't use _from_args to rebuild the numerators and denominators# as the order is not guaranteed to be the same once they have# been separated from each othernumers,denoms=list(zip(*[f.as_numer_denom()forfinself.args]))returnself.func(*numers),self.func(*denoms)defas_base_exp(self):e1=Nonebases=[]nc=0forminself.args:b,e=m.as_base_exp()ifnotb.is_commutative:nc+=1ife1isNone:e1=eelife!=e1ornc>1:returnself,S.Onebases.append(b)returnself.func(*bases),e1def_eval_is_polynomial(self,syms):returnall(term._eval_is_polynomial(syms)forterminself.args)def_eval_is_rational_function(self,syms):returnall(term._eval_is_rational_function(syms)forterminself.args)def_eval_is_algebraic_expr(self,syms):returnall(term._eval_is_algebraic_expr(syms)forterminself.args)_eval_is_bounded=lambdaself:self._eval_template_is_attr('is_bounded')_eval_is_commutative=lambdaself:self._eval_template_is_attr('is_commutative')_eval_is_rational=lambdaself:self._eval_template_is_attr('is_rational',when_multiple=None)def_eval_is_integer(self):is_rational=self.is_rationalifis_rational:n,d=self.as_numer_denom()ifdisS.One:returnTrueelifdisS(2):returnn.is_evenelifis_rationalisFalse:returnFalsedef_eval_is_polar(self):has_polar=any(arg.is_polarforarginself.args)returnhas_polarand \
all(arg.is_polarorarg.is_positiveforarginself.args)def_eval_is_real(self):fromsympy.core.logicimportfuzzy_notim_count=0is_neither=Falseis_zero=Falsefortinself.args:ift.is_imaginary:im_count+=1continuet_real=t.is_realift_real:ifnotis_zero:is_zero=fuzzy_not(t.is_nonzero)ifis_zero:returnTruecontinueelift_realisFalse:ifis_neither:returnelse:is_neither=Trueelse:returnifis_neither:ifim_count%2==0:ifis_zeroisFalse:returnFalseelse:returnim_count%2==0def_eval_is_imaginary(self):ifself.is_nonzero:return(S.ImaginaryUnit*self).is_realdef_eval_is_hermitian(self):nc_count=0im_count=0is_neither=Falsefortinself.args:ifnott.is_commutative:nc_count+=1ifnc_count>1:returnNoneift.is_antihermitian:im_count+=1continuet_real=t.is_hermitianift_real:continueelift_realisFalse:ifis_neither:returnNoneelse:is_neither=Trueelse:returnNoneifis_neither:returnFalsereturn(im_count%2==0)def_eval_is_antihermitian(self):nc_count=0im_count=0is_neither=Falsefortinself.args:ifnott.is_commutative:nc_count+=1ifnc_count>1:returnNoneift.is_antihermitian:im_count+=1continuet_real=t.is_hermitianift_real:continueelift_realisFalse:ifis_neither:returnNoneelse:is_neither=Trueelse:returnNoneifis_neither:returnFalsereturn(im_count%2==1)def_eval_is_irrational(self):fortinself.args:a=t.is_irrationalifa:others=list(self.args)others.remove(t)ifall(x.is_rationalisTrueforxinothers):returnTruereturnNoneifaisNone:returnreturnFalsedef_eval_is_zero(self):zero=Noneforainself.args:ifa.is_zero:zero=Truecontinuebound=a.is_boundedifnotbound:returnboundifzero:returnTruedef_eval_is_positive(self):"""Return True if self is positive, False if not, and None if it cannot be determined. This algorithm is non-recursive and works by keeping track of the sign which changes when a negative or nonpositive is encountered. Whether a nonpositive or nonnegative is seen is also tracked since the presence of these makes it impossible to return True, but possible to return False if the end result is nonpositive. e.g. pos * neg * nonpositive -> pos or zero -> None is returned pos * neg * nonnegative -> neg or zero -> False is returned """sign=1saw_NON=Falsefortinself.args:ift.is_positive:continueelift.is_negative:sign=-signelift.is_zero:returnFalseelift.is_nonpositive:sign=-signsaw_NON=Trueelift.is_nonnegative:saw_NON=Trueelse:returnifsign==1andsaw_NONisFalse:returnTrueifsign<0:returnFalsedef_eval_is_negative(self):"""Return True if self is negative, False if not, and None if it cannot be determined. This algorithm is non-recursive and works by keeping track of the sign which changes when a negative or nonpositive is encountered. Whether a nonpositive or nonnegative is seen is also tracked since the presence of these makes it impossible to return True, but possible to return False if the end result is nonnegative. e.g. pos * neg * nonpositive -> pos or zero -> False is returned pos * neg * nonnegative -> neg or zero -> None is returned """sign=1saw_NON=Falsefortinself.args:ift.is_positive:continueelift.is_negative:sign=-signelift.is_zero:returnFalseelift.is_nonpositive:sign=-signsaw_NON=Trueelift.is_nonnegative:saw_NON=Trueelse:returnifsign==-1andsaw_NONisFalse:returnTrueifsign>0:returnFalsedef_eval_is_odd(self):is_integer=self.is_integerifis_integer:r,acc=True,1fortinself.args:ifnott.is_integer:returnNoneelift.is_even:r=Falseelift.is_integer:ifrisFalse:passelifacc!=1and(acc+t).is_odd:r=Falseelift.is_oddisNone:r=Noneacc=treturnr# !integer -> !oddelifis_integerisFalse:returnFalsedef_eval_is_even(self):is_integer=self.is_integerifis_integer:returnfuzzy_not(self._eval_is_odd())elifis_integerisFalse:returnFalsedef_eval_subs(self,old,new):fromsympy.functions.elementary.complexesimportsignfromsympy.ntheory.factor_importmultiplicityfromsympy.simplify.simplifyimportpowdenest,fractionifnotold.is_Mul:returnNone# try keep replacement literal so -2*x doesn't replace 4*xifold.args[0].is_Numberandold.args[0]<0:ifself.args[0].is_Number:ifself.args[0]<0:returnself._subs(-old,-new)returnNonedefbase_exp(a):# if I and -1 are in a Mul, they get both end up with# a -1 base (see issue 3322); all we want here are the# true Pow or exp separated into base and exponentifa.is_Powora.funcisC.exp:returna.as_base_exp()returna,S.Onedefbreakup(eq):"""break up powers of eq when treated as a Mul: b**(Rational*e) -> b**e, Rational commutatives come back as a dictionary {b**e: Rational} noncommutatives come back as a list [(b**e, Rational)] """(c,nc)=(defaultdict(int),list())forainMul.make_args(eq):a=powdenest(a)(b,e)=base_exp(a)ifeisnotS.One:(co,_)=e.as_coeff_mul()b=Pow(b,e/co)e=coifa.is_commutative:c[b]+=eelse:nc.append([b,e])return(c,nc)defrejoin(b,co):""" Put rational back with exponent; in general this is not ok, but since we took it from the exponent for analysis, it's ok to put it back. """(b,e)=base_exp(b)returnPow(b,e*co)defndiv(a,b):"""if b divides a in an extractive way (like 1/4 divides 1/2 but not vice versa, and 2/5 does not divide 1/3) then return the integer number of times it divides, else return 0. """ifnotb.q%a.qornota.q%b.q:returnint(a/b)return0# give Muls in the denominator a chance to be changed (see issue 2552)# rv will be the default return valuerv=Nonen,d=fraction(self)ifdisnotS.One:self2=n._subs(old,new)/d._subs(old,new)ifnotself2.is_Mul:returnself2._subs(old,new)ifself2!=self:self=rv=self2# Now continue with regular substitution.# handle the leading coefficient and use it to decide if anything# should even be started; we always know where to find the Rational# so it's a quick testco_self=self.args[0]co_old=old.args[0]co_xmul=Noneifco_old.is_Rationalandco_self.is_Rational:# if coeffs are the same there will be no updating to do# below after breakup() step; so skip (and keep co_xmul=None)ifco_old!=co_self:co_xmul=co_self.extract_multiplicatively(co_old)elifco_old.is_Rational:returnrv# break self and old into factors(c,nc)=breakup(self)(old_c,old_nc)=breakup(old)# update the coefficients if we had an extraction# e.g. if co_self were 2*(3/35*x)**2 and co_old = 3/5# then co_self in c is replaced by (3/5)**2 and co_residual# is 2*(1/7)**2ifco_xmulandco_xmul.is_Rationalandabs(co_old)!=1:mult=S(multiplicity(abs(co_old),co_self))c.pop(co_self)ifco_oldinc:c[co_old]+=multelse:c[co_old]=multco_residual=co_self/co_old**multelse:co_residual=1# do quick tests to see if we can't succeedok=Trueiflen(old_nc)>len(nc):# more non-commutative termsok=Falseeliflen(old_c)>len(c):# more commutative termsok=Falseelifset(i[0]foriinold_nc).difference(set(i[0]foriinnc)):# unmatched non-commutative basesok=Falseelifset(old_c).difference(set(c)):# unmatched commutative termsok=Falseelifany(sign(c[b])!=sign(old_c[b])forbinold_c):# differences in signok=Falseifnotok:returnrvifnotold_c:cdid=Noneelse:rat=[]for(b,old_e)inold_c.items():c_e=c[b]rat.append(ndiv(c_e,old_e))ifnotrat[-1]:returnrvcdid=min(rat)ifnotold_nc:ncdid=Noneforiinrange(len(nc)):nc[i]=rejoin(*nc[i])else:ncdid=0# number of nc replacements we didtake=len(old_nc)# how much to look at each timelimit=cdidorS.Infinity# max number that we can takefailed=[]# failed terms will need subs if other terms passi=0whilelimitandi+take<=len(nc):hit=False# the bases must be equivalent in succession, and# the powers must be extractively compatible on the# first and last factor but equal inbetween.rat=[]forjinrange(take):ifnc[i+j][0]!=old_nc[j][0]:breakelifj==0:rat.append(ndiv(nc[i+j][1],old_nc[j][1]))elifj==take-1:rat.append(ndiv(nc[i+j][1],old_nc[j][1]))elifnc[i+j][1]!=old_nc[j][1]:breakelse:rat.append(1)j+=1else:ndo=min(rat)ifndo:iftake==1:ifcdid:ndo=min(cdid,ndo)nc[i]=Pow(new,ndo)*rejoin(nc[i][0],nc[i][1]-ndo*old_nc[0][1])else:ndo=1# the left residuall=rejoin(nc[i][0],nc[i][1]-ndo*old_nc[0][1])# eliminate all middle termsmid=new# the right residual (which may be the same as the middle if take == 2)ir=i+take-1r=(nc[ir][0],nc[ir][1]-ndo*old_nc[-1][1])ifr[1]:ifi+take<len(nc):nc[i:i+take]=[l*mid,r]else:r=rejoin(*r)nc[i:i+take]=[l*mid*r]else:# there was nothing left on the rightnc[i:i+take]=[l*mid]limit-=ndoncdid+=ndohit=Trueifnothit:# do the subs on this failing factorfailed.append(i)i+=1else:ifnotncdid:returnrv# although we didn't fail, certain nc terms may have# failed so we rebuild them after attempting a partial# subs on themfailed.extend(range(i,len(nc)))foriinfailed:nc[i]=rejoin(*nc[i]).subs(old,new)# rebuild the expressionifcdidisNone:do=ncdidelifncdidisNone:do=cdidelse:do=min(ncdid,cdid)margs=[]forbinc:ifbinold_c:# calculate the new exponente=c[b]-old_c[b]*domargs.append(rejoin(b,e))else:margs.append(rejoin(b.subs(old,new),c[b]))ifcdidandnotncdid:# in case we are replacing commutative with non-commutative,# we want the new term to come at the front just like the# rest of this routinemargs=[Pow(new,cdid)]+margsreturnco_residual*self.func(*margs)*self.func(*nc)def_eval_nseries(self,x,n,logx):fromsympyimportpowsimpterms=[t.nseries(x,n=n,logx=logx)fortinself.args]res=powsimp(self.func(*terms).expand(),combine='exp',deep=True)ifres.has(C.Order):res+=C.Order(x**n,x)returnresdef_eval_as_leading_term(self,x):returnself.func(*[t.as_leading_term(x)fortinself.args])def_eval_conjugate(self):returnself.func(*[t.conjugate()fortinself.args])def_eval_transpose(self):returnself.func(*[t.transpose()fortinself.args[::-1]])def_eval_adjoint(self):returnself.func(*[t.adjoint()fortinself.args[::-1]])def_sage_(self):s=1forxinself.args:s*=x._sage_()returns

[docs]defas_content_primitive(self,radical=False):"""Return the tuple (R, self/R) where R is the positive Rational extracted from self. Examples ======== >>> from sympy import sqrt >>> (-3*sqrt(2)*(2 - 2*sqrt(2))).as_content_primitive() (6, -sqrt(2)*(-sqrt(2) + 1)) See docstring of Expr.as_content_primitive for more examples. """coef=S.Oneargs=[]fori,ainenumerate(self.args):c,p=a.as_content_primitive(radical=radical)coef*=cifpisnotS.One:args.append(p)# don't use self._from_args here to reconstruct args# since there may be identical args now that should be combined# e.g. (2+2*x)*(3+3*x) should be (6, (1 + x)**2) not (6, (1+x)*(1+x))returncoef,self.func(*args)

[docs]defprod(a,start=1):"""Return product of elements of a. Start with int 1 so if only ints are included then an int result is returned. Examples ======== >>> from sympy import prod, S >>> prod(range(3)) 0 >>> type(_) is int True >>> prod([S(2), 3]) 6 >>> _.is_Integer True You can start the product at something other than 1: >>> prod([1, 2], 3) 6 """returnreduce(operator.mul,a,start)