def test_reversed(): assert (x < y).reversed == (y > x) assert (x <= y).reversed == (y >= x) assert Eq(x, y, evaluate=False).reversed == Eq(y, x, evaluate=False) assert Ne(x, y, evaluate=False).reversed == Ne(y, x, evaluate=False) assert (x >= y).reversed == (y <= x) assert (x > y).reversed == (y < x)
def test_canonical(): one = Integer(1) def unchanged(v): c = v.canonical return v.is_Relational and c.is_Relational and v == c def isreversed(v): return v.canonical == v.reversed assert unchanged(x < one) assert unchanged(x <= one) assert isreversed(Eq(one, x, evaluate=False)) assert unchanged(Eq(x, one, evaluate=False)) assert isreversed(Ne(one, x, evaluate=False)) assert unchanged(Ne(x, one, evaluate=False)) assert unchanged(x >= one) assert unchanged(x > one) assert unchanged(x < y) assert unchanged(x <= y) assert isreversed(Eq(y, x, evaluate=False)) assert unchanged(Eq(x, y, evaluate=False)) assert isreversed(Ne(y, x, evaluate=False)) assert unchanged(Ne(x, y, evaluate=False)) assert isreversed(x >= y) assert isreversed(x > y) assert (-x < 1).canonical == (x > -1) assert isreversed(-x > y)
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 test_evaluate(): assert str(Eq(x, x, evaluate=False)) == 'Eq(x, x)' assert Eq(x, x, evaluate=False).doit() == S.true assert str(Ne(x, x, evaluate=False)) == 'Ne(x, x)' assert Ne(x, x, evaluate=False).doit() == S.false assert str(Ge(x, x, evaluate=False)) == 'x >= x' assert str(Le(x, x, evaluate=False)) == 'x <= x' assert str(Gt(x, x, evaluate=False)) == 'x > x' assert str(Lt(x, x, evaluate=False)) == 'x < x'
def _eval_is_zero(self): # This is a very naive and quick test, not intended to do the integral to # answer whether it is zero or not, e.g. Integral(sin(x), (x, 0, 2*pi)) # is zero but this routine should return None for that case. But, like # Mul, there are trivial situations for which the integral will be # zero so we check for those. if self.function.is_zero: return True got_false = False free = self.function.free_symbols for xab in self.limits: if len(xab) == 3: z = Eq(xab[1], xab[2]) if z is S.true: return True elif z is S.false: got_false = True elif len(xab) == 2 and xab[0] not in free: if xab[1].is_zero: return True elif xab[1].is_nonzero: got_false = True else: free.add(xab[0]) continue # take integration symbol out of free since it will be replaced # with the free symbols in the limits free.discard(xab[0]) # add in the new symbols for i in xab[1:]: free.update(i.free_symbols) if self.function.is_nonzero and got_false: return False
def test_doit(): p = Symbol('p', positive=True) n = Symbol('n', negative=True) np = Symbol('np', nonpositive=True) nn = Symbol('nn', nonnegative=True) assert Gt(p, 0).doit() is S.true assert Gt(p, 1).doit() == Gt(p, 1) assert Ge(p, 0).doit() is S.true assert Le(p, 0).doit() is S.false assert Lt(n, 0).doit() is S.true assert Le(np, 0).doit() is S.true assert Gt(nn, 0).doit() == Gt(nn, 0) assert Lt(nn, 0).doit() is S.false assert Eq(x, 0).doit() == Eq(x, 0)
def test_relational_bool_output(): # https://github.com/sympy/sympy/issues/5931 pytest.raises(TypeError, lambda: bool(x > 3)) pytest.raises(TypeError, lambda: bool(x >= 3)) pytest.raises(TypeError, lambda: bool(x < 3)) pytest.raises(TypeError, lambda: bool(x <= 3)) pytest.raises(TypeError, lambda: bool(Eq(x, 3))) pytest.raises(TypeError, lambda: bool(Ne(x, 3)))
def test_simplify(): assert simplify(x*(y + 1) - x*y - x + 1 < x) == (x > 1) assert simplify(Integer(1) < -x) == (x < -1) # issue sympy/sympy#10304 d = -(3*2**pi)**(1/pi) + 2*3**(1/pi) assert d.is_real assert simplify(Eq(1 + I*d, 0)) is False
def __new__(cls, p1, pt=None, angle=None, **kwargs): p1 = Point(p1) if pt is not None and angle is None: try: p2 = Point(pt) except NotImplementedError: from diofant.utilities.misc import filldedent raise ValueError(filldedent(''' The 2nd argument was not a valid Point; if it was meant to be an angle it should be given with keyword "angle".''')) if p1 == p2: raise ValueError('A Ray requires two distinct points.') elif angle is not None and pt is None: # we need to know if the angle is an odd multiple of pi/2 c = pi_coeff(sympify(angle)) p2 = None if c is not None: if c.is_Rational: if c.q == 2: if c.p == 1: p2 = p1 + Point(0, 1) elif c.p == 3: p2 = p1 + Point(0, -1) elif c.q == 1: if c.p == 0: p2 = p1 + Point(1, 0) elif c.p == 1: p2 = p1 + Point(-1, 0) if p2 is None: c *= S.Pi else: c = angle % (2*S.Pi) if not p2: m = 2*c/S.Pi left = And(1 < m, m < 3) # is it in quadrant 2 or 3? x = Piecewise((-1, left), (Piecewise((0, Eq(m % 1, 0)), (1, True)), True)) y = Piecewise((-tan(c), left), (Piecewise((1, Eq(m, 1)), (-1, Eq(m, 3)), (tan(c), True)), True)) p2 = p1 + Point(x, y) else: raise ValueError('A 2nd point or keyword "angle" must be used.') return LinearEntity.__new__(cls, p1, p2, **kwargs)
def test_univariate_relational_as_set(): assert (x > 0).as_set() == Interval(0, oo, True, True) assert (x >= 0).as_set() == Interval(0, oo, False, True) assert (x < 0).as_set() == Interval(-oo, 0, True, True) assert (x <= 0).as_set() == Interval(-oo, 0, True) assert Eq(x, 0).as_set() == FiniteSet(0) assert Ne(x, 0).as_set() == Interval(-oo, 0, True, True) + \ Interval(0, oo, True, True) assert (x**2 >= 4).as_set() == (Interval(-oo, -2, True) + Interval(2, oo, False, True))
def test_Eq(): assert Eq(x**2, 0) == Eq(x**2, 0) assert Eq(x**2, 0) != Eq(x**2, 1) pytest.raises(TypeError, lambda: Eq(x)) assert Eq(x, x) # issue sympy/sympy#5719 # issue sympy/sympy#6116 p = Symbol('p', positive=True) assert Eq(p, 0) is false
def test_Eq(): assert Eq(x**2) == Eq(x**2, 0) assert Eq(x**2) != Eq(x**2, 1) assert Eq(x, x) # issue sympy/sympy#5719 # issue sympy/sympy#6116 p = Symbol('p', positive=True) assert Eq(p, 0) is S.false
def test_bool(): assert Eq(0, 0) is S.true assert Eq(1, 0) is S.false assert Ne(0, 0) is S.false assert Ne(1, 0) is S.true assert Lt(0, 1) is S.true assert Lt(1, 0) is S.false assert Le(0, 1) is S.true assert Le(1, 0) is S.false assert Le(0, 0) is S.true assert Gt(1, 0) is S.true assert Gt(0, 1) is S.false assert Ge(1, 0) is S.true assert Ge(0, 1) is S.false assert Ge(1, 1) is S.true assert Eq(I, 2) is S.false assert Ne(I, 2) is S.true pytest.raises(TypeError, lambda: Gt(I, 2)) pytest.raises(TypeError, lambda: Ge(I, 2)) pytest.raises(TypeError, lambda: Lt(I, 2)) pytest.raises(TypeError, lambda: Le(I, 2)) a = Float('.000000000000000000001', '') b = Float('.0000000000000000000001', '') assert Eq(pi + a, pi + b) is S.false
def test_wrappers(): e = x + x**2 res = Relational(y, e, '==') assert Rel(y, x + x**2, '==') == res assert Eq(y, x + x**2) == res res = Relational(y, e, '<') assert Lt(y, x + x**2) == res res = Relational(y, e, '<=') assert Le(y, x + x**2) == res res = Relational(y, e, '>') assert Gt(y, x + x**2) == res res = Relational(y, e, '>=') assert Ge(y, x + x**2) == res res = Relational(y, e, '!=') assert Ne(y, x + x**2) == res
def test_rel_subs(): e = Relational(x, y, '==') e = e.subs(x, z) assert isinstance(e, Equality) assert e.lhs == z assert e.rhs == y e = Relational(x, y, '>=') e = e.subs(x, z) assert isinstance(e, GreaterThan) assert e.lhs == z assert e.rhs == y e = Relational(x, y, '<=') e = e.subs(x, z) assert isinstance(e, LessThan) assert e.lhs == z assert e.rhs == y e = Relational(x, y, '>') e = e.subs(x, z) assert isinstance(e, StrictGreaterThan) assert e.lhs == z assert e.rhs == y e = Relational(x, y, '<') e = e.subs(x, z) assert isinstance(e, StrictLessThan) assert e.lhs == z assert e.rhs == y e = Eq(x, 0) assert e.subs(x, 0) is S.true assert e.subs(x, 1) is S.false
def ufuncify(args, expr, language=None, backend='numpy', tempdir=None, flags=None, verbose=False, helpers=None): """ Generates a binary function that supports broadcasting on numpy arrays. Parameters ---------- args : iterable Either a Symbol or an iterable of symbols. Specifies the argument sequence for the function. expr A Diofant expression that defines the element wise operation. language : string, optional If supplied, (options: 'C' or 'F95'), specifies the language of the generated code. If ``None`` [default], the language is inferred based upon the specified backend. backend : string, optional Backend used to wrap the generated code. Either 'numpy' [default], 'cython', or 'f2py'. tempdir : string, optional Path to directory for temporary files. If this argument is supplied, the generated code and the wrapper input files are left intact in the specified path. flags : iterable, optional Additional option flags that will be passed to the backend verbose : bool, optional If True, autowrap will not mute the command line backends. This can be helpful for debugging. helpers : iterable, optional Used to define auxillary expressions needed for the main expr. If the main expression needs to call a specialized function it should be put in the ``helpers`` iterable. Autowrap will then make sure that the compiled main expression can link to the helper routine. Items should be tuples with (<funtion_name>, <diofant_expression>, <arguments>). It is mandatory to supply an argument sequence to helper routines. Notes ----- The default backend ('numpy') will create actual instances of ``numpy.ufunc``. These support ndimensional broadcasting, and implicit type conversion. Use of the other backends will result in a "ufunc-like" function, which requires equal length 1-dimensional arrays for all arguments, and will not perform any type conversions. References ---------- .. [1] http://docs.scipy.org/doc/numpy/reference/ufuncs.html Examples -------- >>> from diofant.utilities.autowrap import ufuncify >>> from diofant.abc import x, y >>> import numpy as np >>> f = ufuncify((x, y), y + x**2) >>> type(f) is np.ufunc True >>> f([1, 2, 3], 2) array([ 3., 6., 11.]) >>> f(np.arange(5), 3) array([ 3., 4., 7., 12., 19.]) For the F2Py and Cython backends, inputs are required to be equal length 1-dimensional arrays. The F2Py backend will perform type conversion, but the Cython backend will error if the inputs are not of the expected type. >>> f_fortran = ufuncify((x, y), y + x**2, backend='F2Py') >>> f_fortran(1, 2) 3 >>> f_fortran(numpy.array([1, 2, 3]), numpy.array([1.0, 2.0, 3.0])) array([2., 6., 12.]) >>> f_cython = ufuncify((x, y), y + x**2, backend='Cython') >>> f_cython(1, 2) Traceback (most recent call last): ... TypeError: Argument '_x' has incorrect type (expected numpy.ndarray, got int) >>> f_cython(numpy.array([1.0]), numpy.array([2.0])) array([ 3.]) """ if isinstance(args, (Dummy, Symbol)): args = (args, ) else: args = tuple(args) if language: _validate_backend_language(backend, language) else: language = _infer_language(backend) helpers = helpers if helpers else () flags = flags if flags else () if backend.upper() == 'NUMPY': routine = make_routine('autofunc', expr, args) helps = [] for name, expr, args in helpers: helps.append(make_routine(name, expr, args)) code_wrapper = UfuncifyCodeWrapper(CCodeGen("ufuncify"), tempdir, flags, verbose) return code_wrapper.wrap_code(routine, helpers=helps) else: # Dummies are used for all added expressions to prevent name clashes # within the original expression. y = IndexedBase(Dummy()) m = Dummy(integer=True) i = Idx(Dummy(integer=True), m) f = implemented_function(Dummy().name, Lambda(args, expr)) # For each of the args create an indexed version. indexed_args = [IndexedBase(Dummy(str(a))) for a in args] # Order the arguments (out, args, dim) args = [y] + indexed_args + [m] args_with_indices = [a[i] for a in indexed_args] return autowrap(Eq(y[i], f(*args_with_indices)), language, backend, tempdir, tuple(args), flags, verbose, helpers)
def test_equals(): f = Function('f') assert Eq(x, 1).equals(Eq(x * (y + 1) - x * y - x + 1, x)) assert Eq(x, y).equals(x < y, True) is False assert Eq(x, f(1)).equals(Eq(x, f(2)), True) == f(1) - f(2) assert Eq(f(1), y).equals(Eq(f(2), y), True) == f(1) - f(2) assert Eq(x, f(1)).equals(Eq(f(2), x), True) == f(1) - f(2) assert Eq(f(1), x).equals(Eq(x, f(2)), True) == f(1) - f(2) assert Eq(w, x).equals(Eq(y, z), True) is False assert Eq(f(1), f(2)).equals(Eq(f(3), f(4)), True) == f(1) - f(3) assert (x < y).equals(y > x, True) is True assert (x < y).equals(y >= x, True) is False assert (x < y).equals(z < y, True) is False assert (x < y).equals(x < z, True) is False assert (x < f(1)).equals(x < f(2), True) == f(1) - f(2) assert (f(1) < x).equals(f(2) < x, True) == f(1) - f(2)
def roots_quartic(f): r""" Returns a list of roots of a quartic polynomial. There are many references for solving quartic expressions available [1-5]. This reviewer has found that many of them require one to select from among 2 or more possible sets of solutions and that some solutions work when one is searching for real roots but don't work when searching for complex roots (though this is not always stated clearly). The following routine has been tested and found to be correct for 0, 2 or 4 complex roots. The quasisymmetric case solution [6] looks for quartics that have the form `x**4 + A*x**3 + B*x**2 + C*x + D = 0` where `(C/A)**2 = D`. Although no general solution that is always applicable for all coefficients is known to this reviewer, certain conditions are tested to determine the simplest 4 expressions that can be returned: 1) `f = c + a*(a**2/8 - b/2) == 0` 2) `g = d - a*(a*(3*a**2/256 - b/16) + c/4) = 0` 3) if `f != 0` and `g != 0` and `p = -d + a*c/4 - b**2/12` then a) `p == 0` b) `p != 0` Examples ======== >>> from diofant import Poly, symbols, I >>> r = roots_quartic(Poly('x**4-6*x**3+17*x**2-26*x+20')) >>> # 4 complex roots: 1+-I*sqrt(3), 2+-I >>> sorted(str(tmp.evalf(n=2)) for tmp in r) ['1.0 + 1.7*I', '1.0 - 1.7*I', '2.0 + 1.0*I', '2.0 - 1.0*I'] References ========== .. [1] http://mathforum.org/dr.math/faq/faq.cubic.equations.html .. [2] http://en.wikipedia.org/wiki/Quartic_function#Summary_of_Ferrari.27s_method .. [3] http://planetmath.org/encyclopedia/GaloisTheoreticDerivationOfTheQuarticFormula.html .. [4] http://staff.bath.ac.uk/masjhd/JHD-CA.pdf .. [5] http://www.albmath.org/files/Math_5713.pdf .. [6] http://www.statemaster.com/encyclopedia/Quartic-equation .. [7] eqworld.ipmnet.ru/en/solutions/ae/ae0108.pdf """ _, a, b, c, d = f.monic().all_coeffs() if not d: return [S.Zero] + roots([1, a, b, c], multiple=True) elif (c/a)**2 == d: x, m = f.gen, c/a g = Poly(x**2 + a*x + b - 2*m, x) z1, z2 = roots_quadratic(g) h1 = Poly(x**2 - z1*x + m, x) h2 = Poly(x**2 - z2*x + m, x) r1 = roots_quadratic(h1) r2 = roots_quadratic(h2) return r1 + r2 else: a2 = a**2 e = b - 3*a2/8 f = c + a*(a2/8 - b/2) g = d - a*(a*(3*a2/256 - b/16) + c/4) aon4 = a/4 if f is S.Zero: y1, y2 = [sqrt(tmp) for tmp in roots([1, e, g], multiple=True)] return [tmp - aon4 for tmp in [-y1, -y2, y1, y2]] if g is S.Zero: y = [S.Zero] + roots([1, 0, e, f], multiple=True) return [tmp - aon4 for tmp in y] else: # Descartes-Euler method, see [7] sols = _roots_quartic_euler(e, f, g, aon4) if sols: return sols # Ferrari method, see [1, 2] a2 = a**2 e = b - 3*a2/8 f = c + a*(a2/8 - b/2) g = d - a*(a*(3*a2/256 - b/16) + c/4) p = -e**2/12 - g q = -e**3/108 + e*g/3 - f**2/8 TH = Rational(1, 3) def _ans(y): w = sqrt(e + 2*y) arg1 = 3*e + 2*y arg2 = 2*f/w ans = [] for s in [-1, 1]: root = sqrt(-(arg1 + s*arg2)) for t in [-1, 1]: ans.append((s*w - t*root)/2 - aon4) return ans # p == 0 case y1 = -5*e/6 - q**TH if p.is_zero: return _ans(y1) # if p != 0 then u below is not 0 root = sqrt(q**2/4 + p**3/27) r = -q/2 + root # or -q/2 - root u = r**TH # primary root of solve(x**3 - r, x) y2 = -5*e/6 + u - p/u/3 if p.is_nonzero: return _ans(y2) # sort it out once they know the values of the coefficients return [Piecewise((a1, Eq(p, 0)), (a2, True)) for a1, a2 in zip(_ans(y1), _ans(y2))]
def eval_sum_symbolic(f, limits): from diofant.functions import harmonic, bernoulli f_orig = f (i, a, b) = limits if not f.has(i): return f * (b - a + 1) # Linearity if f.is_Mul: L, R = f.as_two_terms() if not L.has(i): sR = eval_sum_symbolic(R, (i, a, b)) if sR: return L * sR if not R.has(i): sL = eval_sum_symbolic(L, (i, a, b)) if sL: return R * sL try: f = apart(f, i) # see if it becomes an Add except PolynomialError: pass if f.is_Add: L, R = f.as_two_terms() lrsum = telescopic(L, R, (i, a, b)) if lrsum: return lrsum lsum = eval_sum_symbolic(L, (i, a, b)) rsum = eval_sum_symbolic(R, (i, a, b)) if None not in (lsum, rsum): r = lsum + rsum if r is not S.NaN: return r # Polynomial terms with Faulhaber's formula n = Wild('n') result = f.match(i**n) if result is not None: n = result[n] if n.is_Integer: if n >= 0: if (b is S.Infinity and a is not S.NegativeInfinity) or \ (a is S.NegativeInfinity and b is not S.Infinity): return S.Infinity return ((bernoulli(n + 1, b + 1) - bernoulli(n + 1, a)) / (n + 1)).expand() elif a.is_Integer and a >= 1: if n == -1: return harmonic(b) - harmonic(a - 1) else: return harmonic(b, abs(n)) - harmonic(a - 1, abs(n)) if not (a.has(S.Infinity, S.NegativeInfinity) or b.has(S.Infinity, S.NegativeInfinity)): # Geometric terms c1 = Wild('c1', exclude=[i]) c2 = Wild('c2', exclude=[i]) c3 = Wild('c3', exclude=[i]) e = f.match(c1**(c2 * i + c3)) if e is not None: p = (c1**c3).subs(e) q = (c1**c2).subs(e) r = p * (q**a - q**(b + 1)) / (1 - q) l = p * (b - a + 1) return Piecewise((l, Eq(q, S.One)), (r, True)) r = gosper_sum(f, (i, a, b)) if r is not None and r.is_finite: return r return eval_sum_hyper(f_orig, (i, a, b))
def _eval_integral(self, f, x, meijerg=None, risch=None, conds='piecewise'): """ Calculate the anti-derivative to the function f(x). The following algorithms are applied (roughly in this order): 1. Simple heuristics (based on pattern matching and integral table): - most frequently used functions (e.g. polynomials, products of trig functions) 2. Integration of rational functions: - A complete algorithm for integrating rational functions is implemented (the Lazard-Rioboo-Trager algorithm). The algorithm also uses the partial fraction decomposition algorithm implemented in apart() as a preprocessor to make this process faster. Note that the integral of a rational function is always elementary, but in general, it may include a RootSum. 3. Full Risch algorithm: - The Risch algorithm is a complete decision procedure for integrating elementary functions, which means that given any elementary function, it will either compute an elementary antiderivative, or else prove that none exists. Currently, part of transcendental case is implemented, meaning elementary integrals containing exponentials, logarithms, and (soon!) trigonometric functions can be computed. The algebraic case, e.g., functions containing roots, is much more difficult and is not implemented yet. - If the routine fails (because the integrand is not elementary, or because a case is not implemented yet), it continues on to the next algorithms below. If the routine proves that the integrals is nonelementary, it still moves on to the algorithms below, because we might be able to find a closed-form solution in terms of special functions. If risch=True, however, it will stop here. 4. The Meijer G-Function algorithm: - This algorithm works by first rewriting the integrand in terms of very general Meijer G-Function (meijerg in Diofant), integrating it, and then rewriting the result back, if possible. This algorithm is particularly powerful for definite integrals (which is actually part of a different method of Integral), since it can compute closed-form solutions of definite integrals even when no closed-form indefinite integral exists. But it also is capable of computing many indefinite integrals as well. - Another advantage of this method is that it can use some results about the Meijer G-Function to give a result in terms of a Piecewise expression, which allows to express conditionally convergent integrals. - Setting meijerg=True will cause integrate() to use only this method. 5. The Heuristic Risch algorithm: - This is a heuristic version of the Risch algorithm, meaning that it is not deterministic. This is tried as a last resort because it can be very slow. It is still used because not enough of the full Risch algorithm is implemented, so that there are still some integrals that can only be computed using this method. The goal is to implement enough of the Risch and Meijer G-function methods so that this can be deleted. """ from diofant.integrals.deltafunctions import deltaintegrate from diofant.integrals.heurisch import heurisch, heurisch_wrapper from diofant.integrals.rationaltools import ratint from diofant.integrals.risch import risch_integrate if risch: try: return risch_integrate(f, x, conds=conds) except NotImplementedError: return # if it is a poly(x) then let the polynomial integrate itself (fast) # # It is important to make this check first, otherwise the other code # will return a diofant expression instead of a Polynomial. # # see Polynomial for details. if isinstance(f, Poly) and not meijerg: return f.integrate(x) # Piecewise antiderivatives need to call special integrate. if f.func is Piecewise: return f._eval_integral(x) # let's cut it short if `f` does not depend on `x` if not f.has(x): return f * x # try to convert to poly(x) and then integrate if successful (fast) poly = f.as_poly(x) if poly is not None and not meijerg: return poly.integrate().as_expr() if risch is not False: try: result, i = risch_integrate(f, x, separate_integral=True, conds=conds) except NotImplementedError: pass else: if i: # There was a nonelementary integral. Try integrating it. return result + i.doit(risch=False) else: return result # since Integral(f=g1+g2+...) == Integral(g1) + Integral(g2) + ... # we are going to handle Add terms separately, # if `f` is not Add -- we only have one term # Note that in general, this is a bad idea, because Integral(g1) + # Integral(g2) might not be computable, even if Integral(g1 + g2) is. # For example, Integral(x**x + x**x*log(x)). But many heuristics only # work term-wise. So we compute this step last, after trying # risch_integrate. We also try risch_integrate again in this loop, # because maybe the integral is a sum of an elementary part and a # nonelementary part (like erf(x) + exp(x)). risch_integrate() is # quite fast, so this is acceptable. parts = [] args = Add.make_args(f) for g in args: coeff, g = g.as_independent(x) # g(x) = const if g is S.One and not meijerg: parts.append(coeff * x) continue # g(x) = expr + O(x**n) order_term = g.getO() if order_term is not None: h = self._eval_integral(g.removeO(), x) if h is not None: parts.append(coeff * (h + self.func(order_term, *self.limits))) continue # NOTE: if there is O(x**n) and we fail to integrate then there is # no point in trying other methods because they will fail anyway. return # c # g(x) = (a*x+b) if g.is_Pow and not g.exp.has(x) and not meijerg: a = Wild('a', exclude=[x]) b = Wild('b', exclude=[x]) M = g.base.match(a * x + b) if M is not None: if g.exp == -1: h = log(g.base) elif conds != 'piecewise': h = g.base**(g.exp + 1) / (g.exp + 1) else: h1 = log(g.base) h2 = g.base**(g.exp + 1) / (g.exp + 1) h = Piecewise((h1, Eq(g.exp, -1)), (h2, True)) parts.append(coeff * h / M[a]) continue # poly(x) # g(x) = ------- # poly(x) if g.is_rational_function(x) and not meijerg: parts.append(coeff * ratint(g, x)) continue if not meijerg: # g(x) = Mul(trig) h = trigintegrate(g, x, conds=conds) if h is not None: parts.append(coeff * h) continue # g(x) has at least a DiracDelta term h = deltaintegrate(g, x) if h is not None: parts.append(coeff * h) continue # Try risch again. if risch is not False: try: h, i = risch_integrate(g, x, separate_integral=True, conds=conds) except NotImplementedError: h = None else: if i: h = h + i.doit(risch=False) parts.append(coeff * h) continue # fall back to heurisch try: if conds == 'piecewise': h = heurisch_wrapper(g, x, hints=[]) else: h = heurisch(g, x, hints=[]) except PolynomialError: # XXX: this exception means there is a bug in the # implementation of heuristic Risch integration # algorithm. h = None else: h = None if meijerg is not False and h is None: # rewrite using G functions try: h = meijerint_indefinite(g, x) except NotImplementedError: from diofant.integrals.meijerint import _debug _debug('NotImplementedError from meijerint_definite') res = None if h is not None: parts.append(coeff * h) continue # if we failed maybe it was because we had # a product that could have been expanded, # so let's try an expansion of the whole # thing before giving up; we don't try this # at the outset because there are things # that cannot be solved unless they are # NOT expanded e.g., x**x*(1+log(x)). There # should probably be a checker somewhere in this # routine to look for such cases and try to do # collection on the expressions if they are already # in an expanded form if not h and len(args) == 1: f = f.expand(mul=True, deep=False) if f.is_Add: # Note: risch will be identical on the expanded # expression, but maybe it will be able to pick out parts, # like x*(exp(x) + erf(x)). return self._eval_integral(f, x, meijerg=meijerg, risch=risch, conds=conds) if h is not None: parts.append(coeff * h) else: return return Add(*parts)
def test_sympyissue_10633(): assert Eq(True, False) is S.false assert Eq(False, True) is S.false assert Eq(True, True) is S.true assert Eq(False, False) is S.true
def test_new_relational(): assert Eq(x) == Relational(x, 0) # None ==> Equality assert Eq(x) == Relational(x, 0, '==') assert Eq(x) == Relational(x, 0, 'eq') assert Eq(x) == Equality(x, 0) assert Eq(x, -1) == Relational(x, -1) # None ==> Equality assert Eq(x, -1) == Relational(x, -1, '==') assert Eq(x, -1) == Relational(x, -1, 'eq') assert Eq(x, -1) == Equality(x, -1) assert Eq(x) != Relational(x, 1) # None ==> Equality assert Eq(x) != Relational(x, 1, '==') assert Eq(x) != Relational(x, 1, 'eq') assert Eq(x) != Equality(x, 1) assert Eq(x, -1) != Relational(x, 1) # None ==> Equality assert Eq(x, -1) != Relational(x, 1, '==') assert Eq(x, -1) != Relational(x, 1, 'eq') assert Eq(x, -1) != Equality(x, 1) assert Ne(x, 0) == Relational(x, 0, '!=') assert Ne(x, 0) == Relational(x, 0, '<>') assert Ne(x, 0) == Relational(x, 0, 'ne') assert Ne(x, 0) == Unequality(x, 0) assert Ne(x, 0) != Relational(x, 1, '!=') assert Ne(x, 0) != Relational(x, 1, '<>') assert Ne(x, 0) != Relational(x, 1, 'ne') assert Ne(x, 0) != Unequality(x, 1) assert Ge(x, 0) == Relational(x, 0, '>=') assert Ge(x, 0) == Relational(x, 0, 'ge') assert Ge(x, 0) == GreaterThan(x, 0) assert Ge(x, 1) != Relational(x, 0, '>=') assert Ge(x, 1) != Relational(x, 0, 'ge') assert Ge(x, 1) != GreaterThan(x, 0) assert (x >= 1) == Relational(x, 1, '>=') assert (x >= 1) == Relational(x, 1, 'ge') assert (x >= 1) == GreaterThan(x, 1) assert (x >= 0) != Relational(x, 1, '>=') assert (x >= 0) != Relational(x, 1, 'ge') assert (x >= 0) != GreaterThan(x, 1) assert Le(x, 0) == Relational(x, 0, '<=') assert Le(x, 0) == Relational(x, 0, 'le') assert Le(x, 0) == LessThan(x, 0) assert Le(x, 1) != Relational(x, 0, '<=') assert Le(x, 1) != Relational(x, 0, 'le') assert Le(x, 1) != LessThan(x, 0) assert (x <= 1) == Relational(x, 1, '<=') assert (x <= 1) == Relational(x, 1, 'le') assert (x <= 1) == LessThan(x, 1) assert (x <= 0) != Relational(x, 1, '<=') assert (x <= 0) != Relational(x, 1, 'le') assert (x <= 0) != LessThan(x, 1) assert Gt(x, 0) == Relational(x, 0, '>') assert Gt(x, 0) == Relational(x, 0, 'gt') assert Gt(x, 0) == StrictGreaterThan(x, 0) assert Gt(x, 1) != Relational(x, 0, '>') assert Gt(x, 1) != Relational(x, 0, 'gt') assert Gt(x, 1) != StrictGreaterThan(x, 0) assert (x > 1) == Relational(x, 1, '>') assert (x > 1) == Relational(x, 1, 'gt') assert (x > 1) == StrictGreaterThan(x, 1) assert (x > 0) != Relational(x, 1, '>') assert (x > 0) != Relational(x, 1, 'gt') assert (x > 0) != StrictGreaterThan(x, 1) assert Lt(x, 0) == Relational(x, 0, '<') assert Lt(x, 0) == Relational(x, 0, 'lt') assert Lt(x, 0) == StrictLessThan(x, 0) assert Lt(x, 1) != Relational(x, 0, '<') assert Lt(x, 1) != Relational(x, 0, 'lt') assert Lt(x, 1) != StrictLessThan(x, 0) assert (x < 1) == Relational(x, 1, '<') assert (x < 1) == Relational(x, 1, 'lt') assert (x < 1) == StrictLessThan(x, 1) assert (x < 0) != Relational(x, 1, '<') assert (x < 0) != Relational(x, 1, 'lt') assert (x < 0) != StrictLessThan(x, 1) # finally, some fuzz testing for i in range(100): while 1: strtype, length = (chr, 65535) if random.randint(0, 1) else (chr, 255) relation_type = strtype(random.randint(0, length)) if random.randint(0, 1): relation_type += strtype(random.randint(0, length)) if relation_type not in ('==', 'eq', '!=', '<>', 'ne', '>=', 'ge', '<=', 'le', '>', 'gt', '<', 'lt'): break pytest.raises(ValueError, lambda: Relational(x, 1, relation_type))
def _eval_rewrite_as_Piecewise(self, arg): if arg.is_extended_real: return Piecewise((1, arg > 0), (Rational(1, 2), Eq(arg, 0)), (0, True))
def heurisch_wrapper(f, x, rewrite=False, hints=None, mappings=None, retries=3, degree_offset=0, unnecessary_permutations=None): """ A wrapper around the heurisch integration algorithm. This method takes the result from heurisch and checks for poles in the denominator. For each of these poles, the integral is reevaluated, and the final integration result is given in terms of a Piecewise. Examples ======== >>> from diofant.core import symbols >>> from diofant.functions import cos >>> from diofant.integrals.heurisch import heurisch, heurisch_wrapper >>> n, x = symbols('n x') >>> heurisch(cos(n*x), x) sin(n*x)/n >>> heurisch_wrapper(cos(n*x), x) Piecewise((x, Eq(n, 0)), (sin(n*x)/n, true)) See Also ======== diofant.integrals.heurisch.heurisch """ from diofant.solvers.solvers import solve, denoms f = sympify(f) if x not in f.free_symbols: return f * x res = heurisch(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations) if not isinstance(res, Basic): return res # We consider each denominator in the expression, and try to find # cases where one or more symbolic denominator might be zero. The # conditions for these cases are stored in the list slns. slns = [] for d in denoms(res): try: slns += solve(d, dict=True, exclude=(x, )) except NotImplementedError: pass if not slns: return res slns = list(uniq(slns)) # Remove the solutions corresponding to poles in the original expression. slns0 = [] for d in denoms(f): try: slns0 += solve(d, dict=True, exclude=(x, )) except NotImplementedError: pass slns = [s for s in slns if s not in slns0] if not slns: return res if len(slns) > 1: eqs = [] for sub_dict in slns: eqs.extend([Eq(key, value) for key, value in sub_dict.items()]) slns = solve(eqs, dict=True, exclude=(x, )) + slns # For each case listed in the list slns, we reevaluate the integral. pairs = [] for sub_dict in slns: expr = heurisch(f.subs(sub_dict), x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations) cond = And(*[Eq(key, value) for key, value in sub_dict.items()]) pairs.append((expr, cond)) pairs.append((heurisch(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations), True)) return Piecewise(*pairs)