def test_Mul_is_infinite(): x = Symbol('x') f = Symbol('f', finite=True) i = Symbol('i', infinite=True) z = Dummy(zero=True) nzf = Dummy(finite=True, zero=False) from diofant import Mul assert (x * f).is_finite is None assert (x * i).is_finite is None assert (f * i).is_finite is False assert (x * f * i).is_finite is None assert (z * i).is_finite is False assert (nzf * i).is_finite is False assert (z * f).is_finite is True assert Mul(0, f, evaluate=False).is_finite is True assert Mul(0, i, evaluate=False).is_finite is False assert (x * f).is_infinite is None assert (x * i).is_infinite is None assert (f * i).is_infinite is None assert (x * f * i).is_infinite is None assert (z * i).is_infinite is S.NaN.is_infinite assert (nzf * i).is_infinite is True assert (z * f).is_infinite is False assert Mul(0, f, evaluate=False).is_infinite is False assert Mul(0, i, evaluate=False).is_infinite is S.NaN.is_infinite
def _eval_subs(self, old, new): if old in self.variables: newexpr = self.expr.subs(old, new) i = self.variables.index(old) newvars = list(self.variables) newpt = list(self.point) if new.is_Symbol: newvars[i] = new else: syms = new.free_symbols if len(syms) == 1 or old in syms: if old in syms: var = self.variables[i] else: var = syms.pop() # First, try to substitute self.point in the "new" # expr to see if this is a fixed point. # E.g. O(y).subs(y, sin(x)) point = new.subs(var, self.point[i]) if point != self.point[i]: from diofant.solvers import solve d = Dummy() res = solve(old - new.subs(var, d), d, dict=True) point = d.subs(res[0]).limit(old, self.point[i]) newvars[i] = var newpt[i] = point elif old not in syms: del newvars[i], newpt[i] if not syms and new == self.point[i]: newvars.extend(syms) newpt.extend([S.Zero]*len(syms)) else: return return Order(newexpr, *zip(newvars, newpt))
def arbitrary_point(self, t=None): """ Returns an arbitrary point on the Plane; varying `t` from 0 to 2*pi will move the point in a circle of radius 1 about p1 of the Plane. Examples ======== >>> from diofant.geometry.plane import Plane >>> from diofant.abc import t >>> p = Plane((0, 0, 0), (0, 0, 1), (0, 1, 0)) >>> p.arbitrary_point(t) Point3D(0, cos(t), sin(t)) >>> _.distance(p.p1).simplify() 1 Returns ======= Point3D """ from diofant import cos, sin t = t or Dummy('t') x, y, z = self.normal_vector a, b, c = self.p1.args if x == y == 0: return Point3D(a + cos(t), b + sin(t), c) elif x == z == 0: return Point3D(a + cos(t), b, c + sin(t)) elif y == z == 0: return Point3D(a, b + cos(t), c + sin(t)) m = Dummy() p = self.projection( Point3D(self.p1.x + cos(t), self.p1.y + sin(t), 0) * m) return p.xreplace({m: solve(p.distance(self.p1) - 1, m)[0]})
def test_gamma(): assert Hyper_Function([2, 3], [-1]).gamma == 0 assert Hyper_Function([-2, -3], [-1]).gamma == 2 n = Dummy(integer=True) assert Hyper_Function([-1, n, 1], []).gamma == 1 assert Hyper_Function([-1, -n, 1], []).gamma == 1 p = Dummy(integer=True, positive=True) assert Hyper_Function([-1, p, 1], []).gamma == 1 assert Hyper_Function([-1, -p, 1], []).gamma == 2
def _eval_rewrite_as_Sum(self, arg): from diofant import Sum if arg.is_even: k = Dummy("k", integer=True) j = Dummy("j", integer=True) n = self.args[0] / 2 Em = (S.ImaginaryUnit * Sum( Sum( binomial(k, j) * ((-1)**j * (k - 2 * j)**(2 * n + 1)) / (2**k * S.ImaginaryUnit**k * k), (j, 0, k)), (k, 1, 2 * n + 1))) return Em
def test_Add_is_pos_neg(): # these cover lines not covered by the rest of tests in core n = Symbol('n', negative=True, infinite=True) nn = Symbol('n', nonnegative=True, infinite=True) np = Symbol('n', nonpositive=True, infinite=True) p = Symbol('p', positive=True, infinite=True) r = Dummy(extended_real=True, finite=False) x = Symbol('x') xf = Symbol('xb', finite=True, real=True) assert (n + p).is_positive is None assert (n + x).is_positive is None assert (p + x).is_positive is None assert (n + p).is_negative is None assert (n + x).is_negative is None assert (p + x).is_negative is None assert (n + xf).is_positive is False assert (p + xf).is_positive is True assert (n + xf).is_negative is True assert (p + xf).is_negative is False assert (x - S.Infinity).is_negative is None # issue sympy/sympy#7798 # issue sympy/sympy#8046, 16.2 assert (p + nn).is_positive assert (n + np).is_negative assert (p + r).is_positive is None
def swinnerton_dyer_poly(n, x=None, **args): """Generates n-th Swinnerton-Dyer polynomial in `x`. """ from .numberfields import minimal_polynomial if n <= 0: raise ValueError( "can't generate Swinnerton-Dyer polynomial of order %s" % n) if x is not None: sympify(x) else: x = Dummy('x') if n > 3: p = 2 a = [sqrt(2)] for i in range(2, n + 1): p = nextprime(p) a.append(sqrt(p)) return minimal_polynomial(Add(*a), x, polys=args.get('polys', False)) if n == 1: ex = x**2 - 2 elif n == 2: ex = x**4 - 10 * x**2 + 1 elif n == 3: ex = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576 if not args.get('polys', False): return ex else: return PurePoly(ex, x)
def contains(self, other): """ Is the other GeometryEntity contained within this Segment? Examples ======== >>> from diofant import Point, Segment >>> p1, p2 = Point(0, 1), Point(3, 4) >>> s = Segment(p1, p2) >>> s2 = Segment(p2, p1) >>> s.contains(s2) True """ if isinstance(other, Segment): return other.p1 in self and other.p2 in self elif isinstance(other, Point): if Point.is_collinear(self.p1, self.p2, other): t = Dummy('t') x, y = self.arbitrary_point(t).args if self.p1.x != self.p2.x: ti = solve(x - other.x, t)[0] else: ti = solve(y - other.y, t)[0] if ti.is_number: return 0 <= ti <= 1 return return False
def deltaproduct(f, limit): """Handle products containing a KroneckerDelta. See Also ======== deltasummation diofant.functions.special.tensor_functions.KroneckerDelta diofant.concrete.products.product """ from diofant.concrete.products import product if ((limit[2] - limit[1]) < 0) is S.true: return S.One if not f.has(KroneckerDelta): return product(f, limit) if f.is_Add: # Identify the term in the Add that has a simple KroneckerDelta delta = None terms = [] for arg in sorted(f.args, key=default_sort_key): if delta is None and _has_simple_delta(arg, limit[0]): delta = arg else: terms.append(arg) newexpr = f.func(*terms) k = Dummy("kprime", integer=True) if isinstance(limit[1], int) and isinstance(limit[2], int): result = deltaproduct(newexpr, limit) + sum( deltaproduct(newexpr, (limit[0], limit[1], ik - 1)) * delta.subs(limit[0], ik) * deltaproduct(newexpr, (limit[0], ik + 1, limit[2])) for ik in range(int(limit[1]), int(limit[2] + 1))) else: result = deltaproduct(newexpr, limit) + deltasummation( deltaproduct(newexpr, (limit[0], limit[1], k - 1)) * delta.subs(limit[0], k) * deltaproduct(newexpr, (limit[0], k + 1, limit[2])), (k, limit[1], limit[2]), no_piecewise=_has_simple_delta(newexpr, limit[0])) return _remove_multiple_delta(result) delta, _ = _extract_delta(f, limit[0]) if not delta: g = _expand_delta(f, limit[0]) if f != g: from diofant import factor try: return factor(deltaproduct(g, limit)) except AssertionError: return deltaproduct(g, limit) return product(f, limit) from diofant import Eq c = Eq(limit[2], limit[1] - 1) return _remove_multiple_delta(f.subs(limit[0], limit[1])*KroneckerDelta(limit[2], limit[1])) + \ S.One*_simplify_delta(KroneckerDelta(limit[2], limit[1] - 1))
def _eval_expand_func(self, **hints): from diofant import Sum n = self.args[0] m = self.args[1] if len(self.args) == 2 else 1 if m == S.One: if n.is_Add: off = n.args[0] nnew = n - off if off.is_Integer and off.is_positive: result = [S.One / (nnew + i) for i in range(off, 0, -1)] + [harmonic(nnew)] return Add(*result) elif off.is_Integer and off.is_negative: result = [-S.One / (nnew + i) for i in range(0, off, -1)] + [harmonic(nnew)] return Add(*result) if n.is_Rational: # Expansions for harmonic numbers at general rational arguments (u + p/q) # Split n as u + p/q with p < q p, q = n.as_numer_denom() u = p // q p = p - u * q if u.is_nonnegative and p.is_positive and q.is_positive and p < q: k = Dummy("k") t1 = q * Sum(1 / (q * k + p), (k, 0, u)) t2 = 2 * Sum( cos((2 * pi * p * k) / q) * log(sin((pi * k) / q)), (k, 1, floor((q - 1) / Integer(2)))) t3 = (pi / 2) * cot((pi * p) / q) + log(2 * q) return t1 + t2 - t3 return self
def build_ideal(x, terms): """ Build generators for our ideal. Terms is an iterable with elements of the form (fn, coeff), indicating that we have a generator fn(coeff*x). If any of the terms is trigonometric, sin(x) and cos(x) are guaranteed to appear in terms. Similarly for hyperbolic functions. For tan(n*x), sin(n*x) and cos(n*x) are guaranteed. """ gens = [] I = [] y = Dummy('y') for fn, coeff in terms: for c, s, t, rel in ([cos, sin, tan, cos(x)**2 + sin(x)**2 - 1], [ cosh, sinh, tanh, cosh(x)**2 - sinh(x)**2 - 1 ]): if coeff == 1 and fn in [c, s]: I.append(rel) elif fn == t: I.append(t(coeff * x) * c(coeff * x) - s(coeff * x)) elif fn in [c, s]: cn = fn(coeff * y).expand(trig=True).subs(y, x) I.append(fn(coeff * x) - cn) return list(set(I))
def posify(eq): """Return eq (with generic symbols made positive) and a dictionary containing the mapping between the old and new symbols. Any symbol that has positive=None will be replaced with a positive dummy symbol having the same name. This replacement will allow more symbolic processing of expressions, especially those involving powers and logarithms. A dictionary that can be sent to subs to restore eq to its original symbols is also returned. >>> from diofant import posify, Symbol, log, solve >>> from diofant.abc import x >>> posify(x + Symbol('p', positive=True) + Symbol('n', negative=True)) (n + p + _x, {_x: x}) >>> eq = 1/x >>> log(eq).expand() log(1/x) >>> log(posify(eq)[0]).expand() -log(_x) >>> p, rep = posify(eq) >>> log(p).expand().subs(rep) -log(x) It is possible to apply the same transformations to an iterable of expressions: >>> eq = x**2 - 4 >>> solve(eq, x) [-2, 2] >>> eq_x, reps = posify([eq, x]); eq_x [_x**2 - 4, _x] >>> solve(*eq_x) [2] """ eq = sympify(eq) if iterable(eq): f = type(eq) eq = list(eq) syms = set() for e in eq: syms = syms.union(e.atoms(Symbol)) reps = {} for s in syms: reps.update({v: k for k, v in posify(s)[1].items()}) for i, e in enumerate(eq): eq[i] = e.subs(reps) return f(eq), {r: s for s, r in reps.items()} reps = { s: Dummy(s.name, positive=True) for s in eq.free_symbols if s.is_positive is None } eq = eq.subs(reps) return eq, {r: s for s, r in reps.items()}
def reduce_inequalities(inequalities, symbols=[]): """ Reduce a system of inequalities with rational coefficients. Examples ======== >>> from diofant.solvers.inequalities import reduce_inequalities >>> x = Symbol('x', real=True) >>> y = Symbol('y', real=True) >>> reduce_inequalities(0 <= x + 3, []) -3 <= x >>> reduce_inequalities(0 <= x + y*2 - 1, [x]) -2*y + 1 <= x """ if not iterable(inequalities): inequalities = [inequalities] # prefilter keep = [] for i in inequalities: if isinstance(i, Relational): i = i.func(i.lhs.as_expr() - i.rhs.as_expr(), 0) elif i not in (True, False): i = Eq(i, 0) if i == S.true: continue elif i == S.false: return S.false if i.lhs.is_number: raise NotImplementedError("Couldn't determine truth value of %s" % i) keep.append(i) inequalities = keep del keep gens = reduce(set.union, [i.free_symbols for i in inequalities], set()) if not iterable(symbols): symbols = [symbols] symbols = set(symbols) or gens # make vanilla symbol real recast = { i: Dummy(i.name, extended_real=True) for i in gens if i.is_extended_real is None } inequalities = [i.xreplace(recast) for i in inequalities] symbols = {i.xreplace(recast) for i in symbols} # solve system rv = _reduce_inequalities(inequalities, symbols) # restore original symbols and return return rv.xreplace({v: k for k, v in recast.items()})
def _eval_rewrite_as_Sum(self, n, k_sym=None, symbols=None): from diofant import Sum if (k_sym is not None) or (symbols is not None): return self # Dobinski's formula if not n.is_nonnegative: return self k = Dummy('k', integer=True, nonnegative=True) return 1 / E * Sum(k**n / factorial(k), (k, 0, S.Infinity))
def perpendicular_segment(self, p): """Create a perpendicular line segment from `p` to this line. The enpoints of the segment are ``p`` and the closest point in the line containing self. (If self is not a line, the point might not be in self.) Parameters ========== p : Point3D Returns ======= segment : Segment3D Notes ===== Returns `p` itself if `p` is on this linear entity. See Also ======== perpendicular_line Examples ======== >>> from diofant import Point3D, Line3D >>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(1, 1, 1), Point3D(0, 2, 0) >>> l1 = Line3D(p1, p2) >>> s1 = l1.perpendicular_segment(p3) >>> l1.is_perpendicular(s1) True >>> p3 in s1 True >>> l1.perpendicular_segment(Point3D(4, 0, 0)) Segment3D(Point3D(4/3, 4/3, 4/3), Point3D(4, 0, 0)) """ p = Point3D(p) if p in self: raise NotImplementedError("Given point should not be on the line") t = Dummy() a = self.arbitrary_point(t) b = [i - j for i, j in zip(p.args, a.args)] c = sum(i * j for i, j in zip(b, self.direction_ratio)) d = solve(c, t) e = a.subs(t, d[0]) return Segment3D(p, e)
def contains(self, o): """ Return True if o is on this Line, or False otherwise. Examples ======== >>> from diofant import Line,Point >>> p1, p2 = Point(0, 1), Point(3, 4) >>> l = Line(p1, p2) >>> l.contains(p1) True >>> l.contains((0, 1)) True >>> l.contains((0, 0)) False """ if is_sequence(o): o = Point(o) if isinstance(o, Point): o = o.func(*[simplify(i) for i in o.args]) x, y = Dummy(), Dummy() eq = self.equation(x, y) if not eq.has(y): return (solve(eq, x)[0] - o.x).equals(0) if not eq.has(x): return (solve(eq, y)[0] - o.y).equals(0) return (solve(eq.subs(x, o.x), y)[0] - o.y).equals(0) elif not isinstance(o, LinearEntity): return False elif isinstance(o, Line): return self.equal(o) elif not self.is_similar(o): return False else: return o.p1 in self and o.p2 in self
def random_point(self, seed=None): """ Returns a random point on the Plane. Returns ======= Point3D """ import random if seed is not None: rng = random.Random(seed) else: rng = random t = Dummy('t') return self.arbitrary_point(t).subs(t, Rational(rng.random()))
def cyclotomic_poly(n, x=None, **args): """Generates cyclotomic polynomial of order `n` in `x`. """ if n <= 0: raise ValueError("can't generate cyclotomic polynomial of order %s" % n) poly = DMP(dup_zz_cyclotomic_poly(int(n), ZZ), ZZ) if x is not None: poly = Poly.new(poly, x) else: poly = PurePoly.new(poly, Dummy('x')) if not args.get('polys', False): return poly.as_expr() else: return poly
def __contains__(self, o): from diofant.geometry.line3d import LinearEntity3D from diofant.geometry.line import LinearEntity x, y, z = map(Dummy, 'xyz') k = self.equation(x, y, z) if isinstance(o, Point): o = Point3D(o) if isinstance(o, Point3D): d = k.xreplace(dict(zip((x, y, z), o.args))) return d.equals(0) elif isinstance(o, (LinearEntity, LinearEntity3D)): t = Dummy() d = Point3D(o.arbitrary_point(t)) e = k.subs([(x, d.x), (y, d.y), (z, d.z)]) return e.equals(0) else: return False
def perpendicular_line(self, p): """Create a new Line perpendicular to this linear entity which passes through the point `p`. Parameters ========== p : Point3D Returns ======= line : Line3D See Also ======== is_perpendicular, perpendicular_segment Examples ======== >>> from diofant import Point3D, Line3D >>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(2, 3, 4), Point3D(-2, 2, 0) >>> l1 = Line3D(p1, p2) >>> l2 = l1.perpendicular_line(p3) >>> p3 in l2 True >>> l1.is_perpendicular(l2) True """ p = Point3D(p) if p in self: raise NotImplementedError("Given point should not be on the line") t = Dummy() a = self.arbitrary_point(t) b = [i - j for i, j in zip(p.args, a.args)] c = sum(i * j for i, j in zip(b, self.direction_ratio)) d = solve(c, t) e = a.subs(t, d[0]) return Line3D(p, e)
def mrv_leadterm(e, x): """ Compute the leading term of the series. Returns ======= tuple The leading term `c_0 w^{e_0}` of the series of `e` in terms of the most rapidly varying subexpression `w` in form of the pair ``(c0, e0)`` of Expr. Examples ======== >>> from diofant import Symbol, exp >>> x = Symbol('x', real=True, positive=True) >>> mrv_leadterm(1/exp(-x + exp(-x)) - exp(x), x) (-1, 0) """ if not e.has(x): return e, S.Zero e = e.replace(lambda f: f.is_Pow and f.base != S.Exp1 and f.exp.has(x), lambda f: exp(log(f.base) * f.exp)) e = e.replace( lambda f: f.is_Mul and sum(a.is_Pow for a in f.args) > 1, lambda f: Mul( exp(Add(*[a.exp for a in f.args if a.is_Pow and a.base is S.Exp1])), * [a for a in f.args if not a.is_Pow or a.base is not S.Exp1])) # The positive dummy, w, is used here so log(w*2) etc. will expand. # TODO: For limits of complex functions, the algorithm would have to # be improved, or just find limits of Re and Im components separately. w = Dummy("w", real=True, positive=True) e, logw = rewrite(e, x, w) lt = e.compute_leading_term(w, logx=logw) return lt.as_coeff_exponent(w)
def _eval_expand_func(self, **hints): arg = self.args[0] if arg.is_Rational: if abs(arg.p) > arg.q: x = Dummy('x') n = arg.p // arg.q p = arg.p - n * arg.q return gamma(x + n)._eval_expand_func().subs( x, Rational(p, arg.q)) if arg.is_Add: coeff, tail = arg.as_coeff_add() if coeff and coeff.q != 1: intpart = floor(coeff) tail = (coeff - intpart, ) + tail coeff = intpart tail = arg._new_rawargs(*tail, reeval=False) return gamma(tail) * RisingFactorial(tail, coeff) return self.func(*self.args)
def _eval_expand_func(self, **hints): from diofant import Sum z = self.args[0] if z.is_Rational: p, q = z.as_numer_denom() # General rational arguments (u + p/q) # Split z as n + p/q with p < q n = p // q p = p - n * q if p.is_positive and q.is_positive and p < q: k = Dummy("k") if n.is_positive: return loggamma(p / q) - n * log(q) + Sum( log((k - 1) * q + p), (k, 1, n)) elif n.is_negative: return loggamma( p / q) - n * log(q) + S.Pi * S.ImaginaryUnit * n - Sum( log(k * q - p), (k, 1, -n)) elif n.is_zero: return loggamma(p / q) return self
""" from diofant.simplify.simplify import posify if force: eq, rep = posify(eq) return powdenest(eq, force=False).xreplace(rep) if polar: eq, rep = polarify(eq) return unpolarify(powdenest(unpolarify(eq, exponents_only=True)), rep) new = powsimp(sympify(eq)) return new.xreplace(Transform(_denest_pow, filter=lambda m: m.is_Pow)) _y = Dummy('y') def _denest_pow(eq): """ Denest powers. This is a helper function for powdenest that performs the actual transformation. """ from diofant.simplify.simplify import logcombine b, e = eq.as_base_exp() if b.is_Pow and e != 1: new = b._eval_power(e) if new is not None:
def besselsimp(expr): """ Simplify bessel-type functions. This routine tries to simplify bessel-type functions. Currently it only works on the Bessel J and I functions, however. It works by looking at all such functions in turn, and eliminating factors of "I" and "-1" (actually their polar equivalents) in front of the argument. Then, functions of half-integer order are rewritten using trigonometric functions and functions of integer order (> 1) are rewritten using functions of low order. Finally, if the expression was changed, compute factorization of the result with factor(). >>> from diofant import besselj, besseli, besselsimp, polar_lift, I, Rational >>> from diofant.abc import z, nu >>> besselsimp(besselj(nu, z*polar_lift(-1))) E**(I*pi*nu)*besselj(nu, z) >>> besselsimp(besseli(nu, z*polar_lift(-I))) E**(-I*pi*nu/2)*besselj(nu, z) >>> besselsimp(besseli(Rational(-1, 2), z)) sqrt(2)*cosh(z)/(sqrt(pi)*sqrt(z)) >>> besselsimp(z*besseli(0, z) + z*(besseli(2, z))/2 + besseli(1, z)) 3*z*besseli(0, z)/2 """ # TODO # - better algorithm? # - simplify (cos(pi*b)*besselj(b,z) - besselj(-b,z))/sin(pi*b) ... # - use contiguity relations? def replacer(fro, to, factors): factors = set(factors) def repl(nu, z): if factors.intersection(Mul.make_args(z)): return to(nu, z) return fro(nu, z) return repl def torewrite(fro, to): def tofunc(nu, z): return fro(nu, z).rewrite(to) return tofunc def tominus(fro): def tofunc(nu, z): return exp(I * pi * nu) * fro(nu, exp_polar(-I * pi) * z) return tofunc orig_expr = expr ifactors = [I, exp_polar(I * pi / 2), exp_polar(-I * pi / 2)] expr = expr.replace( besselj, replacer(besselj, torewrite(besselj, besseli), ifactors)) expr = expr.replace( besseli, replacer(besseli, torewrite(besseli, besselj), ifactors)) minusfactors = [-1, exp_polar(I * pi)] expr = expr.replace(besselj, replacer(besselj, tominus(besselj), minusfactors)) expr = expr.replace(besseli, replacer(besseli, tominus(besseli), minusfactors)) z0 = Dummy('z') def expander(fro): def repl(nu, z): if (nu % 1) == Rational(1, 2): return exptrigsimp( trigsimp( unpolarify( fro(nu, z0).rewrite(besselj).rewrite(jn).expand( func=True)).subs(z0, z))) elif nu.is_Integer and nu > 1: return fro(nu, z).expand(func=True) return fro(nu, z) return repl expr = expr.replace(besselj, expander(besselj)) expr = expr.replace(bessely, expander(bessely)) expr = expr.replace(besseli, expander(besseli)) expr = expr.replace(besselk, expander(besselk)) if expr != orig_expr: expr = expr.factor() return expr
def _eval_interval(self, sym, a, b): """Evaluates the function along the sym in a given interval ab""" # FIXME: Currently complex intervals are not supported. A possible # replacement algorithm, discussed in issue 5227, can be found in the # following papers; # http://portal.acm.org/citation.cfm?id=281649 # http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.70.4127&rep=rep1&type=pdf from diofant.functions.elementary.complexes import Abs if sym.is_real is None: d = Dummy('d', real=True) return self.subs(sym, d)._eval_interval(d, a, b) if self.has(Abs): return piecewise_fold(self.rewrite(Abs, Piecewise))._eval_interval( sym, a, b) if a is None or b is None: # In this case, it is just simple substitution return piecewise_fold( super(Piecewise, self)._eval_interval(sym, a, b)) mul = 1 if a == b: return S.Zero elif (a > b) is S.true: a, b, mul = b, a, -1 elif (a <= b) is not S.true: newargs = [] for e, c in self.args: intervals = self._sort_expr_cond(sym, S.NegativeInfinity, S.Infinity, c) values = [] for lower, upper, expr in intervals: if (a < lower) is S.true: mid = lower rep = b val = e._eval_interval(sym, mid, b) val += self._eval_interval(sym, a, mid) elif (a > upper) is S.true: mid = upper rep = b val = e._eval_interval(sym, mid, b) val += self._eval_interval(sym, a, mid) elif (a >= lower) is S.true and (a <= upper) is S.true: rep = b val = e._eval_interval(sym, a, b) elif (b < lower) is S.true: mid = lower rep = a val = e._eval_interval(sym, a, mid) val += self._eval_interval(sym, mid, b) elif (b > upper) is S.true: mid = upper rep = a val = e._eval_interval(sym, a, mid) val += self._eval_interval(sym, mid, b) elif ((b >= lower) is S.true) and ((b <= upper) is S.true): rep = a val = e._eval_interval(sym, a, b) else: raise NotImplementedError( """The evaluation of a Piecewise interval when both the lower and the upper limit are symbolic is not yet implemented.""" ) values.append(val) if len(set(values)) == 1: try: c = c.subs(sym, rep) except AttributeError: pass e = values[0] newargs.append((e, c)) else: for i in range(len(values)): newargs.append( (values[i], (c == S.true and i == len(values) - 1) or And(rep >= intervals[i][0], rep <= intervals[i][1]))) return self.func(*newargs) # Determine what intervals the expr,cond pairs affect. int_expr = self._sort_expr_cond(sym, a, b) # Finally run through the intervals and sum the evaluation. ret_fun = 0 for int_a, int_b, expr in int_expr: if isinstance(expr, Piecewise): # If we still have a Piecewise by now, _sort_expr_cond would # already have determined that its conditions are independent # of the integration variable, thus we just use substitution. ret_fun += piecewise_fold( super(Piecewise, expr)._eval_interval(sym, Max(a, int_a), Min(b, int_b))) else: ret_fun += expr._eval_interval(sym, Max(a, int_a), Min(b, int_b)) return mul * ret_fun
def _eval_rewrite_as_Product(self, n): from diofant import Product if n.is_nonnegative and n.is_integer: i = Dummy('i', integer=True) return Product(i, (i, 1, n))
def intersection(self, o): """The intersection with another geometrical entity. Parameters ========== o : Point or LinearEntity3D Returns ======= intersection : list of geometrical entities See Also ======== diofant.geometry.point.Point3D Examples ======== >>> from diofant import Point3D, Line3D, Segment3D >>> p1, p2, p3 = Point3D(0, 0, 0), Point3D(1, 1, 1), Point3D(7, 7, 7) >>> l1 = Line3D(p1, p2) >>> l1.intersection(p3) [Point3D(7, 7, 7)] >>> l1 = Line3D(Point3D(4,19,12), Point3D(5,25,17)) >>> l2 = Line3D(Point3D(-3, -15, -19), direction_ratio=[2,8,8]) >>> l1.intersection(l2) [Point3D(1, 1, -3)] >>> p6, p7 = Point3D(0, 5, 2), Point3D(2, 6, 3) >>> s1 = Segment3D(p6, p7) >>> l1.intersection(s1) [] """ if isinstance(o, Point3D): if o in self: return [o] else: return [] elif isinstance(o, LinearEntity3D): if self == o: return [self] elif self.is_parallel(o): if isinstance(self, Line3D): if o.p1 in self: return [o] return [] elif isinstance(self, Ray3D): if isinstance(o, Ray3D): # case 1, rays in the same direction if self.xdirection == o.xdirection and \ self.ydirection == o.ydirection and \ self.zdirection == o.zdirection: return [self] if (self.source in o) else [o] # case 2, rays in the opposite directions else: if o.source in self: if self.source == o.source: return [self.source] return [Segment3D(o.source, self.source)] return [] elif isinstance(o, Segment3D): if o.p1 in self: if o.p2 in self: return [o] return [Segment3D(o.p1, self.source)] elif o.p2 in self: return [Segment3D(o.p2, self.source)] return [] elif isinstance(self, Segment3D): if isinstance(o, Segment3D): # A reminder that the points of Segments are ordered # in such a way that the following works. See # Segment3D.__new__ for details on the ordering. if self.p1 not in o: if self.p2 not in o: # Neither of the endpoints are in o so either # o is contained in this segment or it isn't if o in self: return [o] return [] else: # p1 not in o but p2 is. Either there is a # segment as an intersection, or they only # intersect at an endpoint if self.p2 == o.p1: return [o.p1] return [Segment3D(o.p1, self.p2)] elif self.p2 not in o: # p2 not in o but p1 is. Either there is a # segment as an intersection, or they only # intersect at an endpoint if self.p1 == o.p2: return [o.p2] return [Segment3D(o.p2, self.p1)] # Both points of self in o so the whole segment # is in o return [self] else: # unrecognized LinearEntity raise NotImplementedError else: # If the lines are not parallel then solve their arbitrary points # to obtain the point of intersection t = t1, t2 = Dummy(), Dummy() a = self.arbitrary_point(t1) b = o.arbitrary_point(t2) dx = a.x - b.x c = solve([dx, a.y - b.y], t) d = solve([dx, a.z - b.z], t) if len(c) == 1 and len(d) == 1: return [] e = a.subs(t1, c[t1]) if e in self and e in o: return [e] else: return [] return o.intersection(self)
def test_symbols(): assert mcode(x) == "x" d = Dummy("d") assert mcode(d) == "d%s" % d.dummy_index
from diofant import pi, I from diofant.core.singleton import S from diofant.core import Dummy, sympify from diofant.core.function import Function, ArgumentIndexError from diofant.functions import assoc_legendre from diofant.functions.elementary.trigonometric import sin, cos, cot from diofant.functions.combinatorial.factorials import factorial from diofant.functions.elementary.complexes import Abs from diofant.functions.elementary.exponential import exp from diofant.functions.elementary.miscellaneous import sqrt _x = Dummy("dummy_for_spherical_harmonics") class Ynm(Function): r""" Spherical harmonics defined as .. math:: Y_n^m(\theta, \varphi) := \sqrt{\frac{(2n+1)(n-m)!}{4\pi(n+m)!}} \exp(i m \varphi) \mathrm{P}_n^m\left(\cos(\theta)\right) Ynm() gives the spherical harmonic function of order `n` and `m` in `\theta` and `\varphi`, `Y_n^m(\theta, \varphi)`. The four parameters are as follows: `n \geq 0` an integer and `m` an integer such that `-n \leq m \leq n` holds. The two angles are real-valued with `\theta \in [0, \pi]` and `\varphi \in [0, 2\pi]`. Examples ========