def test_logcombine_complex_coeff(): # TODO: Make the expand() call in logcombine smart enough so that both # these hold. assert logcombine(Integral((sin(x**2)+cos(x**3))/x, x), force=True) == \ Integral((sin(x**2)+cos(x**3))/x, x) assert logcombine(Integral((sin(x**2)+cos(x**3))/x, x)+ (2+3*I)*log(x), \ force=True) == log(x**2)+3*I*log(x) + \ Integral((sin(x**2)+cos(x**3))/x, x)
def _eval_nseries(self, x, n, logx): # NOTE Please see the comment at the beginning of this file, labelled # IMPORTANT. from sympy import cancel, Order, logcombine if not logx: logx = log(x) if self.args[0] == x: return logx arg = self.args[0] k, l = Wild("k"), Wild("l") r = arg.match(k * x**l) if r is not None: k, l = r[k], r[l] if l != 0 and not l.has(x) and not k.has(x): r = log(k) + l * logx # XXX true regardless of assumptions? return r # TODO new and probably slow s = self.args[0].nseries(x, n=n, logx=logx) while s.is_Order: n += 1 s = self.args[0].nseries(x, n=n, logx=logx) a, b = s.leadterm(x) p = cancel(s / (a * x**b) - 1) if p.has(exp): p = logcombine(p) g = None l = [] for i in range(n + 2): g = log.taylor_term(i, p, g) g = g.nseries(x, n=n, logx=logx) l.append(g) return log(a) + b * logx + Add(*l) + Order(p**n, x)
def get_ILR_labels(df, mode="latex", **kwargs): """ Get symbolic labels for ILR coordinates based on dataframe columns. Parameters ---------- df : :class:`pandas.DataFrame` Dataframe to generate ILR labels for. mode : :class:`str` Mode of label to return (:code:`LaTeX`, :code:`simple`). Returns ------- :class:`list` List of ILR coordinates corresponding to dataframe columns. Notes ------ Some variable names are protected in :mod:`sympy` and if used can result in errors. If one of these column names is found, it will be replaced with a title-cased duplicated version of itself (e.g. 'S' will be replaced by 'Ss'). """ D = df.columns.size # encode symbolic variables vars = [sympy.var("c_{}".format(ix)) for ix in range(D)] arr = sympy.Matrix([[sympy.ln(v) for v in vars]]) # this is the CLR --> ILR transform helmert = symbolic_helmert_basis(D, **kwargs) expr = sympy.simplify( sympy.logcombine(sympy.simplify(arr @ helmert.transpose()), force=True) ) expr = expr.applyfunc(_aggregate_sympy_constants) # sub in Phi (the CLR normalisation variable) names = [ r"{} / γ".format( c if c not in __sympy_protected_variables__ else __sympy_protected_variables__[c], ) for c in df.columns ] named_expr = expr.subs({k: v for (k, v) in zip(vars, names)}) # format latex labels if mode.lower() == "latex": labels = [ r"${}$".format(sympy.latex(l, mul_symbol="dot", ln_notation=True)) for l in named_expr ] elif mode.lower() == "simple": # here we could exclude scaling terms and just use ILR(A/B) unscaled_components = named_expr.applyfunc( lambda x: x.func(*[term for term in x.args if term.free_symbols]) ) labels = [str(l).replace("log", "ILR") for l in unscaled_components] else: msg = "Label mode {} not recognised.".format(mode) raise NotImplementedError(msg) return labels
def test_logcombine_2(): # The same as one of the tests above, but with Rational(a, b) replaced with a/b. # This fails because of a bug in matches. See issue 1274. x, y = symbols("x,y") assert logcombine((x*y+sqrt(x**4+y**4)+log(x)-log(y))/(pi*x**(2/3)*y**(3/2)), \ force=True) == log(x**(1/(pi*x**(2/3)*y**(3/2)))*y**(-1/\ (pi*x**(2/3)*y**(3/2)))) + (x**4 + y**4)**(1/2)/(pi*x**(2/3)*y**(3/2)) + \ x**(1/3)/(pi*y**(1/2))
def combines_log(expression): ''' Applies identities (1) and (2) This function uses sympy.logcombine() to combine a log expression. ''' return logcombine(expression)
def test_logcombine_2(): # The same as one of the tests above, but with Rational(a,b) replaced with a/b. # This fails because of a bug in matches. See issue 1274. x, y = symbols("xy") assert logcombine((x*y+sqrt(x**4+y**4)+log(x)-log(y))/(pi*x**(2/3)*y**(3/2)), \ assume_pos_real=True) == log(x**(1/(pi*x**(2/3)*y**(3/2)))*y**(-1/\ (pi*x**(2/3)*y**(3/2)))) + (x**4 + y**4)**(1/2)/(pi*x**(2/3)*y**(3/2)) + \ x**(1/3)/(pi*y**(1/2))
def extra_simple(mul): """Simplification of pysb rates Arguments: mul: psyb reaction (sympy.Mul object) Returns: a simplified version denested of exponents. TODO: make sure it fully simplifies! """ return sp.powsimp((sp.expand_power_base(sp.powdenest(sp.logcombine( sp.expand_log(mul.simplify(), force=True), force=True), force=True), force=True)), force=True)
def _eval_nseries(self, x, n, logx, cdir=0): # NOTE Please see the comment at the beginning of this file, labelled # IMPORTANT. from sympy import im, cancel, I, Order, logcombine if not logx: logx = log(x) if self.args[0] == x: return logx arg = self.args[0] k, l = Wild("k"), Wild("l") r = arg.match(k * x**l) if r is not None: k, l = r[k], r[l] if l != 0 and not l.has(x) and not k.has(x): r = log(k) + l * logx # XXX true regardless of assumptions? return r # TODO new and probably slow try: a, b = arg.leadterm(x) s = arg.nseries(x, n=n + b, logx=logx) except (ValueError, NotImplementedError): s = arg.nseries(x, n=n, logx=logx) while s.is_Order: n += 1 s = arg.nseries(x, n=n, logx=logx) a, b = s.removeO().leadterm(x) p = cancel(s / (a * x**b) - 1) if p.has(exp): p = logcombine(p) g = None l = [] for i in range(n + 2): g = log.taylor_term(i, p, g) g = g.nseries(x, n=n, logx=logx) l.append(g) res = log(a) + b * logx if cdir != 0: cdir = self.args[0].dir(x, cdir) if a.is_real and a.is_negative and im(cdir) < 0: res -= 2 * I * S.Pi return res + Add(*l) + Order(p**n, x)
def logcombine_include_negative_power(expr, force=False): """Perform a more powerful logcombine than SymPy's logcombine. In SymPy: logcombine(-log(x)) = -log(x), rather than log(1/x). This behaviour is implemented here. >>> SolveLogEquation.logcombine_include_negative_power(-sympy.log(2 * x + 1)) log(1/(2*x + 1)) """ expr = sympy.logcombine(expr, force) if expr.could_extract_minus_sign(): interior = expr.match(coeff0 * sympy.log(x0))[x0] expr *= -1 expr = sympy.log(1 / interior) return expr
def log_solver(expr, check_validity=False): """Return valid solutions (i.e. solutions that don't evaluate any log that's part of the expression as complex) for an expression that is the addition/subtraction of logs. >>> SolveLogEquation.log_solver(sympy.log(x - 1)) [2] >>> SolveLogEquation.log_solver(sympy.log(3 * x - 2) - 2 * sympy.log(x)) [1, 2] """ single_log = sympy.logcombine(expr, force=True) interior = single_log.match(coeff0 * sympy.log(x0))[x0] numerator, denominator = interior.as_numer_denom() solutions = sympy.solve(numerator - denominator) if check_validity: return [solution for solution in solutions if SolveLogEquation.is_valid_solution(expr, solution)] else: return solutions
def normalize_transformations(w): # same as # lambda w: w.doit().expand().ratsimp().expand() # except catch Polynomial error that could be triggered by ratsimp() # and catch attribute error for objects like Interval from sympy import PolynomialError w = w.doit() try: w = w.expand() except (AttributeError, TypeError): pass if w.has(sympy_log): from sympy import logcombine try: w = logcombine(w) except TypeError: pass try: w = w.ratsimp().expand() except (AttributeError, PolynomialError, UnicodeEncodeError, TypeError): pass return w
def test_logcombine_1(): x, y = symbols("x,y") a = Symbol("a") z, w = symbols("z,w", positive=True) b = Symbol("b", real=True) assert logcombine(log(x) + 2 * log(y)) == log(x) + 2 * log(y) assert logcombine(log(x) + 2 * log(y), force=True) == log(x * y**2) assert logcombine(a * log(w) + log(z)) == a * log(w) + log(z) assert logcombine(b * log(z) + b * log(x)) == log(z**b) + b * log(x) assert logcombine(b * log(z) - log(w)) == log(z**b / w) assert logcombine(log(x) * log(z)) == log(x) * log(z) assert logcombine(log(w) * log(x)) == log(w) * log(x) assert logcombine(cos(-2 * log(z) + b * log(w))) == cos(log(w**b / z**2)) assert logcombine(log(log(x)-log(y))-log(z), force=True) == \ log(log((x/y)**(1/z))) assert logcombine((2 + I) * log(x), force=True) == I * log(x) + log(x**2) assert logcombine((x**2+log(x)-log(y))/(x*y), force=True) == \ log(x**(1/(x*y))*y**(-1/(x*y)))+x/y assert logcombine(log(x)*2*log(y)+log(z), force=True) == \ log(z*y**log(x**2)) assert logcombine((x*y+sqrt(x**4+y**4)+log(x)-log(y))/(pi*x**Rational(2, 3)*\ sqrt(y)**3), force=True) == \ log(x**(1/(pi*x**Rational(2, 3)*sqrt(y)**3))*y**(-1/(pi*\ x**Rational(2, 3)*sqrt(y)**3))) + sqrt(x**4 + y**4)/(pi*\ x**Rational(2, 3)*sqrt(y)**3) + x**Rational(1, 3)/(pi*sqrt(y)) assert logcombine(Eq(log(x), -2*log(y)), force=True) == \ Eq(log(x*y**2), Integer(0)) assert logcombine(Eq(y, x*acos(-log(x/y))), force=True) == \ Eq(y, x*acos(log(y/x))) assert logcombine(gamma(-log(x/y))*acos(-log(x/y)), force=True) == \ acos(log(y/x))*gamma(log(y/x)) assert logcombine((2+3*I)*log(x), force=True) == \ log(x**2)+3*I*log(x) assert logcombine(Eq(y, -log(x)), force=True) == Eq(y, log(1 / x)) assert logcombine(Integral((sin(x**2)+cos(x**3))/x, x), force=True) == \ Integral((sin(x**2)+cos(x**3))/x, x) assert logcombine(Integral((sin(x**2)+cos(x**3))/x, x)+ (2+3*I)*log(x), \ force=True) == log(x**2)+3*I*log(x) + \ Integral((sin(x**2)+cos(x**3))/x, x)
def test_logcombine_1(): x, y = symbols("x,y") a = Symbol("a") z, w = symbols("z,w", positive=True) b = Symbol("b", real=True) assert logcombine(log(x)+2*log(y)) == log(x) + 2*log(y) assert logcombine(log(x)+2*log(y), force=True) == log(x*y**2) assert logcombine(a*log(w)+log(z)) == a*log(w) + log(z) assert logcombine(b*log(z)+b*log(x)) == log(z**b) + b*log(x) assert logcombine(b*log(z)-log(w)) == log(z**b/w) assert logcombine(log(x)*log(z)) == log(x)*log(z) assert logcombine(log(w)*log(x)) == log(w)*log(x) assert logcombine(cos(-2*log(z)+b*log(w))) in [cos(log(w**b/z**2)), cos(log(z**2/w**b))] assert logcombine(log(log(x)-log(y))-log(z), force=True) == \ log(log((x/y)**(1/z))) assert logcombine((2+I)*log(x), force=True) == I*log(x)+log(x**2) assert logcombine((x**2+log(x)-log(y))/(x*y), force=True) == \ log(x**(1/(x*y))*y**(-1/(x*y)))+x/y assert logcombine(log(x)*2*log(y)+log(z), force=True) == \ log(z*y**log(x**2)) assert logcombine((x*y+sqrt(x**4+y**4)+log(x)-log(y))/(pi*x**Rational(2, 3)*\ sqrt(y)**3), force=True) == \ log(x**(1/(pi*x**Rational(2, 3)*sqrt(y)**3))*y**(-1/(pi*\ x**Rational(2, 3)*sqrt(y)**3))) + sqrt(x**4 + y**4)/(pi*\ x**Rational(2, 3)*sqrt(y)**3) + x**Rational(1, 3)/(pi*sqrt(y)) assert logcombine(Eq(log(x), -2*log(y)), force=True) == \ Eq(log(x*y**2), Integer(0)) assert logcombine(Eq(y, x*acos(-log(x/y))), force=True) == \ Eq(y, x*acos(log(y/x))) assert logcombine(gamma(-log(x/y))*acos(-log(x/y)), force=True) == \ acos(log(y/x))*gamma(log(y/x)) assert logcombine((2+3*I)*log(x), force=True) == \ log(x**2)+3*I*log(x) assert logcombine(Eq(y, -log(x)), force=True) == Eq(y, log(1/x)) assert logcombine(Integral((sin(x**2)+cos(x**3))/x, x), force=True) == \ Integral((sin(x**2)+cos(x**3))/x, x) assert logcombine(Integral((sin(x**2)+cos(x**3))/x, x)+ (2+3*I)*log(x), \ force=True) == log(x**2)+3*I*log(x) + \ Integral((sin(x**2)+cos(x**3))/x, x)
def test_logcombine_1(): x, y = symbols("x,y") a = Symbol("a") z, w = symbols("z,w", positive=True) b = Symbol("b", real=True) assert logcombine(log(x) + 2*log(y)) == log(x) + 2*log(y) assert logcombine(log(x) + 2*log(y), force=True) == log(x*y**2) assert logcombine(a*log(w) + log(z)) == a*log(w) + log(z) assert logcombine(b*log(z) + b*log(x)) == log(z**b) + b*log(x) assert logcombine(b*log(z) - log(w)) == log(z**b/w) assert logcombine(log(x)*log(z)) == log(x)*log(z) assert logcombine(log(w)*log(x)) == log(w)*log(x) assert logcombine(cos(-2*log(z) + b*log(w))) in [cos(log(w**b/z**2)), cos(log(z**2/w**b))] assert logcombine(log(log(x) - log(y)) - log(z), force=True) == \ log(log(x/y)/z) assert logcombine((2 + I)*log(x), force=True) == (2 + I)*log(x) assert logcombine((x**2 + log(x) - log(y))/(x*y), force=True) == \ (x**2 + log(x/y))/(x*y) # the following could also give log(z*x**log(y**2)), what we # are testing is that a canonical result is obtained assert logcombine(log(x)*2*log(y) + log(z), force=True) == \ log(z*y**log(x**2)) assert logcombine((x*y + sqrt(x**4 + y**4) + log(x) - log(y))/(pi*x**Rational(2, 3)* sqrt(y)**3), force=True) == ( x*y + sqrt(x**4 + y**4) + log(x/y))/(pi*x**(S(2)/3)*y**(S(3)/2)) assert logcombine(gamma(-log(x/y))*acos(-log(x/y)), force=True) == \ acos(-log(x/y))*gamma(-log(x/y)) assert logcombine(2*log(z)*log(w)*log(x) + log(z) + log(w)) == \ log(z**log(w**2))*log(x) + log(w*z) assert logcombine(3*log(w) + 3*log(z)) == log(w**3*z**3) assert logcombine(x*(y + 1) + log(2) + log(3)) == x*(y + 1) + log(6) assert logcombine((x + y)*log(w) + (-x - y)*log(3)) == (x + y)*log(w/3)
def test_logcombine_1(): x, y = symbols("x,y") a = Symbol("a") z, w = symbols("z,w", positive=True) b = Symbol("b", real=True) assert logcombine(log(x) + 2 * log(y)) == log(x) + 2 * log(y) assert logcombine(log(x) + 2 * log(y), force=True) == log(x * y**2) assert logcombine(a * log(w) + log(z)) == a * log(w) + log(z) assert logcombine(b * log(z) + b * log(x)) == log(z**b) + b * log(x) assert logcombine(b * log(z) - log(w)) == log(z**b / w) assert logcombine(log(x) * log(z)) == log(x) * log(z) assert logcombine(log(w) * log(x)) == log(w) * log(x) assert logcombine(cos(-2 * log(z) + b * log(w))) in [ cos(log(w**b / z**2)), cos(log(z**2 / w**b)) ] assert logcombine(log(log(x) - log(y)) - log(z), force=True) == \ log(log(x/y)/z) assert logcombine((2 + I) * log(x), force=True) == (2 + I) * log(x) assert logcombine((x**2 + log(x) - log(y))/(x*y), force=True) == \ (x**2 + log(x/y))/(x*y) # the following could also give log(z*x**log(y**2)), what we # are testing is that a canonical result is obtained assert logcombine(log(x)*2*log(y) + log(z), force=True) == \ log(z*y**log(x**2)) assert logcombine( (x * y + sqrt(x**4 + y**4) + log(x) - log(y)) / (pi * x**Rational(2, 3) * sqrt(y)**3), force=True) == (x * y + sqrt(x**4 + y**4) + log(x / y)) / (pi * x**(S(2) / 3) * y**(S(3) / 2)) assert logcombine(gamma(-log(x/y))*acos(-log(x/y)), force=True) == \ acos(-log(x/y))*gamma(-log(x/y)) assert logcombine(2*log(z)*log(w)*log(x) + log(z) + log(w)) == \ log(z**log(w**2))*log(x) + log(w*z) assert logcombine(3 * log(w) + 3 * log(z)) == log(w**3 * z**3) assert logcombine(x * (y + 1) + log(2) + log(3)) == x * (y + 1) + log(6) assert logcombine((x + y) * log(w) + (-x - y) * log(3)) == (x + y) * log(w / 3)
def test_issue_5950(): x, y = symbols("x,y", positive=True) assert logcombine(log(3) - log(2)) == log(Rational(3,2), evaluate=False) assert logcombine(log(x) - log(y)) == log(x/y) assert logcombine(log(Rational(3,2), evaluate=False) - log(2)) == \ log(Rational(3,4), evaluate=False)
sympy.exp(I * (a - b) * x).expand(power_exp=True) # ## Factor # In[85]: sympy.factor(x**2 - 1) # In[86]: sympy.factor(x * sympy.cos(y) + sympy.sin(z) * x) # In[87]: sympy.logcombine(sympy.log(a) - sympy.log(b)) # In[88]: expr = x + y + x * y * z # In[89]: expr.factor() # In[90]: expr.collect(x) # In[91]:
print('expand:',sympy.expand((a * b)**x, power_base=True)) print('expand:',sympy.exp((a-b)*x).expand(power_exp=True)) # 因式分解、合并同类项, expr = sympy.factor(x**2 - 1) print('factor:',expr) # 三角函数因式分解 z = sympy.Symbol('z') expr = sympy.factor(x * sympy.cos(y) + sympy.sin(z) * x) print('factor:',expr) # 对数函数合并 a = sympy.Symbol('a') b = sympy.Symbol('b') expr = sympy.logcombine(sympy.log(a) - sympy.log(b)) print('logcombine:',expr) # 合并某个同类项 expr = x + y + x * y * z print('collect x:',expr.collect(x)) print('collect y:',expr.collect(y)) # 通过apart函数简化表达式 expr = 1/(x**2 + 3*x + 2) print('apart',sympy.apart(expr, x)) # 通过together函数简化表达式 print('together:',sympy.together(1 / (y * x + y) + 1 / (1+x))) # 通过cancel函数简化表达式
#%% sympy.exp((a - b) * x).expand( power_exp=True) #expending the exponent of a power expression #%% md ### Factor, collect, and combine ### #%% sympy.factor(x**2 - 1) #%% sympy.factor(x * sympy.cos(y) + sympy.sin(z) * x) #%% sympy.logcombine(sympy.log(a) - sympy.log(b)) #combine #%% expr = x + y + x * y * z expr.collect(x) #%% expr.collect(y) #%% expr = sympy.cos(x + y) + sympy.sin(x - y) expr.expand(trig=True).collect([sympy.cos(x), sympy.sin(x) ]).collect(sympy.cos(y) - sympy.sin(y)) #%% md ### Apart, together, and cancel ###
def mysimp(expr): from sympy import expand, logcombine, powsimp return expand( powsimp(logcombine(expr, force=True), force=True, deep=True), force=True).replace(exp_polar, exp)
def mysimp(expr): from sympy import expand, logcombine, powsimp return expand(powsimp(logcombine(expr, force=True), force=True, deep=True), force=True).replace(exp_polar, exp)
def eval(cls, arg): from sympy.calculus import AccumBounds from sympy.sets.setexpr import SetExpr from sympy.matrices.matrices import MatrixBase from sympy import im, logcombine, re if isinstance(arg, MatrixBase): return arg.exp() elif global_parameters.exp_is_pow: return Pow(S.Exp1, arg) elif arg.is_Number: if arg is S.NaN: return S.NaN elif arg.is_zero: return S.One elif arg is S.One: return S.Exp1 elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Zero elif arg is S.ComplexInfinity: return S.NaN elif isinstance(arg, log): return arg.args[0] elif isinstance(arg, AccumBounds): return AccumBounds(exp(arg.min), exp(arg.max)) elif isinstance(arg, SetExpr): return arg._eval_func(cls) elif arg.is_Mul: coeff = arg.as_coefficient(S.Pi * S.ImaginaryUnit) if coeff: if (2 * coeff).is_integer: if coeff.is_even: return S.One elif coeff.is_odd: return S.NegativeOne elif (coeff + S.Half).is_even: return -S.ImaginaryUnit elif (coeff + S.Half).is_odd: return S.ImaginaryUnit elif coeff.is_Rational: ncoeff = coeff % 2 # restrict to [0, 2pi) if ncoeff > 1: # restrict to (-pi, pi] ncoeff -= 2 if ncoeff != coeff: return cls(ncoeff * S.Pi * S.ImaginaryUnit) # Warning: code in risch.py will be very sensitive to changes # in this (see DifferentialExtension). # look for a single log factor coeff, terms = arg.as_coeff_Mul() # but it can't be multiplied by oo if coeff in [S.NegativeInfinity, S.Infinity]: if terms.is_number: if coeff is S.NegativeInfinity: terms = -terms if re(terms).is_zero and terms is not S.Zero: return S.NaN if re(terms).is_positive and im(terms) is not S.Zero: return S.ComplexInfinity if re(terms).is_negative: return S.Zero return None coeffs, log_term = [coeff], None for term in Mul.make_args(terms): term_ = logcombine(term) if isinstance(term_, log): if log_term is None: log_term = term_.args[0] else: return None elif term.is_comparable: coeffs.append(term) else: return None return log_term**Mul(*coeffs) if log_term else None elif arg.is_Add: out = [] add = [] argchanged = False for a in arg.args: if a is S.One: add.append(a) continue newa = cls(a) if isinstance(newa, cls): if newa.args[0] != a: add.append(newa.args[0]) argchanged = True else: add.append(a) else: out.append(newa) if out or argchanged: return Mul(*out) * cls(Add(*add), evaluate=False) if arg.is_zero: return S.One
def test_logcombine_complex_coeff(): i = Integral((sin(x**2) + cos(x**3))/x, x) assert logcombine(i, force=True) == i assert logcombine(i + 2*log(x), force=True) == \ i + log(x**2)
from sympy import I, pi, oo sympy.init_printing() x = sympy.Symbol("x") y = sympy.Symbol("y") z = sympy.Symbol("z") b = sympy.Symbol("a", positive=True) a = sympy.Symbol("b", positive=True) f = x**2 - 1 print(sympy.factor(f)) # (x - 1)*(x + 1) f = x * sympy.cos(y) + sympy.sin(y) * x print(sympy.factor(f)) # x*(sin(y) + cos(y)) f = sympy.log(a) - sympy.log(b) print(sympy.logcombine(f)) # log(b/a) f = x + y + x * y * z print(f.collect(x)) # x*(y*z + 1) + y print(f.collect(y)) # x + y*(x*z + 1) f = sympy.cos(x + y) + sympy.sin(x - y) print() print(f.expand(trig=True).collect([sympy.cos(x)])) # (-sin(y) + cos(y))*cos(x) - sin(x)*sin(y) + sin(x)*cos(y) print( f.expand(trig=True).collect( [sympy.cos(x), sympy.sin(x), sympy.sin(y), sympy.cos(y)])) # (-sin(y) + cos(y))*sin(x) + (-sin(y) + cos(y))*cos(x) print(
def test_issue_5950(): x, y = symbols("x,y", positive=True) assert logcombine(log(3) - log(2)) == log(Rational(3, 2), evaluate=False) assert logcombine(log(x) - log(y)) == log(x / y) assert logcombine(log(Rational(3,2), evaluate=False) - log(2)) == \ log(Rational(3,4), evaluate=False)
def eval(cls, arg): from sympy.assumptions import ask, Q from sympy.calculus import AccumBounds from sympy.sets.setexpr import SetExpr from sympy.matrices.matrices import MatrixBase from sympy import logcombine if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Zero: return S.One elif arg is S.One: return S.Exp1 elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Zero elif arg is S.ComplexInfinity: return S.NaN elif isinstance(arg, log): return arg.args[0] elif isinstance(arg, AccumBounds): return AccumBounds(exp(arg.min), exp(arg.max)) elif isinstance(arg, SetExpr): return arg._eval_func(cls) elif arg.is_Mul: if arg.is_number or arg.is_Symbol: coeff = arg.coeff(S.Pi*S.ImaginaryUnit) if coeff: if ask(Q.integer(2*coeff)): if ask(Q.even(coeff)): return S.One elif ask(Q.odd(coeff)): return S.NegativeOne elif ask(Q.even(coeff + S.Half)): return -S.ImaginaryUnit elif ask(Q.odd(coeff + S.Half)): return S.ImaginaryUnit # Warning: code in risch.py will be very sensitive to changes # in this (see DifferentialExtension). # look for a single log factor coeff, terms = arg.as_coeff_Mul() # but it can't be multiplied by oo if coeff in [S.NegativeInfinity, S.Infinity]: return None coeffs, log_term = [coeff], None for term in Mul.make_args(terms): term_ = logcombine(term) if isinstance(term_, log): if log_term is None: log_term = term_.args[0] else: return None elif term.is_comparable: coeffs.append(term) else: return None return log_term**Mul(*coeffs) if log_term else None elif arg.is_Add: out = [] add = [] for a in arg.args: if a is S.One: add.append(a) continue newa = cls(a) if isinstance(newa, cls): add.append(a) else: out.append(newa) if out: return Mul(*out)*cls(Add(*add), evaluate=False) elif isinstance(arg, MatrixBase): return arg.exp()
def test_logcombine_complex_coeff(): i = Integral((sin(x**2) + cos(x**3)) / x, x) assert logcombine(i, force=True) == i assert logcombine(i + 2*log(x), force=True) == \ i + log(x**2)
def eval(cls, arg): from sympy.assumptions import ask, Q from sympy.calculus import AccumBounds from sympy.sets.setexpr import SetExpr from sympy.matrices.matrices import MatrixBase from sympy import logcombine if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Zero: return S.One elif arg is S.One: return S.Exp1 elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Zero elif arg is S.ComplexInfinity: return S.NaN elif isinstance(arg, log): return arg.args[0] elif isinstance(arg, AccumBounds): return AccumBounds(exp(arg.min), exp(arg.max)) elif isinstance(arg, SetExpr): return arg._eval_func(cls) elif arg.is_Mul: if arg.is_number or arg.is_Symbol: coeff = arg.coeff(S.Pi * S.ImaginaryUnit) if coeff: if ask(Q.integer(2 * coeff)): if ask(Q.even(coeff)): return S.One elif ask(Q.odd(coeff)): return S.NegativeOne elif ask(Q.even(coeff + S.Half)): return -S.ImaginaryUnit elif ask(Q.odd(coeff + S.Half)): return S.ImaginaryUnit # Warning: code in risch.py will be very sensitive to changes # in this (see DifferentialExtension). # look for a single log factor coeff, terms = arg.as_coeff_Mul() # but it can't be multiplied by oo if coeff in [S.NegativeInfinity, S.Infinity]: return None coeffs, log_term = [coeff], None for term in Mul.make_args(terms): term_ = logcombine(term) if isinstance(term_, log): if log_term is None: log_term = term_.args[0] else: return None elif term.is_comparable: coeffs.append(term) else: return None return log_term**Mul(*coeffs) if log_term else None elif arg.is_Add: out = [] add = [] for a in arg.args: if a is S.One: add.append(a) continue newa = cls(a) if isinstance(newa, cls): add.append(a) else: out.append(newa) if out: return Mul(*out) * cls(Add(*add), evaluate=False) elif isinstance(arg, MatrixBase): return arg.exp()
def _eval_nseries(self, x, n, logx, cdir=0): # NOTE Please see the comment at the beginning of this file, labelled # IMPORTANT. from sympy import im, cancel, I, Order, logcombine from itertools import product if not logx: logx = log(x) if self.args[0] == x: return logx arg = self.args[0] k, l = Wild("k"), Wild("l") r = arg.match(k * x**l) if r is not None: k, l = r[k], r[l] if l != 0 and not l.has(x) and not k.has(x): r = log(k) + l * logx # XXX true regardless of assumptions? return r def coeff_exp(term, x): coeff, exp = S.One, S.Zero for factor in Mul.make_args(term): if factor.has(x): base, exp = factor.as_base_exp() if base != x: try: return term.leadterm(x) except ValueError: return term, S.Zero else: coeff *= factor return coeff, exp # TODO new and probably slow try: a, b = arg.leadterm(x) s = arg.nseries(x, n=n + b, logx=logx) except (ValueError, NotImplementedError): s = arg.nseries(x, n=n, logx=logx) while s.is_Order: n += 1 s = arg.nseries(x, n=n, logx=logx) a, b = s.removeO().leadterm(x) p = cancel(s / (a * x**b) - 1).expand().powsimp() if p.has(exp): p = logcombine(p) if isinstance(p, Order): n = p.getn() _, d = coeff_exp(p, x) if not d.is_positive: return log(a) + b * logx + Order(x**n, x) def mul(d1, d2): res = {} for e1, e2 in product(d1, d2): ex = e1 + e2 if ex < n: res[ex] = res.get(ex, S.Zero) + d1[e1] * d2[e2] return res pterms = {} for term in Add.make_args(p): co1, e1 = coeff_exp(term, x) pterms[e1] = pterms.get(e1, S.Zero) + co1.removeO() k = S.One terms = {} pk = pterms while k * d < n: coeff = -(-1)**k / k for ex in pk: terms[ex] = terms.get(ex, S.Zero) + coeff * pk[ex] pk = mul(pk, pterms) k += S.One res = log(a) + b * logx for ex in terms: res += terms[ex] * x**(ex) if cdir != 0: cdir = self.args[0].dir(x, cdir) if a.is_real and a.is_negative and im(cdir) < 0: res -= 2 * I * S.Pi return res + Order(x**n, x)
#### 인수 구분 #### print(">>> 수식 전개 <<<") expr = x**2 -1 print(expr) print(sympy.factor(expr)) expr = x * sympy.cos(y) + sympy.sin(z) * x print(expr) print(sympy.factor(expr)) print(sympy.trigsimp(expr)) print("\n"+">>> 로그함수 병합 <<<") expr = sympy.log(a) - sympy.log(b) print(expr) print(sympy.factor(expr)) print(sympy.logcombine(expr)) print("\n"+">>> 기호 전개 <<<") expr = x + y + x*y*z print(expr) print(expr.collect(x)) print("\n"+">>> 기호 전개 응용<<<") expr = sympy.cos(x + y) + sympy.sin(x - y) print(expr) print(expr.expand(trig=True)) print(expr.expand(trig=True).collect([sympy.cos(x), sympy.sin(x)])) print(expr.expand(trig=True).collect([sympy.cos(x), sympy.sin(x)]).collect( sympy.cos(y) - sympy.sin(y))) # 위와 같이 기호 전개를 체인콜 시키는게 가능하다!