def compute_cdf(self, expr): if self._is_symbolic: d = self.compute_density(expr) k = Dummy('k') ki = Dummy('ki') return Lambda(k, Sum(d(ki), (ki, self.args[1].low, k))) expr = rv_subs(expr, self.values) return FinitePSpace(self.domain, self.distribution).compute_cdf(expr)
def compute_moment_generating_function(self, expr, **kwargs): if not self.domain.set.is_Interval: raise NotImplementedError("Moment generating function of multivariate expressions not implemented") d = self.compute_density(expr, **kwargs) x, t = symbols('x, t', real=True, cls=Dummy) mgf = integrate(exp(t * x) * d(x), (x, -oo, oo), **kwargs) return Lambda(t, mgf)
def _set_function(f, x): # noqa:F811 from sympy.sets.sets import is_function_invertible_in_set # If the function is invertible, intersect the maps of the sets. if is_function_invertible_in_set(f, x): return Intersection(*(imageset(f, arg) for arg in x.args)) else: return ImageSet(Lambda(_x, f(_x)), x)
def _compute_joint_eigen_distribution(self, beta): """ Helper function for computing the joint probability distribution of eigen values of the random matrix. """ n = self.dimension Zbn = self._compute_normalization_constant(beta, n) l = IndexedBase('l') i = Dummy('i', integer=True, positive=True) j = Dummy('j', integer=True, positive=True) k = Dummy('k', integer=True, positive=True) term1 = exp((-S(n) / 2) * Sum(l[k]**2, (k, 1, n)).doit()) sub_term = Lambda(i, Product(Abs(l[j] - l[i])**beta, (j, i + 1, n))) term2 = Product(sub_term(i).doit(), (i, 1, n - 1)).doit() syms = ArrayComprehension(l[k], (k, 1, n)).doit() return Lambda(tuple(syms), (term1 * term2) / Zbn)
def compute_characteristic_function(self, expr, **kwargs): if not self.domain.set.is_Interval: raise NotImplementedError("Characteristic function of multivariate expressions not implemented") d = self.compute_density(expr, **kwargs) x, t = symbols('x, t', real=True, cls=Dummy) cf = integrate(exp(I*t*x)*d(x), (x, -oo, oo), **kwargs) return Lambda(t, cf)
def test_RootSum___eq__(): f = Lambda(x, exp(x)) assert (RootSum(x**3 + x + 1, f) == RootSum(x**3 + x + 1, f)) is True assert (RootSum(x**3 + x + 1, f) == RootSum(y**3 + y + 1, f)) is True assert (RootSum(x**3 + x + 1, f) == RootSum(x**3 + x + 2, f)) is False assert (RootSum(x**3 + x + 1, f) == RootSum(y**3 + y + 2, f)) is False
def _set_function(f, self): if self.is_integer: #for positive integers: if self.args == (1, S.Infinity, 1): expr = f.expr if not isinstance(expr, Expr): return x = f.variables[0] if not expr.free_symbols - {x}: step = expr.coeff(x) c = expr.subs(x, 0) if c.is_Integer and step.is_Integer and expr == step * x + c: if self is S.Naturals: c += step if step > 0: return Range(c, S.Infinity, step) return Range(c, S.NegativeInfinity, step) return expr = f.expr if not isinstance(expr, Expr): return n = f.variables[0] # f(x) + c and f(-x) + c cover the same integers # so choose the form that has the fewest negatives c = f(0) fx = f(n) - c f_x = f(-n) - c neg_count = lambda e: sum(_._coeff_isneg() for _ in Add.make_args(e)) if neg_count(f_x) < neg_count(fx): expr = f_x + c a = Wild('a', exclude=[n]) b = Wild('b', exclude=[n]) match = expr.match(a * n + b) if match and match[a]: # canonical shift b = match[b] if abs(match[a]) == 1: nonint = [] for bi in Add.make_args(b): if not bi.is_integer: nonint.append(bi) b = Add(*nonint) if b.is_number and match[a].is_real: mod = b % match[a] reps = dict([(m, m.args[0]) for m in mod.atoms(Mod) if not m.args[0].is_real]) mod = mod.xreplace(reps) expr = match[a] * n + mod else: expr = match[a] * n + b if expr != f.expr: return ImageSet(Lambda(n, expr), S.Integers)
def _intersect(self, other): from sympy import Dummy from sympy.solvers.diophantine import diophantine from sympy.sets.sets import imageset if self.base_set is S.Integers: if isinstance(other, ImageSet) and other.base_set is S.Integers: f, g = self.lamda.expr, other.lamda.expr n, m = self.lamda.variables[0], other.lamda.variables[0] # Diophantine sorts the solutions according to the alphabetic # order of the variable names, since the result should not depend # on the variable name, they are replaced by the dummy variables # below a, b = Dummy('a'), Dummy('b') f, g = f.subs(n, a), g.subs(m, b) solns_set = diophantine(f - g) if solns_set == set(): return EmptySet() solns = list(diophantine(f - g)) if len(solns) == 1: t = list(solns[0][0].free_symbols)[0] else: return None # since 'a' < 'b' return imageset(Lambda(t, f.subs(a, solns[0][0])), S.Integers) if other == S.Reals: from sympy.solvers.solveset import solveset_real from sympy.core.function import expand_complex if len(self.lamda.variables) > 1: return None f = self.lamda.expr n = self.lamda.variables[0] n_ = Dummy(n.name, real=True) f_ = f.subs(n, n_) re, im = f_.as_real_imag() im = expand_complex(im) return imageset(Lambda(n_, re), self.base_set.intersect( solveset_real(im, n_)))
def _solve_as_poly(f, symbol, solveset_solver, invert_func): """ Solve the equation using polynomial techniques if it already is a polynomial equation or, with a change of variables, can be made so. """ result = None if f.is_polynomial(symbol): solns = roots(f, symbol, cubics=True, quartics=True, quintics=True, domain='EX') num_roots = sum(solns.values()) if degree(f, symbol) <= num_roots: result = FiniteSet(*solns.keys()) else: poly = Poly(f, symbol) solns = poly.all_roots() if poly.degree() <= len(solns): result = FiniteSet(*solns) else: result = ConditionSet(Lambda(symbol, Eq(f, 0)), S.Complexes) else: poly = Poly(f) if poly is None: result = ConditionSet(Lambda(symbol, Eq(f, 0)), S.Complexes) gens = [g for g in poly.gens if g.has(symbol)] if len(gens) == 1: poly = Poly(poly, gens[0]) gen = poly.gen deg = poly.degree() poly = Poly(poly.as_expr(), poly.gen, composite=True) poly_solns = FiniteSet(*roots(poly, cubics=True, quartics=True, quintics=True).keys()) if len(poly_solns) < deg: result = ConditionSet(Lambda(symbol, Eq(f, 0)), S.Complexes) if gen != symbol: y = Dummy('y') lhs, rhs_s = invert_func(gen, y, symbol) if lhs is symbol: result = Union(*[rhs_s.subs(y, s) for s in poly_solns]) else: result = ConditionSet(Lambda(symbol, Eq(f, 0)), S.Complexes) else: result = ConditionSet(Lambda(symbol, Eq(f, 0)), S.Complexes) if result is not None: if isinstance(result, FiniteSet): # this is to simplify solutions like -sqrt(-I) to sqrt(2)/2 # - sqrt(2)*I/2. We are not expanding for solution with free # variables because that makes the solution more complicated. For # example expand_complex(a) returns re(a) + I*im(a) if all([s.free_symbols == set() and not isinstance(s, RootOf) for s in result]): s = Dummy('s') result = imageset(Lambda(s, expand_complex(s)), result) return result else: return ConditionSet(Lambda(symbol, Eq(f, 0)), S.Complexes)
def test_free_symbols(): assert ConditionSet(x, Eq(y, 0), FiniteSet(z) ).free_symbols == {y, z} assert ConditionSet(x, Eq(x, 0), FiniteSet(z) ).free_symbols == {z} assert ConditionSet(x, Eq(x, 0), FiniteSet(x, z) ).free_symbols == {x, z} assert ConditionSet(x, Eq(x, 0), ImageSet(Lambda(y, y**2), S.Integers)).free_symbols == set()
def test_as_dummy(): u, v, x, y, z, _0, _1 = symbols('u v x y z _0 _1') assert Lambda(x, x + 1).as_dummy() == Lambda(_0, _0 + 1) assert Lambda(x, x + _0).as_dummy() == Lambda(_1, _0 + _1) eq = (1 + Sum(x, (x, 1, x))) ans = 1 + Sum(_0, (_0, 1, x)) once = eq.as_dummy() assert once == ans twice = once.as_dummy() assert twice == ans assert Integral(x + _0, (x, x + 1), (_0, 1, 2) ).as_dummy() == Integral(_0 + _1, (_0, x + 1), (_1, 1, 2)) for T in (Symbol, Dummy): d = T('x', real=True) D = d.as_dummy() assert D != d and D.func == Dummy and D.is_real is None assert Dummy().as_dummy().is_commutative assert Dummy(commutative=False).as_dummy().is_commutative == False
def test_bound_symbols(): assert ConditionSet(x, Eq(y, 0), FiniteSet(z) ).bound_symbols == [x] assert ConditionSet(x, Eq(x, 0), FiniteSet(x, y) ).bound_symbols == [x] assert ConditionSet(x, x < 10, ImageSet(Lambda(y, y**2), S.Integers) ).bound_symbols == [x] assert ConditionSet(x, x < 10, ConditionSet(y, y > 1, S.Integers) ).bound_symbols == [x]
def test_GaussianSymplecticEnsemble(): H = RandomMatrixSymbol('H', 3, 3) _H = MatrixSymbol('_H', 3, 3) G = GSE('O', 3) assert density(G)(H) == exp(-3 * Trace(H**2)) / Integral( exp(-3 * Trace(_H**2)), _H) i, j = (Dummy('i', integer=True, positive=True), Dummy('j', integer=True, positive=True)) l = IndexedBase('l') assert joint_eigen_distribution(G).dummy_eq( Lambda((l[1], l[2], l[3]), 162 * sqrt(3) * exp(-3 * l[1]**2 / 2 - 3 * l[2]**2 / 2 - 3 * l[3]**2 / 2) * Product(Abs(l[i] - l[j])**4, (j, i + 1, 3), (i, 1, 2)) / (5 * pi**Rational(3, 2)))) s = Dummy('s') assert level_spacing_distribution(G).dummy_eq( Lambda(s, S(262144) * s**4 * exp(-64 * s**2 / (9 * pi)) / (729 * pi**3)))
def _get_function_fdiff(self): d = Dummy("d") function = self.function(d) fdiff = function.diff(d) if isinstance(fdiff, Function): fdiff = type(fdiff) else: fdiff = Lambda(d, fdiff) return fdiff
def compute_moment_generating_function(self, **kwargs): """ Compute the moment generating function from the PDF. Returns a Lambda. """ x, t = symbols('x, t', real=True, cls=Dummy) pdf = self.pdf(x) mgf = integrate(exp(t * x) * pdf, (x, self.set)) return Lambda(t, mgf)
def _print_FunctionMatrix(self, expr): from sympy.abc import i, j lamda = expr.lamda if not isinstance(lamda, Lambda): lamda = Lambda((i, j), lamda(i, j)) return '{}(lambda {}: {}, {})'.format( self._module_format(self._module + '.fromfunction'), ', '.join(self._print(arg) for arg in lamda.args[0]), self._print(lamda.args[1]), self._print(expr.shape))
def test_GaussianOrthogonalEnsemble(): H = RandomMatrixSymbol('H', 3, 3) _H = MatrixSymbol('_H', 3, 3) G = GOE('O', 3) assert density(G)(H) == exp(-3 * Trace(H**2) / 4) / Integral( exp(-3 * Trace(_H**2) / 4), _H) i, j = (Dummy('i', integer=True, positive=True), Dummy('j', integer=True, positive=True)) l = IndexedBase('l') assert joint_eigen_distribution(G).dummy_eq( Lambda((l[1], l[2], l[3]), 9 * sqrt(2) * exp(-3 * l[1]**2 / 2 - 3 * l[2]**2 / 2 - 3 * l[3]**2 / 2) * Product(Abs(l[i] - l[j]), (j, i + 1, 3), (i, 1, 2)) / (32 * pi))) s = Dummy('s') assert level_spacing_distribution(G).dummy_eq( Lambda(s, s * pi * exp(-s**2 * pi / 4) / 2))
def compute_characteristic_function(self, **kwargs): """ Compute the characteristic function from the PDF. Returns a Lambda. """ x, t = symbols('x, t', real=True, cls=Dummy) pdf = self.pdf(x) cf = summation(exp(I * t * x) * pdf, (x, self.set.inf, self.set.sup)) return Lambda(t, cf)
def test_CircularOrthogonalEnsemble(): CO = COE('U', 3) j, k = (Dummy('j', integer=True, positive=True), Dummy('k', integer=True, positive=True)) t = IndexedBase('t') assert joint_eigen_distribution(CO).dummy_eq( Lambda((t[1], t[2], t[3]), Product(Abs(exp(I * t[j]) - exp(I * t[k])), (j, k + 1, 3), (k, 1, 2)) / (48 * pi**2)))
def _contains(self, other): from sympy.matrices import Matrix from sympy.solvers.solveset import solveset, linsolve from sympy.utilities.iterables import iterable, cartes L = self.lamda if self._is_multivariate(): if not iterable(L.expr): if iterable(other): return S.false return other.as_numer_denom() in self.func( Lambda(L.variables, L.expr.as_numer_denom()), self.base_set) if len(L.expr) != len(self.lamda.variables): raise NotImplementedError(filldedent(''' Dimensions of input and output of Lambda are different.''')) eqs = [expr - val for val, expr in zip(other, L.expr)] variables = L.variables free = set(variables) if all(i.is_number for i in list(Matrix(eqs).jacobian(variables))): solns = list(linsolve([e - val for e, val in zip(L.expr, other)], variables)) else: syms = [e.free_symbols & free for e in eqs] solns = {} for i, (e, s, v) in enumerate(zip(eqs, syms, other)): if not s: if e != v: return S.false solns[vars[i]] = [v] continue elif len(s) == 1: sy = s.pop() sol = solveset(e, sy) if sol is S.EmptySet: return S.false elif isinstance(sol, FiniteSet): solns[sy] = list(sol) else: raise NotImplementedError else: raise NotImplementedError solns = cartes(*[solns[s] for s in variables]) else: # assume scalar -> scalar mapping solnsSet = solveset(L.expr - other, L.variables[0]) if solnsSet.is_FiniteSet: solns = list(solnsSet) else: raise NotImplementedError(filldedent(''' Determining whether an ImageSet contains %s has not been implemented.''' % func_name(other))) for soln in solns: try: if soln in self.base_set: return S.true except TypeError: return self.base_set.contains(soln.evalf()) return S.false
def test_CircularSymplecticEnsemble(): CS = CSE('U', 3) j, k = (Dummy('j', integer=True, positive=True), Dummy('k', integer=True, positive=True)) t = IndexedBase('t') assert joint_eigen_distribution(CS).dummy_eq( Lambda((t[1], t[2], t[3]), Product( Abs(exp(I * t[j]) - exp(I * t[k]))**4, (j, k + 1, 3), (k, 1, 2)) / (720 * pi**3)))
def test_functions_subs(): f, g = symbols('f g', cls=Function) l = Lambda((x, y), sin(x) + y) assert (g(y, x) + cos(x)).subs(g, l) == sin(y) + x + cos(x) assert (f(x)**2).subs(f, sin) == sin(x)**2 assert (f(x, y)).subs(f, log) == log(x, y) assert (f(x, y)).subs(f, sin) == f(x, y) assert (sin(x) + atan2(x, y)).subs([[atan2, f], [sin, g]]) == \ f(x, y) + g(x) assert (g(f(x + y, x))).subs([[f, l], [g, exp]]) == exp(x + sin(x + y))
def _get_newpspace(self, evaluate=False): x = Dummy('x') parent_dist = self.distribution.args[0] func = Lambda(x, self.distribution.pdf(x, evaluate)) new_pspace = self._transform_pspace(self.symbol, parent_dist, func) if new_pspace is not None: return new_pspace message = ("Compound Distribution for %s is not implemeted yet" % str(parent_dist)) raise NotImplementedError(message)
def fdiff(self, argindex=1): """ Returns the first derivative of the function. """ if argindex == 1: return 1/self.args[0] s = C.Dummy('x') return Lambda(s**(-1), s) else: raise ArgumentIndexError(self, argindex)
def _invert_complex(f, g_ys, symbol): """ Helper function for invert_complex """ if not f.has(symbol): raise ValueError("Inverse of constant function doesn't exist") if f is symbol: return (f, g_ys) n = Dummy('n') if f.is_Add: # f = g + h g, h = f.as_independent(symbol) if g != S.Zero: return _invert_complex(h, imageset(Lambda(n, n - g), g_ys), symbol) if f.is_Mul: # f = g*h g, h = f.as_independent(symbol) if g != S.One: return _invert_complex(h, imageset(Lambda(n, n / g), g_ys), symbol) if hasattr(f, 'inverse') and \ not isinstance(f, TrigonometricFunction) and \ not isinstance(f, exp): if len(f.args) > 1: raise ValueError("Only functions with one argument are supported.") return _invert_complex(f.args[0], imageset(Lambda(n, f.inverse()(n)), g_ys), symbol) if isinstance(f, exp): if isinstance(g_ys, FiniteSet): exp_invs = Union(*[ imageset( Lambda(n, I * (2 * n * pi + arg(g_y)) + log(Abs(g_y))), S.Integers) for g_y in g_ys if g_y != 0 ]) return _invert_complex(f.args[0], exp_invs, symbol) return (f, g_ys)
def test_DifferentialExtension_misc(): # Odd ends assert DifferentialExtension(sin(y)*exp(x), x)._important_attrs == \ (Poly(sin(y)*t0, t0, domain='ZZ[sin(y)]'), Poly(1, t0, domain='ZZ'), [Poly(1, x, domain='ZZ'), Poly(t0, t0, domain='ZZ')], [x, t0], [Lambda(i, exp(i))], [], [None, 'exp'], [None, x]) raises(NotImplementedError, lambda: DifferentialExtension(sin(x), x)) assert DifferentialExtension(10**x, x)._important_attrs == \ (Poly(t0, t0), Poly(1, t0), [Poly(1, x), Poly(log(10)*t0, t0)], [x, t0], [Lambda(i, exp(i*log(10)))], [(exp(x*log(10)), 10**x)], [None, 'exp'], [None, x*log(10)]) assert DifferentialExtension(log(x) + log(x**2), x)._important_attrs in [ (Poly(3*t0, t0), Poly(2, t0), [Poly(1, x), Poly(2/x, t0)], [x, t0], [Lambda(i, log(i**2))], [], [None, ], [], [1], [x**2]), (Poly(3*t0, t0), Poly(1, t0), [Poly(1, x), Poly(1/x, t0)], [x, t0], [Lambda(i, log(i))], [], [None, 'log'], [None, x])] assert DifferentialExtension(S.Zero, x)._important_attrs == \ (Poly(0, x), Poly(1, x), [Poly(1, x)], [x], [], [], [None], [None]) assert DifferentialExtension(tan(atan(x).rewrite(log)), x)._important_attrs == \ (Poly(x, x), Poly(1, x), [Poly(1, x)], [x], [], [], [None], [None])
def test_applyfunc_shape_11_matrices(): M = MatrixSymbol("M", 1, 1) double = Lambda(x, x * 2) expr = M.applyfunc(sin) assert isinstance(expr, ElementwiseApplyFunction) expr = M.applyfunc(double) assert isinstance(expr, MatMul) assert expr == 2 * M
def _marginal_distribution(self, indices, sym): sym = ImmutableMatrix([Indexed(sym, i) for i in indices]) _mu, _sigma = self.mu, self.sigma k = self.mu.shape[0] for i in range(k): if i not in indices: _mu = _mu.row_del(i) _sigma = _sigma.col_del(i) _sigma = _sigma.row_del(i) return Lambda(tuple(sym), S.One/sqrt((2*pi)**(len(_mu))*det(_sigma))*exp( Rational(-1, 2)*(_mu - sym).transpose()*(_sigma.inv()*\ (_mu - sym)))[0])
def compute_quantile(self, **kwargs): """ Compute the Quantile from the PDF. Returns a Lambda. """ x = Dummy('x', integer=True) p = Dummy('p', real=True) left_bound = self.set.inf pdf = self.pdf(x) cdf = summation(pdf, (x, left_bound, x), **kwargs) set = ((x, p <= cdf), ) return Lambda(p, Piecewise(*set))
def pdf(self, x, evaluate=False): dist = self.args[0] randoms = [rv for rv in dist.args if is_random(rv)] if isinstance(dist, SingleFiniteDistribution): y = Dummy('y', integer=True, negative=False) expr = dist.pmf(y) else: y = Dummy('y') expr = dist.pdf(y) for rv in randoms: expr = self._marginalise(expr, rv, evaluate) return Lambda(y, expr)(x)