118
118
"""
119
119
from functools import reduce
120
120
121
- from sympy .core import Basic , S , Mul , PoleError , expand_mul
121
+ from sympy .core import Basic , S , Mul , PoleError , expand_mul , evaluate
122
122
from sympy .core .cache import cacheit
123
- from sympy .core .intfunc import ilcm
124
123
from sympy .core .numbers import I , oo
125
- from sympy .core .symbol import Dummy , Wild
124
+ from sympy .core .symbol import Dummy , Wild , Symbol
126
125
from sympy .core .traversal import bottom_up
126
+ from sympy .core .sorting import ordered
127
127
128
- from sympy .functions import log , exp , sign as _sign
128
+ from sympy .functions import log , exp , sign , sin
129
129
from sympy .series .order import Order
130
130
from sympy .utilities .exceptions import SymPyDeprecationWarning
131
131
from sympy .utilities .misc import debug_decorator as debug
@@ -142,7 +142,6 @@ def mrv(e, x):
142
142
{x}
143
143
144
144
"""
145
- from ..functions import log
146
145
147
146
if not e .has (x ):
148
147
return set ()
@@ -151,7 +150,7 @@ def mrv(e, x):
151
150
if e .is_Mul or e .is_Add :
152
151
a , b = e .as_two_terms ()
153
152
return mrv_max (mrv (a , x ), mrv (b , x ), x )
154
- if e .is_Exp :
153
+ if e .func == exp :
155
154
if e .exp == x :
156
155
return {e }
157
156
if any (a .is_infinite for a in Mul .make_args (limitinf (e .exp , x ))):
@@ -161,11 +160,41 @@ def mrv(e, x):
161
160
return mrv (e .base , x )
162
161
if isinstance (e , log ):
163
162
return mrv (e .args [0 ], x )
164
- if e .is_Function and not isinstance (e .func , UndefinedFunction ):
165
- return functools .reduce (lambda a , b : mrv_max (a , b , x ),
166
- (mrv (a , x ) for a in e .args ))
163
+ if e .is_Function :
164
+ return reduce (lambda a , b : mrv_max (a , b , x ), (mrv (a , x ) for a in e .args ))
167
165
raise NotImplementedError (f"Can't calculate the MRV of { e } ." )
168
166
167
+ def mrv_max (f , g , x ):
168
+ """Compute the maximum of two MRV sets.
169
+
170
+ Examples
171
+ ========
172
+
173
+ >>> mrv_max({log(x)}, {x**5}, x)
174
+ {x**5}
175
+
176
+ """
177
+
178
+ if not f :
179
+ return g
180
+ if not g :
181
+ return f
182
+ if f & g :
183
+ return f | g
184
+
185
+ a , b = map (next , map (iter , (f , g )))
186
+
187
+ # The log(exp(...)) must always be simplified here.
188
+ la = a .exp if a .is_Exp else log (a )
189
+ lb = b .exp if b .is_Exp else log (b )
190
+
191
+ c = limitinf (la / lb , x )
192
+ if c .is_zero :
193
+ return g
194
+ if c .is_infinite :
195
+ return f
196
+ return f | g
197
+
169
198
def rewrite (e , x , w ):
170
199
r"""
171
200
Rewrites the expression in terms of the MRV subexpression.
@@ -194,7 +223,6 @@ def rewrite(e, x, w):
194
223
(log(x)/y, -x)
195
224
196
225
"""
197
- from ..functions import exp
198
226
199
227
Omega = mrv (e , x )
200
228
if not Omega :
@@ -245,25 +273,24 @@ def mrv_leadterm(e, x):
245
273
(-1, 0)
246
274
247
275
"""
248
- from ..functions import exp , log
249
276
250
277
if not e .has (x ):
251
278
return e , Integer (0 )
252
279
253
280
# Rewrite to exp-log functions per Sec. 3.3 of thesis.
254
281
e = e .replace (lambda f : f .is_Pow and f .exp .has (x ),
255
282
lambda f : exp (log (f .base )* f .exp ))
256
- e = e .replace (lambda f : f .is_Mul and sum (a .is_Exp for a in f .args ) > 1 ,
257
- lambda f : Mul (exp (Add (* (a .exp for a in f .args if a .is_Exp ))),
258
- * (a for a in f .args if not a .is_Exp )))
283
+ e = e .replace (lambda f : f .is_Mul and sum (a .func == exp for a in f .args ) > 1 ,
284
+ lambda f : Mul (exp (Add (* (a .exp for a in f .args if a .func == exp ))),
285
+ * (a for a in f .args if not a .func == exp )))
259
286
260
287
# The positive dummy, w, is used here so log(w*2) etc. will expand.
261
288
# TODO: For limits of complex functions, the algorithm would have to
262
289
# be improved, or just find limits of Re and Im components separately.
263
290
w = Dummy ('w' , real = True , positive = True )
264
291
e , logw = rewrite (e , x , w )
265
292
266
- c0 , e0 = f .leadterm (w , logx = logw )
293
+ c0 , e0 = e .leadterm (w , logx = logw )
267
294
if c0 .has (w ):
268
295
raise NotImplementedError (f'Cannot compute leadterm({ e } , { x } ). '
269
296
'The coefficient should have been free of '
@@ -283,12 +310,11 @@ def signinf(e, x):
283
310
large and zero if `e` is *constantly* zero for `x\to\infty`.
284
311
285
312
"""
286
- from ..functions import sign
287
313
288
314
if not e .has (x ):
289
315
return sign (e ).simplify ()
290
316
if e == x or (e .is_Pow and signinf (e .base , x ) == 1 ):
291
- return Integer (1 )
317
+ return S (1 )
292
318
if e .is_Mul :
293
319
a , b = e .as_two_terms ()
294
320
return signinf (a , x )* signinf (b , x )
@@ -365,4 +391,9 @@ def gruntz(e, z, z0, dir="+"):
365
391
# tractable functions in terms of familiar intractable ones.
366
392
# It might be nicer to rewrite the exactly to what they were initially,
367
393
# but that would take some work to implement.
368
- return r .rewrite ('intractable' , deep = True )
394
+ return r .rewrite ('intractable' , deep = True )
395
+
396
+ # tests
397
+ x = Symbol ('x' )
398
+ ans = gruntz (sin (x )/ x , x , 0 )
399
+ print (ans )
0 commit comments