def test_Trace(): assert isinstance(Trace(A), Trace) assert not isinstance(Trace(A), MatrixExpr) raises(ShapeError, lambda: Trace(C)) assert trace(eye(3)) == 3 assert trace(Matrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9])) == 15 assert adjoint(Trace(A)) == trace(Adjoint(A)) assert conjugate(Trace(A)) == trace(Adjoint(A)) assert transpose(Trace(A)) == Trace(A) A / Trace(A) # Make sure this is possible # Some easy simplifications assert trace(Identity(5)) == 5 assert trace(ZeroMatrix(5, 5)) == 0 assert trace(2 * A * B) == 2 * Trace(A * B) assert trace(A.T) == trace(A) i, j = symbols('i j') F = FunctionMatrix(3, 3, Lambda((i, j), i + j)) assert trace(F) == (0 + 0) + (1 + 1) + (2 + 2) raises(TypeError, lambda: Trace(S.One)) assert Trace(A).arg is A assert str(trace(A)) == str(Trace(A).doit())
def test_Pow(): assert rust_code(1 / x) == "x.recip()" assert rust_code(x**-1) == rust_code(x**-1.0) == "x.recip()" assert rust_code(sqrt(x)) == "x.sqrt()" assert rust_code(x**S.Half) == rust_code(x**0.5) == "x.sqrt()" assert rust_code(1 / sqrt(x)) == "x.sqrt().recip()" assert rust_code(x**-S.Half) == rust_code(x**-0.5) == "x.sqrt().recip()" assert rust_code(1 / pi) == "PI.recip()" assert rust_code(pi**-1) == rust_code(pi**-1.0) == "PI.recip()" assert rust_code(pi**-0.5) == "PI.sqrt().recip()" assert rust_code(x**Rational(1, 3)) == "x.cbrt()" assert rust_code(2**x) == "x.exp2()" assert rust_code(exp(x)) == "x.exp()" assert rust_code(x**3) == "x.powi(3)" assert rust_code(x**(y**3)) == "x.powf(y.powi(3))" assert rust_code(x**Rational(2, 3)) == "x.powf(2_f64/3.0)" g = implemented_function('g', Lambda(x, 2 * x)) assert rust_code(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "(3.5*2*x).powf(-x + y.powf(x))/(x.powi(2) + y)" _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi", 1), (lambda base, exp: not exp.is_integer, "pow", 1)] assert rust_code(x**3, user_functions={'Pow': _cond_cfunc}) == 'x.dpowi(3)' assert rust_code(x**3.2, user_functions={'Pow': _cond_cfunc}) == 'x.pow(3.2)'
def test_glsl_code_Pow(): g = implemented_function('g', Lambda(x, 2*x)) assert glsl_code(x**3) == "pow(x, 3.0)" assert glsl_code(x**(y**3)) == "pow(x, pow(y, 3.0))" assert glsl_code(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2.0) + y)" assert glsl_code(x**-1.0) == '1.0/x'
def test_ccode_Pow(): assert ccode(x**3) == "pow(x, 3)" assert ccode(x**(y**3)) == "pow(x, pow(y, 3))" g = implemented_function('g', Lambda(x, 2 * x)) assert ccode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2) + y)" assert ccode(x**-1.0) == '1.0/x' assert ccode(x**Rational(2, 3)) == 'pow(x, 2.0/3.0)' assert ccode(x**Rational(2, 3), type_aliases={real: float80}) == 'powl(x, 2.0L/3.0L)' _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi"), (lambda base, exp: not exp.is_integer, "pow")] assert ccode(x**3, user_functions={'Pow': _cond_cfunc}) == 'dpowi(x, 3)' assert ccode(x**0.5, user_functions={'Pow': _cond_cfunc}) == 'pow(x, 0.5)' assert ccode(x**Rational(16, 5), user_functions={'Pow': _cond_cfunc}) == 'pow(x, 16.0/5.0)' _cond_cfunc2 = [(lambda base, exp: base == 2, lambda base, exp: 'exp2(%s)' % exp), (lambda base, exp: base != 2, 'pow')] # Related to gh-11353 assert ccode(2**x, user_functions={'Pow': _cond_cfunc2}) == 'exp2(x)' assert ccode(x**2, user_functions={'Pow': _cond_cfunc2}) == 'pow(x, 2)' # For issue 14160 assert ccode( Mul(-2, x, Pow(Mul(y, y, evaluate=False), -1, evaluate=False), evaluate=False)) == '-2*x/(y*y)'
def test_inline_function(): x = symbols('x') g = implemented_function('g', Lambda(x, 2 * x)) assert rust_code(g(x)) == "2*x" g = implemented_function('g', Lambda(x, 2 * x / Catalan)) assert rust_code(g(x)) == ("const Catalan: f64 = %s;\n2*x/Catalan" % Catalan.evalf(17)) A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x * (1 + x) * (2 + x))) assert rust_code(g( A[i]), assign_to=A[i]) == ("for i in 0..n {\n" " A[i] = (A[i] + 1)*(A[i] + 2)*A[i];\n" "}")
def test_Pow(): assert mcode(x**3) == "x.^3" assert mcode(x**(y**3)) == "x.^(y.^3)" assert mcode(x**Rational(2, 3)) == 'x.^(2/3)' g = implemented_function('g', Lambda(x, 2 * x)) assert mcode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "(3.5*2*x).^(-x + y.^x)./(x.^2 + y)"
def test_jscode_Pow(): g = implemented_function('g', Lambda(x, 2 * x)) assert jscode(x**3) == "Math.pow(x, 3)" assert jscode(x**(y**3)) == "Math.pow(x, Math.pow(y, 3))" assert jscode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "Math.pow(3.5*2*x, -x + Math.pow(y, x))/(Math.pow(x, 2) + y)" assert jscode(x**-1.0) == '1/x'
def test_inline_function(): from sympy.tensor import IndexedBase, Idx from sympy import symbols n, m = symbols('n m', integer=True) A, x, y = map(IndexedBase, 'Axy') i = Idx('i', m) p = FCodeGen() func = implemented_function('func', Lambda(n, n*(n + 1))) routine = make_routine('test_inline', Eq(y[i], func(x[i]))) code = get_string(p.dump_f95, [routine]) expected = ( 'subroutine test_inline(m, x, y)\n' 'implicit none\n' 'INTEGER*4, intent(in) :: m\n' 'REAL*8, intent(in), dimension(1:m) :: x\n' 'REAL*8, intent(out), dimension(1:m) :: y\n' 'INTEGER*4 :: i\n' 'do i = 1, m\n' ' y(i) = %s*%s\n' 'end do\n' 'end subroutine\n' ) args = ('x(i)', '(x(i) + 1)') assert code == expected % args or\ code == expected % args[::-1]
def cdf(self, x): """ Return the cumulative density function as an expression in x Examples ======== >>> from sympy.statistics.distributions import PDF >>> from sympy import exp, oo >>> from sympy.abc import x, y >>> PDF(exp(-x/y), (x,0,oo)).cdf(4) y - y*exp(-4/y) >>> PDF(2*x + y, (x, 10, oo)).cdf(0) -10*y - 100 """ x = sympify(x) if self._cdf is not None: return self._cdf(x) else: from sympy import integrate w = Dummy('w', real=True) self._cdf = integrate(self.pdf(w), w) self._cdf = Lambda(w, self._cdf - self._cdf.subs(w, self.domain[0])) return self._cdf(x)
def test_rcode_inline_function(): x = symbols('x') g = implemented_function('g', Lambda(x, 2*x)) assert rcode(g(x)) == "2*x" g = implemented_function('g', Lambda(x, 2*x/Catalan)) assert rcode( g(x)) == "Catalan = %s;\n2*x/Catalan" % Catalan.n() A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) res=rcode(g(A[i]), assign_to=A[i]) ref=( "for (i in 1:n){\n" " A[i] = (A[i] + 1)*(A[i] + 2)*A[i];\n" "}" ) assert res == ref
def test_funcmatrix(): i, j = symbols('i,j') X = FunctionMatrix(3, 3, Lambda((i, j), i - j)) assert X[1, 1] == 0 assert X[1, 2] == -1 assert X.shape == (3, 3) assert X.rows == X.cols == 3 assert Matrix(X) == Matrix(3, 3, lambda i, j: i - j) assert isinstance(X*X + X, MatrixExpr)
def test_Pow(): assert mcode(x**3) == "x.^3" assert mcode(x**(y**3)) == "x.^(y.^3)" assert mcode(x**Rational(2, 3)) == 'x.^(2/3)' g = implemented_function('g', Lambda(x, 2*x)) assert mcode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "(3.5*2*x).^(-x + y.^x)./(x.^2 + y)" # For issue 14160 assert mcode(Mul(-2, x, Pow(Mul(y,y,evaluate=False), -1, evaluate=False), evaluate=False)) == '-2*x./(y.*y)'
def cdf(self, x): x = sympify(x) if self._cdf is not None: return self._cdf(x) else: from sympy import integrate w = Dummy('w', real=True) self._cdf = integrate(self.pdf(w), w) self._cdf = Lambda(w, self._cdf - self._cdf.subs(w, self.domain[0])) return self._cdf(x)
def test_rcode_Pow(): assert rcode(x**3) == "x^3" assert rcode(x**(y**3)) == "x^(y^3)" g = implemented_function('g', Lambda(x, 2*x)) assert rcode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "(3.5*2*x)^(-x + y^x)/(x^2 + y)" assert rcode(x**-1.0) == '1.0/x' assert rcode(x**Rational(2, 3)) == 'x^(2.0/3.0)' _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi"), (lambda base, exp: not exp.is_integer, "pow")] assert rcode(x**3, user_functions={'Pow': _cond_cfunc}) == 'dpowi(x, 3)' assert rcode(x**3.2, user_functions={'Pow': _cond_cfunc}) == 'pow(x, 3.2)'
def test_ccode_Pow(): assert ccode(x**3) == "pow(x, 3)" assert ccode(x**(y**3)) == "pow(x, pow(y, 3))" g = implemented_function('g', Lambda(x, 2 * x)) assert ccode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2) + y)" assert ccode(x**-1.0) == '1.0/x' assert ccode(x**Rational(2, 3)) == 'pow(x, 2.0L/3.0L)' _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi"), (lambda base, exp: not exp.is_integer, "pow")] assert ccode(x**3, user_functions={'Pow': _cond_cfunc}) == 'dpowi(x, 3)' assert ccode(x**3.2, user_functions={'Pow': _cond_cfunc}) == 'pow(x, 3.2)'
def test_Pow(): assert maple_code(x ** 3) == "x^3" assert maple_code(x ** (y ** 3)) == "x^(y^3)" assert maple_code((x ** 3) ** y) == "(x^3)^y" assert maple_code(x ** Rational(2, 3)) == 'x^(2/3)' g = implemented_function('g', Lambda(x, 2 * x)) assert maple_code(1 / (g(x) * 3.5) ** (x - y ** x) / (x ** 2 + y)) == \ "(3.5*2*x)^(-x + y^x)/(x^2 + y)" # For issue 14160 assert maple_code(Mul(-2, x, Pow(Mul(y, y, evaluate=False), -1, evaluate=False), evaluate=False)) == '-2*x/(y*y)'
def test_rcode_Pow(): assert rcode(x**3) == "x^3" assert rcode(x**(y**3)) == "x^(y^3)" g = implemented_function("g", Lambda(x, 2 * x)) assert (rcode(1 / (g(x) * 3.5)**(x - y**x) / (x**2 + y)) == "(3.5*2*x)^(-x + y^x)/(x^2 + y)") assert rcode(x**-1.0) == "1.0/x" assert rcode(x**Rational(2, 3)) == "x^(2.0/3.0)" _cond_cfunc = [ (lambda base, exp: exp.is_integer, "dpowi"), (lambda base, exp: not exp.is_integer, "pow"), ] assert rcode(x**3, user_functions={"Pow": _cond_cfunc}) == "dpowi(x, 3)" assert rcode(x**3.2, user_functions={"Pow": _cond_cfunc}) == "pow(x, 3.2)"
def assemble_partfrac_list(partial_list): r"""Reassemble a full partial fraction decomposition from a structured result obtained by the function ``apart_list``. Examples ======== This example is taken from Bronstein's original paper: >>> from sympy.polys.partfrac import apart_list, assemble_partfrac_list >>> from sympy.abc import x >>> f = 36 / (x**5 - 2*x**4 - 2*x**3 + 4*x**2 + x - 2) >>> pfd = apart_list(f) >>> pfd (1, Poly(0, x, domain='ZZ'), [(Poly(_w - 2, _w, domain='ZZ'), Lambda(_a, 4), Lambda(_a, -_a + x), 1), (Poly(_w**2 - 1, _w, domain='ZZ'), Lambda(_a, -3*_a - 6), Lambda(_a, -_a + x), 2), (Poly(_w + 1, _w, domain='ZZ'), Lambda(_a, -4), Lambda(_a, -_a + x), 1)]) >>> assemble_partfrac_list(pfd) -4/(x + 1) - 3/(x + 1)**2 - 9/(x - 1)**2 + 4/(x - 2) If we happen to know some roots we can provide them easily inside the structure: >>> pfd = apart_list(2/(x**2-2)) >>> pfd (1, Poly(0, x, domain='ZZ'), [(Poly(_w**2 - 2, _w, domain='ZZ'), Lambda(_a, _a/2), Lambda(_a, -_a + x), 1)]) >>> pfda = assemble_partfrac_list(pfd) >>> pfda RootSum(_w**2 - 2, Lambda(_a, _a/(-_a + x)))/2 >>> pfda.doit() -sqrt(2)/(2*(x + sqrt(2))) + sqrt(2)/(2*(x - sqrt(2))) >>> from sympy import Dummy, Poly, Lambda, sqrt >>> a = Dummy("a") >>> pfd = (1, Poly(0, x, domain='ZZ'), [([sqrt(2),-sqrt(2)], Lambda(a, a/2), Lambda(a, -a + x), 1)]) >>> assemble_partfrac_list(pfd) -sqrt(2)/(2*(x + sqrt(2))) + sqrt(2)/(2*(x - sqrt(2))) See Also ======== apart, apart_list """ # Common factor common = partial_list[0] # Polynomial part polypart = partial_list[1] pfd = polypart.as_expr() # Rational parts for r, nf, df, ex in partial_list[2]: if isinstance(r, Poly): # Assemble in case the roots are given implicitly by a polynomials an, nu = nf.variables, nf.expr ad, de = df.variables, df.expr # Hack to make dummies equal because Lambda created new Dummies de = de.subs(ad[0], an[0]) func = Lambda(tuple(an), nu/de**ex) pfd += RootSum(r, func, auto=False, quadratic=False) else: # Assemble in case the roots are given explicitly by a list of algebraic numbers for root in r: pfd += nf(root)/df(root)**ex return common*pfd
def apart_list_full_decomposition(P, Q, dummygen): """ Bronstein's full partial fraction decomposition algorithm. Given a univariate rational function ``f``, performing only GCD operations over the algebraic closure of the initial ground domain of definition, compute full partial fraction decomposition with fractions having linear denominators. Note that no factorization of the initial denominator of ``f`` is performed. The final decomposition is formed in terms of a sum of :class:`RootSum` instances. References ========== .. [1] [Bronstein93]_ """ f, x, U = P/Q, P.gen, [] u = Function('u')(x) a = Dummy('a') partial = [] for d, n in Q.sqf_list_include(all=True): b = d.as_expr() U += [ u.diff(x, n - 1) ] h = cancel(f*b**n) / u**n H, subs = [h], [] for j in range(1, n): H += [ H[-1].diff(x) / j ] for j in range(1, n + 1): subs += [ (U[j - 1], b.diff(x, j) / j) ] for j in range(0, n): P, Q = cancel(H[j]).as_numer_denom() for i in range(0, j + 1): P = P.subs(*subs[j - i]) Q = Q.subs(*subs[0]) P = Poly(P, x) Q = Poly(Q, x) G = P.gcd(d) D = d.quo(G) B, g = Q.half_gcdex(D) b = (P * B.quo(g)).rem(D) Dw = D.subs(x, next(dummygen)) numer = Lambda(a, b.as_expr().subs(x, a)) denom = Lambda(a, (x - a)) exponent = n-j partial.append((Dw, numer, denom, exponent)) return partial
def test_funcmatrix_creation(): i, j, k = symbols('i j k') assert FunctionMatrix(2, 2, Lambda((i, j), 0)) assert FunctionMatrix(0, 0, Lambda((i, j), 0)) raises(ValueError, lambda: FunctionMatrix(-1, 0, Lambda((i, j), 0))) raises(ValueError, lambda: FunctionMatrix(2.0, 0, Lambda((i, j), 0))) raises(ValueError, lambda: FunctionMatrix(2j, 0, Lambda((i, j), 0))) raises(ValueError, lambda: FunctionMatrix(0, -1, Lambda((i, j), 0))) raises(ValueError, lambda: FunctionMatrix(0, 2.0, Lambda((i, j), 0))) raises(ValueError, lambda: FunctionMatrix(0, 2j, Lambda((i, j), 0))) raises(ValueError, lambda: FunctionMatrix(2, 2, Lambda(i, 0))) raises(ValueError, lambda: FunctionMatrix(2, 2, lambda i, j: 0)) raises(ValueError, lambda: FunctionMatrix(2, 2, Lambda((i,), 0))) raises(ValueError, lambda: FunctionMatrix(2, 2, Lambda((i, j, k), 0))) raises(ValueError, lambda: FunctionMatrix(2, 2, i+j)) assert FunctionMatrix(2, 2, "lambda i, j: 0") == \ FunctionMatrix(2, 2, Lambda((i, j), 0)) m = FunctionMatrix(2, 2, KroneckerDelta) assert m.as_explicit() == Identity(2).as_explicit() assert m.args[2] == Lambda((i, j), KroneckerDelta(i, j)) n = symbols('n') assert FunctionMatrix(n, n, Lambda((i, j), 0)) n = symbols('n', integer=False) raises(ValueError, lambda: FunctionMatrix(n, n, Lambda((i, j), 0))) n = symbols('n', negative=True) raises(ValueError, lambda: FunctionMatrix(n, n, Lambda((i, j), 0)))
def _eval_derivative(self, x): var, expr = self.fun.args func = Lambda(var, expr.diff(x)) return self.new(self.poly, func, self.auto)
class PDF(ContinuousProbability): """ PDF(func, (x, a, b)) represents continuous probability distribution with probability distribution function func(x) on interval (a, b) If func is not normalized so that integrate(func, (x, a, b)) == 1, it can be normalized using PDF.normalize() method Example usage: >>> from sympy import Symbol, exp, oo >>> from sympy.statistics.distributions import PDF >>> from sympy.abc import x >>> a = Symbol('a', positive=True) >>> exponential = PDF(exp(-x/a)/a, (x,0,oo)) >>> exponential.pdf(x) exp(-x/a)/a >>> exponential.cdf(x) 1 - exp(-x/a) >>> exponential.mean a >>> exponential.variance a**2 """ def __init__(self, pdf, var): #XXX maybe add some checking of parameters if isinstance(var, (tuple, list)): self.pdf = Lambda(var[0], pdf) self.domain = tuple(var[1:]) else: self.pdf = Lambda(var, pdf) self.domain = (-oo, oo) self._cdf = None self._mean = None self._variance = None self._stddev = None def normalize(self): """ Normalize the probability distribution function so that integrate(self.pdf(x), (x, a, b)) == 1 Example usage: >>> from sympy import Symbol, exp, oo >>> from sympy.statistics.distributions import PDF >>> from sympy.abc import x >>> a = Symbol('a', positive=True) >>> exponential = PDF(exp(-x/a), (x,0,oo)) >>> exponential.normalize().pdf(x) exp(-x/a)/a """ norm = self.probability(*self.domain) if norm != 1: w = Dummy('w', real=True) return self.__class__( self.pdf(w) / norm, (w, self.domain[0], self.domain[1])) #self._cdf = Lambda(w, (self.cdf(w) - self.cdf(self.domain[0]))/norm) #if self._mean is not None: # self._mean /= norm #if self._variance is not None: # self._variance = (self._variance + (self._mean*norm)**2)/norm - self.mean**2 #if self._stddev is not None: # self._stddev = sqrt(self._variance) else: return self def cdf(self, x): x = sympify(x) if self._cdf is not None: return self._cdf(x) else: from sympy import integrate w = Dummy('w', real=True) self._cdf = integrate(self.pdf(w), w) self._cdf = Lambda(w, self._cdf - self._cdf.subs(w, self.domain[0])) return self._cdf(x) def _get_mean(self): if self._mean is not None: return self._mean else: from sympy import integrate w = Dummy('w', real=True) self._mean = integrate( self.pdf(w) * w, (w, self.domain[0], self.domain[1])) return self._mean def _get_variance(self): if self._variance is not None: return self._variance else: from sympy import integrate, simplify w = Dummy('w', real=True) self._variance = integrate( self.pdf(w) * w**2, (w, self.domain[0], self.domain[1])) - self.mean**2 self._variance = simplify(self._variance) return self._variance def _get_stddev(self): if self._stddev is not None: return self._stddev else: self._stddev = sqrt(self.variance) return self._stddev mean = property(_get_mean) variance = property(_get_variance) stddev = property(_get_stddev) def _random(s): raise NotImplementedError def transform(self, func, var): """Return a probability distribution of random variable func(x) currently only some simple injective functions are supported""" w = Dummy('w', real=True) from sympy import solve inverse = solve(func - w, var) newPdf = S.Zero funcdiff = func.diff(var) #TODO check if x is in domain for x in inverse: # this assignment holds only for x in domain # in general it would require implementing # piecewise defined functions in sympy newPdf += (self.pdf(var) / abs(funcdiff)).subs(var, x) return PDF(newPdf, (w, func.subs( var, self.domain[0]), func.subs(var, self.domain[1])))
def __new__(cls, expr, func=None, x=None, auto=True, quadratic=False): """Construct a new ``RootSum`` instance carrying all roots of a polynomial. """ coeff, poly = cls._transform(expr, x) if not poly.is_univariate: raise MultivariatePolynomialError( "only univariate polynomials are allowed") if func is None: func = Lambda(poly.gen, poly.gen) else: try: is_func = func.is_Function except AttributeError: is_func = False if is_func and 1 in func.nargs: if not isinstance(func, Lambda): func = Lambda(poly.gen, func(poly.gen)) else: raise ValueError("expected a univariate function, got %s" % func) var, expr = func.variables[0], func.expr if coeff is not S.One: expr = expr.subs(var, coeff * var) deg = poly.degree() if not expr.has(var): return deg * expr if expr.is_Add: add_const, expr = expr.as_independent(var) else: add_const = S.Zero if expr.is_Mul: mul_const, expr = expr.as_independent(var) else: mul_const = S.One func = Lambda(var, expr) rational = cls._is_func_rational(poly, func) (_, factors), terms = poly.factor_list(), [] for poly, k in factors: if poly.is_linear: term = func(roots_linear(poly)[0]) elif quadratic and poly.is_quadratic: term = sum(map(func, roots_quadratic(poly))) else: if not rational or not auto: term = cls._new(poly, func, auto) else: term = cls._rational_case(poly, func) terms.append(k * term) return mul_const * Add(*terms) + deg * add_const
def test_ccode_inline_function(): g = implemented_function('g', Lambda(x, 2 * x)) assert ccode(g(x)) == "2*x"
def imageset(*args): r""" Image of set under transformation ``f``. If this function can't compute the image, it returns an unevaluated ImageSet object. .. math:: { f(x) | x \in self } Examples ======== >>> from sympy import Interval, Symbol, imageset, sin, Lambda >>> x = Symbol('x') >>> imageset(x, 2*x, Interval(0, 2)) [0, 4] >>> imageset(lambda x: 2*x, Interval(0, 2)) [0, 4] >>> imageset(Lambda(x, sin(x)), Interval(-2, 1)) ImageSet(Lambda(x, sin(x)), [-2, 1]) See Also ======== sympy.sets.fancysets.ImageSet """ from sympy.core import Dummy, Lambda from sympy.sets.fancysets import ImageSet if len(args) == 3: f = Lambda(*args[:2]) else: # var and expr are being defined this way to # support Python lambda and not just sympy Lambda f = args[0] if not isinstance(f, Lambda): var = Dummy() expr = args[0](var) f = Lambda(var, expr) set = args[-1] r = set._eval_imageset(f) if isinstance(r, ImageSet): f, set = r.args if f.variables[0] == f.expr: return set if isinstance(set, ImageSet): if len(set.lamda.variables) == 1 and len(f.variables) == 1: return imageset( Lambda(set.lamda.variables[0], f.expr.subs(f.variables[0], set.lamda.expr)), set.base_set) if r is not None: return r return ImageSet(f, set)
def test_funcmatrix_creation(): i, j, k = symbols('i j k') assert FunctionMatrix(2, 2, Lambda((i, j), 0)) assert FunctionMatrix(0, 0, Lambda((i, j), 0)) raises(ValueError, lambda: FunctionMatrix(-1, 0, Lambda((i, j), 0))) raises(ValueError, lambda: FunctionMatrix(2.0, 0, Lambda((i, j), 0))) raises(ValueError, lambda: FunctionMatrix(2j, 0, Lambda((i, j), 0))) raises(ValueError, lambda: FunctionMatrix(0, -1, Lambda((i, j), 0))) raises(ValueError, lambda: FunctionMatrix(0, 2.0, Lambda((i, j), 0))) raises(ValueError, lambda: FunctionMatrix(0, 2j, Lambda((i, j), 0))) raises(ValueError, lambda: FunctionMatrix(2, 2, Lambda(i, 0))) with warns(SymPyDeprecationWarning, test_stacklevel=False): # This raises a deprecation warning from sympify() raises(ValueError, lambda: FunctionMatrix(2, 2, lambda i, j: 0)) raises(ValueError, lambda: FunctionMatrix(2, 2, Lambda((i,), 0))) raises(ValueError, lambda: FunctionMatrix(2, 2, Lambda((i, j, k), 0))) raises(ValueError, lambda: FunctionMatrix(2, 2, i+j)) assert FunctionMatrix(2, 2, "lambda i, j: 0") == \ FunctionMatrix(2, 2, Lambda((i, j), 0)) m = FunctionMatrix(2, 2, KroneckerDelta) assert m.as_explicit() == Identity(2).as_explicit() assert m.args[2].dummy_eq(Lambda((i, j), KroneckerDelta(i, j))) n = symbols('n') assert FunctionMatrix(n, n, Lambda((i, j), 0)) n = symbols('n', integer=False) raises(ValueError, lambda: FunctionMatrix(n, n, Lambda((i, j), 0))) n = symbols('n', negative=True) raises(ValueError, lambda: FunctionMatrix(n, n, Lambda((i, j), 0)))
def __new__(cls, name, transformation=None, parent=None, location=None, rotation_matrix=None, vector_names=None, variable_names=None): """ The orientation/location parameters are necessary if this system is being defined at a certain orientation or location wrt another. Parameters ========== name : str The name of the new CoordSys3D instance. transformation : Lambda, Tuple, str Transformation defined by transformation equations or chosen from predefined ones. location : Vector The position vector of the new system's origin wrt the parent instance. rotation_matrix : SymPy ImmutableMatrix The rotation matrix of the new coordinate system with respect to the parent. In other words, the output of new_system.rotation_matrix(parent). parent : CoordSys3D The coordinate system wrt which the orientation/location (or both) is being defined. vector_names, variable_names : iterable(optional) Iterables of 3 strings each, with custom names for base vectors and base scalars of the new system respectively. Used for simple str printing. """ name = str(name) Vector = sympy.vector.Vector BaseVector = sympy.vector.BaseVector Point = sympy.vector.Point if not isinstance(name, string_types): raise TypeError("name should be a string") if transformation is not None: if (location is not None) or (rotation_matrix is not None): raise ValueError("specify either `transformation` or " "`location`/`rotation_matrix`") if isinstance(transformation, (Tuple, tuple, list)): if isinstance(transformation[0], MatrixBase): rotation_matrix = transformation[0] location = transformation[1] else: transformation = Lambda(transformation[0], transformation[1]) elif isinstance(transformation, Callable): x1, x2, x3 = symbols('x1 x2 x3', cls=Dummy) transformation = Lambda((x1, x2, x3), transformation(x1, x2, x3)) elif isinstance(transformation, string_types): transformation = Symbol(transformation) elif isinstance(transformation, (Symbol, Lambda)): pass else: raise TypeError("transformation: " "wrong type {0}".format(type(transformation))) # If orientation information has been provided, store # the rotation matrix accordingly if rotation_matrix is None: rotation_matrix = ImmutableDenseMatrix(eye(3)) else: if not isinstance(rotation_matrix, MatrixBase): raise TypeError("rotation_matrix should be an Immutable" + "Matrix instance") rotation_matrix = rotation_matrix.as_immutable() # If location information is not given, adjust the default # location as Vector.zero if parent is not None: if not isinstance(parent, CoordSys3D): raise TypeError("parent should be a " + "CoordSys3D/None") if location is None: location = Vector.zero else: if not isinstance(location, Vector): raise TypeError("location should be a Vector") # Check that location does not contain base # scalars for x in location.free_symbols: if isinstance(x, BaseScalar): raise ValueError("location should not contain" + " BaseScalars") origin = parent.origin.locate_new(name + '.origin', location) else: location = Vector.zero origin = Point(name + '.origin') if transformation is None: transformation = Tuple(rotation_matrix, location) if isinstance(transformation, Tuple): lambda_transformation = CoordSys3D._compose_rotation_and_translation( transformation[0], transformation[1], parent) r, l = transformation l = l._projections lambda_lame = CoordSys3D._get_lame_coeff('cartesian') lambda_inverse = lambda x, y, z: r.inv() * Matrix( [x - l[0], y - l[1], z - l[2]]) elif isinstance(transformation, Symbol): trname = transformation.name lambda_transformation = CoordSys3D._get_transformation_lambdas( trname) if parent is not None: if parent.lame_coefficients() != (S.One, S.One, S.One): raise ValueError('Parent for pre-defined coordinate ' 'system should be Cartesian.') lambda_lame = CoordSys3D._get_lame_coeff(trname) lambda_inverse = CoordSys3D._set_inv_trans_equations(trname) elif isinstance(transformation, Lambda): if not CoordSys3D._check_orthogonality(transformation): raise ValueError("The transformation equation does not " "create orthogonal coordinate system") lambda_transformation = transformation lambda_lame = CoordSys3D._calculate_lame_coeff( lambda_transformation) lambda_inverse = None else: lambda_transformation = lambda x, y, z: transformation(x, y, z) lambda_lame = CoordSys3D._get_lame_coeff(transformation) lambda_inverse = None if variable_names is None: if isinstance(transformation, Lambda): variable_names = ["x1", "x2", "x3"] elif isinstance(transformation, Symbol): if transformation.name == 'spherical': variable_names = ["r", "theta", "phi"] elif transformation.name == 'cylindrical': variable_names = ["r", "theta", "z"] else: variable_names = ["x", "y", "z"] else: variable_names = ["x", "y", "z"] if vector_names is None: vector_names = ["i", "j", "k"] # All systems that are defined as 'roots' are unequal, unless # they have the same name. # Systems defined at same orientation/position wrt the same # 'parent' are equal, irrespective of the name. # This is true even if the same orientation is provided via # different methods like Axis/Body/Space/Quaternion. # However, coincident systems may be seen as unequal if # positioned/oriented wrt different parents, even though # they may actually be 'coincident' wrt the root system. if parent is not None: obj = super(CoordSys3D, cls).__new__(cls, Symbol(name), transformation, parent) else: obj = super(CoordSys3D, cls).__new__(cls, Symbol(name), transformation) obj._name = name # Initialize the base vectors _check_strings('vector_names', vector_names) vector_names = list(vector_names) latex_vects = [(r'\mathbf{\hat{%s}_{%s}}' % (x, name)) for x in vector_names] pretty_vects = ['%s_%s' % (x, name) for x in vector_names] obj._vector_names = vector_names v1 = BaseVector(0, obj, pretty_vects[0], latex_vects[0]) v2 = BaseVector(1, obj, pretty_vects[1], latex_vects[1]) v3 = BaseVector(2, obj, pretty_vects[2], latex_vects[2]) obj._base_vectors = (v1, v2, v3) # Initialize the base scalars _check_strings('variable_names', vector_names) variable_names = list(variable_names) latex_scalars = [(r"\mathbf{{%s}_{%s}}" % (x, name)) for x in variable_names] pretty_scalars = ['%s_%s' % (x, name) for x in variable_names] obj._variable_names = variable_names obj._vector_names = vector_names x1 = BaseScalar(0, obj, pretty_scalars[0], latex_scalars[0]) x2 = BaseScalar(1, obj, pretty_scalars[1], latex_scalars[1]) x3 = BaseScalar(2, obj, pretty_scalars[2], latex_scalars[2]) obj._base_scalars = (x1, x2, x3) obj._transformation = transformation obj._transformation_lambda = lambda_transformation obj._lame_coefficients = lambda_lame(x1, x2, x3) obj._transformation_from_parent_lambda = lambda_inverse setattr(obj, variable_names[0], x1) setattr(obj, variable_names[1], x2) setattr(obj, variable_names[2], x3) setattr(obj, vector_names[0], v1) setattr(obj, vector_names[1], v2) setattr(obj, vector_names[2], v3) # Assign params obj._parent = parent if obj._parent is not None: obj._root = obj._parent._root else: obj._root = obj obj._parent_rotation_matrix = rotation_matrix obj._origin = origin # Return the instance return obj
def apart(f, z=None, **args): """Computes partial fraction decomposition of a rational function. Given a rational function 'f', performing only gcd operations over the algebraic closure of the initial field of definition, compute full partial fraction decomposition with fractions having linear denominators. For all other kinds of expressions the input is returned in an unchanged form. Note however, that `apart` function can thread over sums and relational operators. Note that no factorization of the initial denominator of `f` is needed. The final decomposition is formed in terms of a sum of RootSum instances. By default RootSum tries to compute all its roots to simplify itself. This behavior can be however avoided by setting the keyword flag evaluate=False, which will make this function return a formal decomposition. >>> from sympy import apart >>> from sympy.abc import x, y >>> apart(y/(x+2)/(x+1), x) y/(1 + x) - y/(2 + x) >>> apart(1/(1+x**5), x, evaluate=False) RootSum(Lambda(_a, -_a/(5*(x - _a))), x**5 + 1, x, domain='ZZ') References ========== .. [Bronstein93] M. Bronstein, B. Salvy, Full partial fraction decomposition of rational functions, Proceedings ISSAC '93, ACM Press, Kiev, Ukraine, 1993, pp. 157-160. """ f = cancel(f) if z is None: symbols = f.atoms(Symbol) if not symbols: return f if len(symbols) == 1: z = list(symbols)[0] else: raise ValueError("multivariate partial fractions are not supported") P, Q = f.as_numer_denom() if not Q.has(z): return f partial, r = div(P, Q, z) f, q, U = r / Q, Q, [] u = Function('u')(z) a = Dummy('a') q = Poly(q, z) for d, n in q.sqf_list(all=True, include=True): b = d.as_basic() U += [ u.diff(z, n-1) ] h = cancel(f*b**n) / u**n H, subs = [h], [] for j in range(1, n): H += [ H[-1].diff(z) / j ] for j in range(1, n+1): subs += [ (U[j-1], b.diff(z, j) / j) ] for j in range(0, n): P, Q = cancel(H[j]).as_numer_denom() for i in range(0, j+1): P = P.subs(*subs[j-i]) Q = Q.subs(*subs[0]) P = Poly(P, z) Q = Poly(Q, z) G = P.gcd(d) D = d.exquo(G) B, g = Q.half_gcdex(D) b = (P * B.exquo(g)).rem(D) numer = b.as_basic() denom = (z-a)**(n-j) expr = numer.subs(z, a) / denom partial += RootSum(Lambda(a, expr), D, **args) return partial
class PDF(ContinuousProbability): """ PDF(func, (x, a, b)) represents continuous probability distribution with probability distribution function func(x) on interval (a, b) If func is not normalized so that integrate(func, (x, a, b)) == 1, it can be normalized using PDF.normalize() method Examples ======== >>> from sympy import Symbol, exp, oo >>> from sympy.statistics.distributions import PDF >>> from sympy.abc import x >>> a = Symbol('a', positive=True) >>> exponential = PDF(exp(-x/a)/a, (x,0,oo)) >>> exponential.pdf(x) exp(-x/a)/a >>> exponential.cdf(x) 1 - exp(-x/a) >>> exponential.mean a >>> exponential.variance a**2 """ def __init__(self, pdf, var): #XXX maybe add some checking of parameters if isinstance(var, (tuple, list)): self.pdf = Lambda(var[0], pdf) self.domain = tuple(var[1:]) else: self.pdf = Lambda(var, pdf) self.domain = (-oo, oo) self._cdf = None self._mean = None self._variance = None self._stddev = None def normalize(self): """ Normalize the probability distribution function so that integrate(self.pdf(x), (x, a, b)) == 1 Examples ======== >>> from sympy import Symbol, exp, oo >>> from sympy.statistics.distributions import PDF >>> from sympy.abc import x >>> a = Symbol('a', positive=True) >>> exponential = PDF(exp(-x/a), (x,0,oo)) >>> exponential.normalize().pdf(x) exp(-x/a)/a """ norm = self.probability(*self.domain) if norm != 1: w = Dummy('w', real=True) return self.__class__(self.pdf(w)/norm, (w, self.domain[0], self.domain[1])) #self._cdf = Lambda(w, (self.cdf(w) - self.cdf(self.domain[0]))/norm) #if self._mean is not None: # self._mean /= norm #if self._variance is not None: # self._variance = (self._variance + (self._mean*norm)**2)/norm - self.mean**2 #if self._stddev is not None: # self._stddev = sqrt(self._variance) else: return self def cdf(self, x): """ Return the cumulative density function as an expression in x Examples ======== >>> from sympy.statistics.distributions import PDF >>> from sympy import exp, oo >>> from sympy.abc import x, y >>> PDF(exp(-x/y), (x,0,oo)).cdf(4) y - y*exp(-4/y) >>> PDF(2*x + y, (x, 10, oo)).cdf(0) -10*y - 100 """ x = sympify(x) if self._cdf is not None: return self._cdf(x) else: from sympy import integrate w = Dummy('w', real=True) self._cdf = integrate(self.pdf(w), w) self._cdf = Lambda(w, self._cdf - self._cdf.subs(w, self.domain[0])) return self._cdf(x) def _get_mean(self): if self._mean is not None: return self._mean else: from sympy import integrate w = Dummy('w', real=True) self._mean = integrate(self.pdf(w)*w,(w,self.domain[0],self.domain[1])) return self._mean def _get_variance(self): if self._variance is not None: return self._variance else: from sympy import integrate, simplify w = Dummy('w', real=True) self._variance = integrate(self.pdf(w)*w**2,(w,self.domain[0],self.domain[1])) - self.mean**2 self._variance = simplify(self._variance) return self._variance def _get_stddev(self): if self._stddev is not None: return self._stddev else: self._stddev = sqrt(self.variance) return self._stddev mean = property(_get_mean) variance = property(_get_variance) stddev = property(_get_stddev) def _random(s): raise NotImplementedError def transform(self,func,var): """ Return a probability distribution of random variable func(x) currently only some simple injective functions are supported Examples ======== >>> from sympy.statistics.distributions import PDF >>> from sympy import oo >>> from sympy.abc import x, y >>> PDF(2*x + y, (x, 10, oo)).transform(x, y) PDF(0, ((_w,), x, x)) """ w = Dummy('w', real=True) from sympy import solve from sympy import S inverse = solve(func-w, var) newPdf = S.Zero funcdiff = func.diff(var) #TODO check if x is in domain for x in inverse: # this assignment holds only for x in domain # in general it would require implementing # piecewise defined functions in sympy newPdf += (self.pdf(var)/abs(funcdiff)).subs(var,x) return PDF(newPdf, (w, func.subs(var, self.domain[0]), func.subs(var, self.domain[1])))
def test_coordsys_transform(): # test inverse transforms p, q, r, s = symbols('p q r s') rel = {('first', 'second'): [(p, q), (q, -p)]} R2_pq = CoordSystem('first', R2_origin, [p, q], rel) R2_rs = CoordSystem('second', R2_origin, [r, s], rel) r, s = R2_rs.symbols assert R2_rs.transform(R2_pq) == Matrix([[-s], [r]]) # inverse transform impossible case a, b = symbols('a b', positive=True) rel = {('first', 'second'): [(a,), (-a,)]} R2_a = CoordSystem('first', R2_origin, [a], rel) R2_b = CoordSystem('second', R2_origin, [b], rel) # This transformation is uninvertible because there is no positive a, b satisfying a = -b with raises(NotImplementedError): R2_b.transform(R2_a) # inverse transform ambiguous case c, d = symbols('c d') rel = {('first', 'second'): [(c,), (c**2,)]} R2_c = CoordSystem('first', R2_origin, [c], rel) R2_d = CoordSystem('second', R2_origin, [d], rel) # The transform method should throw if it finds multiple inverses for a coordinate transformation. with raises(ValueError): R2_d.transform(R2_c) # test indirect transformation a, b, c, d, e, f = symbols('a, b, c, d, e, f') rel = {('C1', 'C2'): [(a, b), (2*a, 3*b)], ('C2', 'C3'): [(c, d), (3*c, 2*d)]} C1 = CoordSystem('C1', R2_origin, (a, b), rel) C2 = CoordSystem('C2', R2_origin, (c, d), rel) C3 = CoordSystem('C3', R2_origin, (e, f), rel) a, b = C1.symbols c, d = C2.symbols e, f = C3.symbols assert C2.transform(C1) == Matrix([c/2, d/3]) assert C1.transform(C3) == Matrix([6*a, 6*b]) assert C3.transform(C1) == Matrix([e/6, f/6]) assert C3.transform(C2) == Matrix([e/3, f/2]) a, b, c, d, e, f = symbols('a, b, c, d, e, f') rel = {('C1', 'C2'): [(a, b), (2*a, 3*b + 1)], ('C3', 'C2'): [(e, f), (-e - 2, 2*f)]} C1 = CoordSystem('C1', R2_origin, (a, b), rel) C2 = CoordSystem('C2', R2_origin, (c, d), rel) C3 = CoordSystem('C3', R2_origin, (e, f), rel) a, b = C1.symbols c, d = C2.symbols e, f = C3.symbols assert C2.transform(C1) == Matrix([c/2, (d - 1)/3]) assert C1.transform(C3) == Matrix([-2*a - 2, (3*b + 1)/2]) assert C3.transform(C1) == Matrix([-e/2 - 1, (2*f - 1)/3]) assert C3.transform(C2) == Matrix([-e - 2, 2*f]) # old signature uses Lambda a, b, c, d, e, f = symbols('a, b, c, d, e, f') rel = {('C1', 'C2'): Lambda((a, b), (2*a, 3*b + 1)), ('C3', 'C2'): Lambda((e, f), (-e - 2, 2*f))} C1 = CoordSystem('C1', R2_origin, (a, b), rel) C2 = CoordSystem('C2', R2_origin, (c, d), rel) C3 = CoordSystem('C3', R2_origin, (e, f), rel) a, b = C1.symbols c, d = C2.symbols e, f = C3.symbols assert C2.transform(C1) == Matrix([c/2, (d - 1)/3]) assert C1.transform(C3) == Matrix([-2*a - 2, (3*b + 1)/2]) assert C3.transform(C1) == Matrix([-e/2 - 1, (2*f - 1)/3]) assert C3.transform(C2) == Matrix([-e - 2, 2*f])