def mrv_inflimit(expr, x, _cache = {}): if _cache.has_key((expr, x)): raise RuntimeError('Detected recursion while computing mrv_inflimit(%s, %s)' % (expr, x)) _cache[(expr, x)] = 1 expr_map = {} mrv_map = {} newexpr = mrv2(expr, x, expr_map, mrv_map) if mrv_map.has_key(x): t = Basic.Temporary(unbounded=True, positive=True) r = mrv_inflimit(expr.subs(Basic.log(x), t).subs(x, Basic.exp(t)).subs(t, x), x) del _cache[(expr, x)] return r w = Basic.Symbol('w_0',dummy=True, positive=True, infinitesimal=True) germ, new_mrv_map = rewrite_mrv_map(mrv_map, x, w) new_expr = rewrite_expr(newexpr, germ, new_mrv_map, w) lt = new_expr.as_leading_term(w) if germ is not None: lt = lt.subs(Basic.log(w), -germ[0]) c,e = lt.as_coeff_exponent(w) assert not c.has(w),`c` if e==0: r = c.inflimit(x) del _cache[(expr, x)] return r if e.is_positive: del _cache[(expr, x)] return S.Zero if e.is_negative: del _cache[(expr, x)] return Basic.sign(c) * S.Infinity raise RuntimeError('Failed to compute mrv_inflimit(%s, %s), got lt=%s' % (self, x, lt))
def mrv2(expr, x, d, md): """ Compute a set of most rapidly varying subexpressions of expr with respect to x. d = {} md = {} mrv2(x + exp(x),x,d) -> x+se, d={x:x, exp(x):se}, md={exp(x):se} """ if d.has_key(expr): return d[expr] if not expr.has(x): return expr if expr==x: if not md: md[x] = x return x if isinstance(expr, (Basic.Add, Basic.Mul)): r = expr.__class__(*[mrv2(t, x, d, md) for t in expr]) d[expr] = r return r log = Basic.log exp = Basic.exp if isinstance(expr, Basic.Pow): if not expr.exp.has(x): r = mrv2(expr.base, x, d, md)**expr.exp else: r = mrv2(exp(expr.exp * log(expr.base)), x, d, md) d[expr] = r return r if isinstance(expr, Basic.exp): e = expr[0] l = e.inflimit(x) r = exp(mrv2(e, x, d, md)) if isinstance(l, Basic.Infinity): # e -> oo as x->oo en = e elif isinstance(l, Basic.NegativeInfinity): # e -> -oo as x->oo # rewrite to ensure that exp(e) -> oo en = -e else: # |e| < oo as x->oo d[expr] = r return r # normalize exp(2*e) -> exp(e) coeff, terms = en.as_coeff_terms() new_terms = [] for t in terms: if t.has(x): pass elif t.is_positive: continue elif t.is_negative: coeff *= -1 continue new_terms.append(t) terms = new_terms coeff = Basic.sign(coeff) if not isinstance(coeff, Basic.One): terms.insert(0,coeff) en = Basic.Mul(*terms) nexpr = exp(en) #print coeff,terms,nexpr if md.has_key(x): c = '>' else: lst = md.keys() lst.sort(cmp_ops_count) c = mrv_compare(nexpr, lst[0], x) if c !='<': if c=='>': md.clear() if md.has_key(nexpr): tmp = md[nexpr] else: tmp = Basic.Temporary() md[nexpr] = tmp r = expr.subs(nexpr, tmp) d[expr] = r return r if isinstance(expr, Basic.Function): r = expr.func(*[mrv2(a, x, d, md) for a in expr]) d[expr] = r return r raise NotImplementedError("don't know how to find mrv2(%s,%s)" % (expr,x))