def as_real_imag(self, deep=True, **hints): """ Returns this function as a 2-tuple representing a complex number. Examples ======== >>> from sympy import I >>> from sympy.abc import x >>> from sympy.functions import exp >>> exp(x).as_real_imag() (exp(re(x))*cos(im(x)), exp(re(x))*sin(im(x))) >>> exp(1).as_real_imag() (E, 0) >>> exp(I).as_real_imag() (cos(1), sin(1)) >>> exp(1+I).as_real_imag() (E*cos(1), E*sin(1)) See Also ======== sympy.functions.elementary.complexes.re sympy.functions.elementary.complexes.im """ re, im = self.args[0].as_real_imag() if deep: re = re.expand(deep, **hints) im = im.expand(deep, **hints) cos, sin = C.cos(im), C.sin(im) return (exp(re)*cos, exp(re)*sin)
def eval(cls, arg): arg = sympify(arg) if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Zero: return S.Zero elif arg is S.One: return S.Infinity elif arg is S.NegativeOne: return S.NegativeInfinity elif arg is S.Infinity: return -S.ImaginaryUnit * C.atan(arg) elif arg is S.NegativeInfinity: return S.ImaginaryUnit * C.atan(-arg) elif arg.is_negative: return -cls(-arg) else: if arg is S.ComplexInfinity: return S.NaN i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return S.ImaginaryUnit * C.atan(i_coeff) else: if _coeff_isneg(arg): return -cls(-arg)
def _eval_expand_complex(self, deep=True, **hints): re, im = self.args[0].as_real_imag() if deep: re = re.expand(deep, **hints) im = im.expand(deep, **hints) cos, sin = C.cos(im), C.sin(im) return exp(re) * cos + S.ImaginaryUnit * exp(re) * sin
def as_real_imag(self, deep=True, **hints): """ Returns this function as a complex coordinate. Examples ======== >>> from sympy import I >>> from sympy.abc import x >>> from sympy.functions import log >>> log(x).as_real_imag() (log(Abs(x)), arg(x)) >>> log(I).as_real_imag() (0, pi/2) >>> log(1+I).as_real_imag() (log(sqrt(2)), pi/4) >>> log(I*x).as_real_imag() (log(Abs(x)), arg(I*x)) """ if deep: abs = C.Abs(self.args[0].expand(deep, **hints)) arg = C.arg(self.args[0].expand(deep, **hints)) else: abs = C.Abs(self.args[0]) arg = C.arg(self.args[0]) if hints.get('log', False): # Expand the log hints['complex'] = False return (log(abs).expand(deep, **hints), arg) else: return (log(abs), arg)
def vertices(self): points = [] c, r, n = self v = 2*S.Pi/n for k in xrange(0, n): points.append( Point(c[0] + r*C.cos(k*v), c[1] + r*C.sin(k*v)) ) return points
def vertices(self): """The vertices of the regular polygon. Returns ------- vertices : list Each vertex is a Point. See Also -------- Point Examples -------- >>> from sympy.geometry import RegularPolygon, Point >>> rp = RegularPolygon(Point(0, 0), 5, 4) >>> rp.vertices [Point(5, 0), Point(0, 5), Point(-5, 0), Point(0, -5)] """ points = [] c, r, n = self v = 2*S.Pi/n for k in xrange(0, n): points.append(Point(c[0] + r*C.cos(k*v), c[1] + r*C.sin(k*v))) return points
def arbitrary_point(self, parameter_name='t'): """A parametric point on the ellipse. Parameters ---------- parameter_name : str, optional Default value is 't'. Returns ------- arbitrary_point : Point See Also -------- Point Examples -------- >>> from sympy import Point, Ellipse >>> e1 = Ellipse(Point(0, 0), 3, 2) >>> e1.arbitrary_point() Point(3*cos(t), 2*sin(t)) """ t = C.Symbol(parameter_name, real=True) return Point(self.center[0] + self.hradius*C.cos(t), self.center[1] + self.vradius*C.sin(t))
def monomial_count(V, N): r""" Computes the number of monomials. The number of monomials is given by the following formula: .. math:: \frac{(\#V + N)!}{\#V! N!} where `N` is a total degree and `V` is a set of variables. Examples ======== >>> from sympy.polys.monomials import itermonomials, monomial_count >>> from sympy.polys.orderings import monomial_key >>> from sympy.abc import x, y >>> monomial_count(2, 2) 6 >>> M = itermonomials([x, y], 2) >>> sorted(M, key=monomial_key('grlex', [y, x])) [1, x, y, x**2, x*y, y**2] >>> len(M) 6 """ return C.factorial(V + N) / C.factorial(V) / C.factorial(N)
def arbitrary_point(self, parameter='t'): """A parameterized point on the ellipse. Parameters ---------- parameter : str, optional Default value is 't'. Returns ------- arbitrary_point : Point Raises ------ ValueError When `parameter` already appears in the functions. See Also -------- Point Examples -------- >>> from sympy import Point, Ellipse >>> e1 = Ellipse(Point(0, 0), 3, 2) >>> e1.arbitrary_point() Point(3*cos(t), 2*sin(t)) """ t = _symbol(parameter) if t.name in (f.name for f in self.free_symbols): raise ValueError('Symbol %s already appears in object and cannot be used as a parameter.' % t.name) return Point(self.center[0] + self.hradius*C.cos(t), self.center[1] + self.vradius*C.sin(t))
def monomial_count(V, N): r""" Computes the number of monomials. The number of monomials is given by the following formula: .. math:: \frac{(\#V + N)!}{\#V! N!} where `N` is a total degree and `V` is a set of variables. **Examples** >>> from sympy import monomials, monomial_count >>> from sympy.abc import x, y >>> monomial_count(2, 2) 6 >>> M = monomials([x, y], 2) >>> sorted(M) [1, x, y, x**2, y**2, x*y] >>> len(M) 6 """ return C.factorial(V + N) / C.factorial(V) / C.factorial(N)
def eval(cls, z, a=S.One): z, a = map(sympify, (z, a)) if a.is_Number: if a is S.NaN: return S.NaN elif a is S.Zero: return cls(z) if z.is_Number: if z is S.NaN: return S.NaN elif z is S.Infinity: return S.One elif z is S.Zero: if a.is_negative: return S.Half - a - 1 else: return S.Half - a elif z is S.One: return S.ComplexInfinity elif z.is_Integer: if a.is_Integer: if z.is_negative: zeta = (-1)**z * C.bernoulli(-z+1)/(-z+1) elif z.is_even: B, F = C.bernoulli(z), C.factorial(z) zeta = 2**(z-1) * abs(B) * pi**z / F else: return if a.is_negative: return zeta + C.harmonic(abs(a), z) else: return zeta - C.harmonic(a-1, z)
def eval(cls, arg): arg = sympify(arg) if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.NegativeInfinity elif arg is S.Zero: return S.Zero elif arg is S.One: return C.log(2**S.Half + 1) elif arg is S.NegativeOne: return C.log(2**S.Half - 1) elif arg.is_negative: return -cls(-arg) else: i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return S.ImaginaryUnit * C.asin(i_coeff) else: if arg.as_coeff_mul()[0].is_negative: return -cls(-arg)
def as_real_imag(self, deep=True, **hints): re, im = self.args[0].as_real_imag() if deep: re = re.expand(deep, **hints) im = im.expand(deep, **hints) cos, sin = C.cos(im), C.sin(im) return (exp(re) * cos, exp(re) * sin)
def eval(cls, arg): from sympy.simplify.simplify import signsimp if hasattr(arg, '_eval_Abs'): obj = arg._eval_Abs() if obj is not None: return obj # handle what we can arg = signsimp(arg, evaluate=False) if arg.is_Mul: known = [] unk = [] for t in arg.args: tnew = cls(t) if tnew.func is cls: unk.append(tnew.args[0]) else: known.append(tnew) known = Mul(*known) unk = cls(Mul(*unk), evaluate=False) if unk else S.One return known*unk if arg is S.NaN: return S.NaN if arg.is_Pow: base, exponent = arg.as_base_exp() if base.is_real: if exponent.is_integer: if exponent.is_even: return arg if base is S.NegativeOne: return S.One if base.func is cls and exponent is S.NegativeOne: return arg return Abs(base)**exponent if base.is_positive == True: return base**re(exponent) return (-base)**re(exponent)*C.exp(-S.Pi*im(exponent)) if isinstance(arg, C.exp): return C.exp(re(arg.args[0])) if arg.is_zero: # it may be an Expr that is zero return S.Zero if arg.is_nonnegative: return arg if arg.is_nonpositive: return -arg if arg.is_imaginary: arg2 = -S.ImaginaryUnit * arg if arg2.is_nonnegative: return arg2 if arg.is_Add: if arg.has(S.Infinity, S.NegativeInfinity): if any(a.is_infinite for a in arg.as_real_imag()): return S.Infinity if arg.is_real is None and arg.is_imaginary is None: if all(a.is_real or a.is_imaginary or (S.ImaginaryUnit*a).is_real for a in arg.args): from sympy import expand_mul return sqrt(expand_mul(arg*arg.conjugate())) if arg.is_real is False and arg.is_imaginary is False: from sympy import expand_mul return sqrt(expand_mul(arg*arg.conjugate()))
def real_root(arg, n=None): """Return the real nth-root of arg if possible. If n is omitted then all instances of (-n)**(1/odd) will be changed to -n**(1/odd); this will only create a real root of a principle root -- the presence of other factors may cause the result to not be real. Examples ======== >>> from sympy import root, real_root, Rational >>> from sympy.abc import x, n >>> real_root(-8, 3) -2 >>> root(-8, 3) 2*(-1)**(1/3) >>> real_root(_) -2 If one creates a non-principle root and applies real_root, the result will not be real (so use with caution): >>> root(-8, 3, 2) -2*(-1)**(2/3) >>> real_root(_) -2*(-1)**(2/3) See Also ======== sympy.polys.rootoftools.RootOf sympy.core.power.integer_nthroot root, sqrt """ if n is not None: try: n = as_int(n) arg = sympify(arg) if arg.is_positive or arg.is_negative: rv = root(arg, n) else: raise ValueError except ValueError: return root(arg, n)*C.Piecewise( (S.One, ~C.Equality(C.im(arg), 0)), (C.Pow(S.NegativeOne, S.One/n)**(2*C.floor(n/2)), C.And( C.Equality(n % 2, 1), arg < 0)), (S.One, True)) else: rv = sympify(arg) n1pow = Transform(lambda x: -(-x.base)**x.exp, lambda x: x.is_Pow and x.base.is_negative and x.exp.is_Rational and x.exp.p == 1 and x.exp.q % 2) return rv.xreplace(n1pow)
def eval(cls, n, z): n, z = list(map(sympify, (n, z))) from sympy import unpolarify if n.is_integer: if n.is_nonnegative: nz = unpolarify(z) if z != nz: return polygamma(n, nz) if n == -1: return loggamma(z) else: if z.is_Number: if z is S.NaN: return S.NaN elif z is S.Infinity: if n.is_Number: if n is S.Zero: return S.Infinity else: return S.Zero elif z.is_Integer: if z.is_nonpositive: return S.ComplexInfinity else: if n is S.Zero: return -S.EulerGamma + C.harmonic(z - 1, 1) elif n.is_odd: return (-1) ** (n + 1) * C.factorial(n) * zeta(n + 1, z) if n == 0: if z is S.NaN: return S.NaN elif z.is_Rational: # TODO actually *any* n/m can be done, but that is messy lookup = { S(1) / 2: -2 * log(2) - S.EulerGamma, S(1) / 3: -S.Pi / 2 / sqrt(3) - 3 * log(3) / 2 - S.EulerGamma, S(1) / 4: -S.Pi / 2 - 3 * log(2) - S.EulerGamma, S(3) / 4: -3 * log(2) - S.EulerGamma + S.Pi / 2, S(2) / 3: -3 * log(3) / 2 + S.Pi / 2 / sqrt(3) - S.EulerGamma, } if z > 0: n = floor(z) z0 = z - n if z0 in lookup: return lookup[z0] + Add(*[1 / (z0 + k) for k in range(n)]) elif z < 0: n = floor(1 - z) z0 = z + n if z0 in lookup: return lookup[z0] - Add(*[1 / (z0 - 1 - k) for k in range(n)]) elif z in (S.Infinity, S.NegativeInfinity): return S.Infinity else: t = z.extract_multiplicatively(S.ImaginaryUnit) if t in (S.Infinity, S.NegativeInfinity): return S.Infinity
def eval(cls, arg): arg = sympify(arg) if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Infinity elif arg is S.Zero: return S.Pi*S.ImaginaryUnit / 2 elif arg is S.One: return S.Zero elif arg is S.NegativeOne: return S.Pi*S.ImaginaryUnit if arg.is_number: cst_table = { S.ImaginaryUnit : C.log(S.ImaginaryUnit*(1+sqrt(2))), -S.ImaginaryUnit : C.log(-S.ImaginaryUnit*(1+sqrt(2))), S.Half : S.Pi/3, -S.Half : 2*S.Pi/3, sqrt(2)/2 : S.Pi/4, -sqrt(2)/2 : 3*S.Pi/4, 1/sqrt(2) : S.Pi/4, -1/sqrt(2) : 3*S.Pi/4, sqrt(3)/2 : S.Pi/6, -sqrt(3)/2 : 5*S.Pi/6, (sqrt(3)-1)/sqrt(2**3) : 5*S.Pi/12, -(sqrt(3)-1)/sqrt(2**3) : 7*S.Pi/12, sqrt(2+sqrt(2))/2 : S.Pi/8, -sqrt(2+sqrt(2))/2 : 7*S.Pi/8, sqrt(2-sqrt(2))/2 : 3*S.Pi/8, -sqrt(2-sqrt(2))/2 : 5*S.Pi/8, (1+sqrt(3))/(2*sqrt(2)) : S.Pi/12, -(1+sqrt(3))/(2*sqrt(2)) : 11*S.Pi/12, (sqrt(5)+1)/4 : S.Pi/5, -(sqrt(5)+1)/4 : 4*S.Pi/5 } if arg in cst_table: if arg.is_real: return cst_table[arg]*S.ImaginaryUnit return cst_table[arg] if arg is S.ComplexInfinity: return S.Infinity i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: if _coeff_isneg(i_coeff): return S.ImaginaryUnit * C.acos(i_coeff) return S.ImaginaryUnit * C.acos(-i_coeff) else: if _coeff_isneg(arg): return -cls(-arg)
def _eval_aseries(self, n, args0, x, logx): if args0[0] != S.Infinity: return super(_erfs, self)._eval_aseries(n, args0, x, logx) z = self.args[0] l = [ 1/sqrt(S.Pi) * C.factorial(2*k)*(-S(4))**(-k)/C.factorial(k) * (1/z)**(2*k+1) for k in xrange(0,n) ] o = C.Order(1/z**(2*n+1), x) # It is very inefficient to first add the order and then do the nseries return (Add(*l))._eval_nseries(x, n, logx) + o
def eval(cls, a, x): if a.is_Number: if a is S.One: return S.One - C.exp(-x) elif a.is_Integer: b = a - 1 if b.is_positive: return b*cls(b, x) - x**b * C.exp(-x)
def eval(cls, n): if (n.is_Integer and n.is_nonnegative) or \ (n.is_noninteger and n.is_negative): return 4**n*C.gamma(n + S.Half)/(C.gamma(S.Half)*C.gamma(n + 2)) if (n.is_integer and n.is_negative): if (n + 1).is_negative: return S.Zero if (n + 1).is_zero: return -S.Half
def taylor_term(n, x, *previous_terms): if n < 0 or n % 2 == 0: return S.Zero else: x = sympify(x) k = C.floor((n - 1)/S(2)) if len(previous_terms) > 2: return -previous_terms[-2] * x**2 * (n - 2)/(n*k) else: return 2*(-1)**k * x**n/(n*C.factorial(k)*sqrt(S.Pi))
def eval(cls, r, k): r, k = map(sympify, (r, k)) if k.is_Number: if k is S.Zero: return S.One elif k.is_Integer: if k.is_negative: return S.Zero else: if r.is_Integer and r.is_nonnegative: r, k = int(r), int(k) if k > r: return S.Zero elif k > r // 2: k = r - k M, result = int(sqrt(r)), 1 for prime in sieve.primerange(2, r + 1): if prime > r - k: result *= prime elif prime > r // 2: continue elif prime > M: if r % prime < k % prime: result *= prime else: R, K = r, k exp = a = 0 while R > 0: a = int((R % prime) < (K % prime + a)) R, K = R // prime, K // prime exp = a + exp if exp > 0: result *= prime ** exp return C.Integer(result) else: result = r - k + 1 for i in xrange(2, k + 1): result *= r - k + i result /= i return result if k.is_integer: if k.is_negative: return S.Zero else: return C.gamma(r + 1) / (C.gamma(r - k + 1) * C.gamma(k + 1))
def separate(expr, deep=False): """Rewrite or separate a power of product to a product of powers but without any expanding, ie. rewriting products to summations. >>> from sympy import * >>> x, y, z = symbols('x', 'y', 'z') >>> separate((x*y)**2) x**2*y**2 >>> separate((x*(y*z)**3)**2) x**2*y**6*z**6 >>> separate((x*sin(x))**y + (x*cos(x))**y) x**y*cos(x)**y + x**y*sin(x)**y #this does not work because of exp combining #>>> separate((exp(x)*exp(y))**x) #exp(x*y)*exp(x**2) >>> separate((sin(x)*cos(x))**y) cos(x)**y*sin(x)**y Notice that summations are left un touched. If this is not the requested behaviour, apply 'expand' to input expression before: >>> separate(((x+y)*z)**2) z**2*(x + y)**2 >>> separate((x*y)**(1+z)) x**(1 + z)*y**(1 + z) """ expr = sympify(expr) if expr.is_Pow: terms, expo = [], separate(expr.exp, deep) if expr.base.is_Mul: t = [ separate(C.Pow(t,expo), deep) for t in expr.base.args ] return C.Mul(*t) elif expr.base.func is C.exp: if deep == True: return C.exp(separate(expr.base[0], deep)*expo) else: return C.exp(expr.base[0]*expo) else: return C.Pow(separate(expr.base, deep), expo) elif expr.is_Add or expr.is_Mul: return type(expr)(*[ separate(t, deep) for t in expr.args ]) elif expr.is_Function and deep: return expr.func(*[ separate(t) for t in expr.args]) else: return expr
def fdiff(self, argindex=1): if argindex == 1: # http://functions.wolfram.com/GammaBetaErf/Binomial/20/01/01/ n, k = self.args return binomial(n, k)*(C.polygamma(0, n + 1) - C.polygamma(0, n - k + 1)) elif argindex == 2: # http://functions.wolfram.com/GammaBetaErf/Binomial/20/01/02/ n, k = self.args return binomial(n, k)*(C.polygamma(0, n - k + 1) - C.polygamma(0, k + 1)) else: raise ArgumentIndexError(self, argindex)
def as_real_imag(self, deep=True, **hints): if deep: abs = C.Abs(self.args[0].expand(deep, **hints)) arg = C.arg(self.args[0].expand(deep, **hints)) else: abs = C.Abs(self.args[0]) arg = C.arg(self.args[0]) if hints.get("log", False): # Expand the log hints["complex"] = False return (log(abs).expand(deep, **hints), arg) else: return (log(abs), arg)
def as_real_imag(self, deep=True, **hints): if self.args[0].is_real: if deep: return (self.expand(deep, **hints), S.Zero) else: return (self, S.Zero) if deep: re, im = self.args[0].expand(deep, **hints).as_real_imag() else: re, im = self.args[0].as_real_imag() denom = sinh(re)**2 + C.sin(im)**2 return (sinh(re)*cosh(re)/denom, -C.sin(im)*C.cos(im)/denom)
def as_real_imag(self, deep=True, **hints): if self.args[0].is_real: if deep: hints['complex'] = False return (self.expand(deep, **hints), S.Zero) else: return (self, S.Zero) if deep: re, im = self.args[0].expand(deep, **hints).as_real_imag() else: re, im = self.args[0].as_real_imag() return (sinh(re)*C.cos(im), cosh(re)*C.sin(im))
def _eval_expand_complex(self, deep=True, **hints): if deep: abs = C.abs(self.args[0].expand(deep, **hints)) arg = C.arg(self.args[0].expand(deep, **hints)) else: abs = C.abs(self.args[0]) arg = C.arg(self.args[0]) if hints['log']: # Expand the log hints['complex'] = False return log(abs).expand(deep, **hints) + S.ImaginaryUnit * arg else: return log(abs) + S.ImaginaryUnit * arg
def taylor_term(n, x, *previous_terms): if n == 0: return 1 / sympify(x) elif n < 0 or n % 2 == 0: return S.Zero else: x = sympify(x) B = C.bernoulli(n+1) F = C.factorial(n+1) return 2**(n+1) * B/F * x**n
def as_real_imag(self, deep=True, **hints): if deep: abs = C.abs(self.args[0].expand(deep, **hints)) arg = C.arg(self.args[0].expand(deep, **hints)) else: abs = C.abs(self.args[0]) arg = C.arg(self.args[0]) if hints['log']: # Expand the log hints['complex'] = False return (log(abs).expand(deep, **hints), arg) else: return (log(abs), arg)
def fdiff(self, argindex=1): n = self.args[0] return catalan(n) * (C.polygamma(0, n + Rational(1, 2)) - C.polygamma(0, n + 2) + C.log(4))
def _eval_rewrite_as_gamma(self, n): return C.gamma(n + 1)
def _eval_rewrite_as_gamma(self, x, k): return (-1)**k * C.gamma(-x + k) / C.gamma(-x)
def _eval_rewrite_as_Heaviside(self, arg): # Note this only holds for real arg (since Heaviside is not defined # for complex arguments). if arg.is_real: return arg*(C.Heaviside(arg) - C.Heaviside(-arg))
def _eval_rewrite_as_exp(self, arg): return (C.exp(arg) + C.exp(-arg)) / 2
def _eval_rewrite_as_exp(self, arg): neg_exp, pos_exp = C.exp(-arg), C.exp(arg) return (pos_exp + neg_exp) / (pos_exp - neg_exp)
def _eval_rewrite_as_tanh(self, arg): return (1 + C.tanh(arg/2))/(1 - C.tanh(arg/2))
def root(arg, n): """The n-th root function (a shortcut for ``arg**(1/n)``) root(x, n) -> Returns the principal n-th root of x. Examples ======== >>> from sympy import root, Rational >>> from sympy.abc import x, n >>> root(x, 2) sqrt(x) >>> root(x, 3) x**(1/3) >>> root(x, n) x**(1/n) >>> root(x, -Rational(2, 3)) x**(-3/2) To get all n n-th roots you can use the RootOf function. The following examples show the roots of unity for n equal 2, 3 and 4: >>> from sympy import RootOf, I >>> [ RootOf(x**2-1,i) for i in (0,1) ] [-1, 1] >>> [ RootOf(x**3-1,i) for i in (0,1,2) ] [1, -1/2 - sqrt(3)*I/2, -1/2 + sqrt(3)*I/2] >>> [ RootOf(x**4-1,i) for i in (0,1,2,3) ] [-1, 1, -I, I] SymPy, like other symbolic algebra systems, returns the complex root of negative numbers. This is the principal root and differs from the text-book result that one might be expecting. For example, the cube root of -8 does not come back as -2: >>> root(-8, 3) 2*(-1)**(1/3) The real_root function can be used to either make such a result real or simply return the real root in the first place: >>> from sympy import real_root >>> real_root(_) -2 >>> real_root(-32, 5) -2 See Also ======== sympy.polys.rootoftools.RootOf sympy.core.power.integer_nthroot sqrt, real_root References ========== * http://en.wikipedia.org/wiki/Square_root * http://en.wikipedia.org/wiki/Real_root * http://en.wikipedia.org/wiki/Root_of_unity * http://en.wikipedia.org/wiki/Principal_value * http://mathworld.wolfram.com/CubeRoot.html """ n = sympify(n) return C.Pow(arg, 1/n)
def fdiff(self, argindex=1): if argindex == 1: return C.gamma(self.args[0] + 1) * C.polygamma(0, self.args[0] + 1) else: raise ArgumentIndexError(self, argindex)
def sqrt(arg): """The square root function sqrt(x) -> Returns the principal square root of x. Examples ======== >>> from sympy import sqrt, Symbol >>> x = Symbol('x') >>> sqrt(x) sqrt(x) >>> sqrt(x)**2 x Note that sqrt(x**2) does not simplify to x. >>> sqrt(x**2) sqrt(x**2) This is because the two are not equal to each other in general. For example, consider x == -1: >>> from sympy import Eq >>> Eq(sqrt(x**2), x).subs(x, -1) False This is because sqrt computes the principal square root, so the square may put the argument in a different branch. This identity does hold if x is positive: >>> y = Symbol('y', positive=True) >>> sqrt(y**2) y You can force this simplification by using the powdenest() function with the force option set to True: >>> from sympy import powdenest >>> sqrt(x**2) sqrt(x**2) >>> powdenest(sqrt(x**2), force=True) x To get both branches of the square root you can use the RootOf function: >>> from sympy import RootOf >>> [ RootOf(x**2-3,i) for i in (0,1) ] [-sqrt(3), sqrt(3)] See Also ======== sympy.polys.rootoftools.RootOf, root, real_root References ========== * http://en.wikipedia.org/wiki/Square_root * http://en.wikipedia.org/wiki/Principal_value """ # arg = sympify(arg) is handled by Pow return C.Pow(arg, S.Half)
def _eval_rewrite_as_factorial(self, n, k): return C.factorial(n) / (C.factorial(k) * C.factorial(n - k))
def _eval_rewrite_as_tractable(self, z): return S.One - _erfs(z) * C.exp(-z**2)
def eval(cls, n): if n.is_Integer and n.is_nonnegative: return 4**n * C.gamma(n + S.Half) / (C.gamma(S.Half) * C.gamma(n + 2))
def _eval_rewrite_as_cos(self, arg): I = S.ImaginaryUnit return C.cos(I*arg) + I*C.cos(I*arg + S.Pi/2)
def _eval_rewrite_as_Sum(self, n, m=None): k = C.Dummy("k", integer=True) if m is None: m = S.One return C.Sum(k**(-m), (k, 1, n))
def _eval_rewrite_as_sin(self, arg): I = S.ImaginaryUnit return C.sin(I*arg + S.Pi/2) - I*C.sin(I*arg)
def _eval_rewrite_as_intractable(self, z): return (S.One - erf(z)) * C.exp(z**2)
def _eval_rewrite_as_Heaviside(self, arg): if arg.is_real: return C.Heaviside(arg)*2-1
def _eval_rewrite_as_sign(self, arg): return arg/C.sign(arg)
def pde_1st_linear_constant_coeff(eq, func, order, match, solvefun): r""" Solves a first order linear partial differential equation with constant coefficients. The general form of this partial differential equation is .. math:: a \frac{df(x,y)}{dx} + b \frac{df(x,y)}{dy} + c f(x,y) = G(x,y) where `a`, `b` and `c` are constants and `G(x, y)` can be an arbitrary function in `x` and `y`. The general solution of the PDE is:: >>> from sympy.solvers import pdsolve >>> from sympy.abc import x, y, a, b, c >>> from sympy import Function, pprint >>> f = Function('f') >>> G = Function('G') >>> u = f(x,y) >>> ux = u.diff(x) >>> uy = u.diff(y) >>> genform = a*u + b*ux + c*uy - G(x,y) >>> pprint(genform) d d a*f(x, y) + b*--(f(x, y)) + c*--(f(x, y)) - G(x, y) dx dy >>> pprint(pdsolve(genform, hint='1st_linear_constant_coeff_Integral')) // b*x + c*y \ || / | || | | || | a*xi | || | ------- | || | 2 2 | || | /b*xi + c*eta -b*eta + c*xi\ b + c | || | G|------------, -------------|*e d(xi)| || | | 2 2 2 2 | | || | \ b + c b + c / | || | | || / | || | f(x, y) = ||F(eta) + -------------------------------------------------------|* || 2 2 | \\ b + c / <BLANKLINE> \| || || || || || || || || -a*xi || -------|| 2 2|| b + c || e || || /|eta=-b*y + c*x, xi=b*x + c*y Examples ======== >>> from sympy.solvers.pde import pdsolve >>> from sympy import Function, diff, pprint, exp >>> from sympy.abc import x,y >>> f = Function('f') >>> eq = -2*f(x,y).diff(x) + 4*f(x,y).diff(y) + 5*f(x,y) - exp(x + 3*y) >>> pdsolve(eq) f(x, y) == (F(4*x + 2*y) + exp(x/2 + 4*y)/15)*exp(x/2 - y) References ========== - Viktor Grigoryan, "Partial Differential Equations" Math 124A - Fall 2010, pp.7 """ # TODO : For now homogeneous first order linear PDE's having # two variables are implemented. Once there is support for # solving systems of ODE's, this can be extended to n variables. xi, eta = symbols("xi eta") f = func.func x = func.args[0] y = func.args[1] b = match[match['b']] c = match[match['c']] d = match[match['d']] e = -match[match['e']] expterm = exp(-S(d) / (b**2 + c**2) * xi) functerm = solvefun(eta) solvedict = solve((b * x + c * y - xi, c * x - b * y - eta), x, y) # Integral should remain as it is in terms of xi, # doit() should be done in _handle_Integral. genterm = (1 / S(b**2 + c**2)) * C.Integral( (1 / expterm * e).subs(solvedict), (xi, b * x + c * y)) return Eq( f(x, y), Subs(expterm * (functerm + genterm), (eta, xi), (c * x - b * y, b * x + c * y)))
def eval(cls, s): if s == 1: return C.log(2) else: return (1-2**(1-s)) * zeta(s)
def _eval_rewrite_as_gamma(self, x, k): return C.gamma(x + k) / C.gamma(x)
def _eval_rewrite_as_uppergamma(self, z): return sqrt(z** 2) / z * (S.One - C.uppergamma(S.Half, z**2) / sqrt(S.Pi))
def limit(e, z, z0, dir="+"): """ Compute the limit of e(z) at the point z0. z0 can be any expression, including oo and -oo. For dir="+" (default) it calculates the limit from the right (z->z0+) and for dir="-" the limit from the left (z->z0-). For infinite z0 (oo or -oo), the dir argument doesn't matter. Examples: >>> from sympy import limit, sin, Symbol, oo >>> from sympy.abc import x >>> limit(sin(x)/x, x, 0) 1 >>> limit(1/x, x, 0, dir="+") oo >>> limit(1/x, x, 0, dir="-") -oo >>> limit(1/x, x, oo) 0 Strategy: First we try some heuristics for easy and frequent cases like "x", "1/x", "x**2" and similar, so that it's fast. For all other cases, we use the Gruntz algorithm (see the gruntz() function). """ from sympy import Wild, log e = sympify(e) z = sympify(z) z0 = sympify(z0) if e == z: return z0 if e.is_Rational: return e if not e.has(z): return e if e.func is tan: # discontinuity at odd multiples of pi/2; 0 at even disc = S.Pi/2 sign = 1 if dir == '-': sign *= -1 i = limit(sign*e.args[0], z, z0)/disc if i.is_integer: if i.is_even: return S.Zero elif i.is_odd: if dir == '+': return S.NegativeInfinity else: return S.Infinity if e.func is cot: # discontinuity at multiples of pi; 0 at odd pi/2 multiples disc = S.Pi sign = 1 if dir == '-': sign *= -1 i = limit(sign*e.args[0], z, z0)/disc if i.is_integer: if dir == '-': return S.NegativeInfinity else: return S.Infinity elif (2*i).is_integer: return S.Zero if e.is_Pow: b, ex = e.args c = None # records sign of b if b is +/-z or has a bounded value if b.is_Mul: c, b = b.as_two_terms() if c is S.NegativeOne and b == z: c = '-' elif b == z: c = '+' if ex.is_number: if c is None: base = b.subs(z, z0) if base.is_bounded and (ex.is_bounded or base is not S.One): return base**ex else: if z0 == 0 and ex < 0: if dir != c: # integer if ex.is_even: return S.Infinity elif ex.is_odd: return S.NegativeInfinity # rational elif ex.is_Rational: return (S.NegativeOne**ex)*S.Infinity else: return S.ComplexInfinity return S.Infinity return z0**ex if e.is_Mul or not z0 and e.is_Pow and b.func is log: if e.is_Mul: # weed out the z-independent terms i, d = e.as_independent(z) if i is not S.One: return i*limit(d, z, z0, dir) else: i, d = S.One, e if not z0: # look for log(z)**q or z**p*log(z)**q p, q = Wild("p"), Wild("q") r = d.match(z**p * log(z)**q) if r: p, q = [r.get(w, w) for w in [p, q]] if q and q.is_number and p.is_number: if q > 0: if p > 0: return S.Zero else: return -oo*i else: if p >= 0: return S.Zero else: return -oo*i if e.is_Add: if e.is_polynomial() and not z0.is_unbounded: return Add(*[limit(term, z, z0, dir) for term in e.args]) # this is a case like limit(x*y+x*z, z, 2) == x*y+2*x # but we need to make sure, that the general gruntz() algorithm is # executed for a case like "limit(sqrt(x+1)-sqrt(x),x,oo)==0" unbounded = []; unbounded_result=[] finite = []; unknown = [] ok = True for term in e.args: if not term.has(z): finite.append(term) continue result = term.subs(z, z0) bounded = result.is_bounded if bounded is False or result is S.NaN: if unknown: ok = False break unbounded.append(term) if result != S.NaN: # take result from direction given result = limit(term, z, z0, dir) unbounded_result.append(result) elif bounded: finite.append(result) else: if unbounded: ok = False break unknown.append(result) if not ok: # we won't be able to resolve this with unbounded # terms, e.g. Sum(1/k, (k, 1, n)) - log(n) as n -> oo: # since the Sum is unevaluated it's boundedness is # unknown and the log(n) is oo so you get Sum - oo # which is unsatisfactory. raise NotImplementedError('unknown boundedness for %s' % (unknown or result)) u = Add(*unknown) if unbounded: inf_limit = Add(*unbounded_result) if inf_limit is not S.NaN: return inf_limit + u if finite: return Add(*finite) + limit(Add(*unbounded), z, z0, dir) + u else: return Add(*finite) + u if e.is_Order: args = e.args return C.Order(limit(args[0], z, z0), *args[1:]) try: r = gruntz(e, z, z0, dir) if r is S.NaN: raise PoleError() except PoleError: r = heuristics(e, z, z0, dir) return r
def _eval_rewrite_as_hyper(self, n): return C.hyper([1 - n, -n], [2], 1)
def fdiff(self, argindex=1): if argindex == 1: return 2 * C.exp(-self.args[0]**2) / sqrt(S.Pi) else: raise ArgumentIndexError(self, argindex)
def _eval_rewrite_as_gamma(self, n): # The gamma function allows to generalize Catalan numbers to complex n return 4**n * C.gamma(n + S.Half) / (C.gamma(S.Half) * C.gamma(n + 2))
def _eval_rewrite_as_binomial(self, n): return C.binomial(2 * n, n) / (n + 1)
def _eval_rewrite_as_gamma(self, n, k): return C.gamma(n + 1) / (C.gamma(k + 1) * C.gamma(n - k + 1))
def _eval_rewrite_as_Heaviside(self, *args): return C.Add(*[j*C.Mul(*[C.Heaviside(i-j) for i in args if i!=j]) \ for j in args])