def reduce_inequalities(inequalities, symbols=[]): """Reduce a system of inequalities with rational coefficients. Examples ======== >>> from sympy import sympify as S, Symbol >>> from sympy.abc import x, y >>> from sympy.solvers.inequalities import reduce_inequalities >>> reduce_inequalities(S(0) <= x + 3, []) And(-3 <= x, x < oo) >>> reduce_inequalities(S(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 == True: continue elif i == False: return S.false if i.lhs.is_number: raise NotImplementedError( "could not 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 = dict([(i, Dummy(i.name, real=True)) for i in gens if i.is_real is None]) inequalities = [i.xreplace(recast) for i in inequalities] symbols = set([i.xreplace(recast) for i in symbols]) # solve system rv = _reduce_inequalities(inequalities, symbols) # restore original symbols and return return rv.xreplace(dict([(v, k) for k, v in recast.items()]))
def eval_sum_symbolic(f, limits): from sympy.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 not r is 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 not a is S.NegativeInfinity) or \ (a is S.NegativeInfinity and not b is 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 not r in (None, S.NaN): return r return eval_sum_hyper(f_orig, (i, a, b))
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 do not 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 sympy import Poly >>> from sympy.polys.polyroots import roots_quartic >>> 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. https://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 = _mexpand(c + a * (a2 / 8 - b / 2)) aon4 = a / 4 g = _mexpand(d - aon4 * (a * (3 * a2 / 64 - b / 4) + c)) if f.is_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_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] 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 # whether a Piecewise is returned or not # depends on knowing p, so try to put # in a simple form p = _mexpand(p) # p == 0 case y1 = e * Rational(-5, 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 = e * Rational(-5, 6) + u - p / u / 3 if fuzzy_not(p.is_zero): 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 test_Equality_rewrite_as_Add(): eq = Eq(x + y, y - x) assert eq.rewrite(Add) == 2 * x assert eq.rewrite(Add, evaluate=None).args == (x, x, y, -y) assert eq.rewrite(Add, evaluate=False).args == (x, y, x, -y)
def test_issue_10633(): assert Eq(True, False) == False assert Eq(False, True) == False assert Eq(True, True) == True assert Eq(False, False) == True
def test_issue_10304(): d = cos(1)**2 + sin(1)**2 - 1 assert d.is_comparable is False # if this fails, find a new d e = 1 + d * I assert simplify(Eq(e, 0)) is S.false
def test_new_relational(): x = Symbol('x') 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 from random import randint from sympy.core.compatibility import unichr for i in range(100): while 1: strtype, length = (unichr, 65535) if randint(0, 1) else (chr, 255) relation_type = strtype(randint(0, length)) if randint(0, 1): relation_type += strtype(randint(0, length)) if relation_type not in ('==', 'eq', '!=', '<>', 'ne', '>=', 'ge', '<=', 'le', '>', 'gt', '<', 'lt', ':=', '+=', '-=', '*=', '/=', '%='): break raises(ValueError, lambda: Relational(x, 1, relation_type)) assert all(Relational(x, 0, op).rel_op == '==' for op in ('eq', '==')) assert all( Relational(x, 0, op).rel_op == '!=' for op in ('ne', '<>', '!=')) assert all(Relational(x, 0, op).rel_op == '>' for op in ('gt', '>')) assert all(Relational(x, 0, op).rel_op == '<' for op in ('lt', '<')) assert all(Relational(x, 0, op).rel_op == '>=' for op in ('ge', '>=')) assert all(Relational(x, 0, op).rel_op == '<=' for op in ('le', '<='))
def _preprocess_eqs(eqs): processed_eqs = [] for eq in eqs: processed_eqs.append(eq if isinstance(eq, Equality) else Eq(eq, 0)) return processed_eqs
def test_BooleanFunction_diff(): assert And(x, y).diff(x) == Piecewise((0, Eq(y, False)), (1, True))
def test_simplification(): """ Test working of simplification methods. """ set1 = [[0, 0, 1], [0, 1, 1], [1, 0, 0], [1, 1, 0]] set2 = [[0, 0, 0], [0, 1, 0], [1, 0, 1], [1, 1, 1]] assert SOPform([x, y, z], set1) == Or(And(Not(x), z), And(Not(z), x)) assert Not(SOPform([x, y, z], set2)) == \ Not(Or(And(Not(x), Not(z)), And(x, z))) assert POSform([x, y, z], set1 + set2) is true assert SOPform([x, y, z], set1 + set2) is true assert SOPform([Dummy(), Dummy(), Dummy()], set1 + set2) is true minterms = [[0, 0, 0, 1], [0, 0, 1, 1], [0, 1, 1, 1], [1, 0, 1, 1], [1, 1, 1, 1]] dontcares = [[0, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 1]] assert (SOPform([w, x, y, z], minterms, dontcares) == Or(And(y, z), And(Not(w), Not(x)))) assert POSform([w, x, y, z], minterms, dontcares) == And(Or(Not(w), y), z) minterms = [1, 3, 7, 11, 15] dontcares = [0, 2, 5] assert (SOPform([w, x, y, z], minterms, dontcares) == Or(And(y, z), And(Not(w), Not(x)))) assert POSform([w, x, y, z], minterms, dontcares) == And(Or(Not(w), y), z) minterms = [1, [0, 0, 1, 1], 7, [1, 0, 1, 1], [1, 1, 1, 1]] dontcares = [0, [0, 0, 1, 0], 5] assert (SOPform([w, x, y, z], minterms, dontcares) == Or(And(y, z), And(Not(w), Not(x)))) assert POSform([w, x, y, z], minterms, dontcares) == And(Or(Not(w), y), z) minterms = [1, {y: 1, z: 1}] dontcares = [0, [0, 0, 1, 0], 5] assert (SOPform([w, x, y, z], minterms, dontcares) == Or(And(y, z), And(Not(w), Not(x)))) assert POSform([w, x, y, z], minterms, dontcares) == And(Or(Not(w), y), z) minterms = [{y: 1, z: 1}, 1] dontcares = [[0, 0, 0, 0]] minterms = [[0, 0, 0]] raises(ValueError, lambda: SOPform([w, x, y, z], minterms)) raises(ValueError, lambda: POSform([w, x, y, z], minterms)) raises(TypeError, lambda: POSform([w, x, y, z], ["abcdefg"])) # test simplification ans = And(A, Or(B, C)) assert simplify_logic(A & (B | C)) == ans assert simplify_logic((A & B) | (A & C)) == ans assert simplify_logic(Implies(A, B)) == Or(Not(A), B) assert simplify_logic(Equivalent(A, B)) == \ Or(And(A, B), And(Not(A), Not(B))) assert simplify_logic(And(Equality(A, 2), C)) == And(Equality(A, 2), C) assert simplify_logic(And(Equality(A, 2), A)) is S.false assert simplify_logic(And(Equality(A, 2), A)) == And(Equality(A, 2), A) assert simplify_logic(And(Equality(A, B), C)) == And(Equality(A, B), C) assert simplify_logic(Or(And(Equality(A, 3), B), And(Equality(A, 3), C))) \ == And(Equality(A, 3), Or(B, C)) b = (~x & ~y & ~z) | (~x & ~y & z) e = And(A, b) assert simplify_logic(e) == A & ~x & ~y raises(ValueError, lambda: simplify_logic(A & (B | C), form='blabla')) # Check that expressions with nine variables or more are not simplified # (without the force-flag) a, b, c, d, e, f, g, h, j = symbols('a b c d e f g h j') expr = a & b & c & d & e & f & g & h & j | \ a & b & c & d & e & f & g & h & ~j # This expression can be simplified to get rid of the j variables assert simplify_logic(expr) == expr # check input ans = SOPform([x, y], [[1, 0]]) assert SOPform([x, y], [[1, 0]]) == ans assert POSform([x, y], [[1, 0]]) == ans raises(ValueError, lambda: SOPform([x], [[1]], [[1]])) assert SOPform([x], [[1]], [[0]]) is true assert SOPform([x], [[0]], [[1]]) is true assert SOPform([x], [], []) is false raises(ValueError, lambda: POSform([x], [[1]], [[1]])) assert POSform([x], [[1]], [[0]]) is true assert POSform([x], [[0]], [[1]]) is true assert POSform([x], [], []) is false # check working of simplify assert simplify((A & B) | (A & C)) == And(A, Or(B, C)) assert simplify(And(x, Not(x))) == False assert simplify(Or(x, Not(x))) == True assert simplify(And(Eq(x, 0), Eq(x, y))) == And(Eq(x, 0), Eq(y, 0)) assert And(Eq(x - 1, 0), Eq(x, y)).simplify() == And(Eq(x, 1), Eq(y, 1)) assert And(Ne(x - 1, 0), Ne(x, y)).simplify() == And(Ne(x, 1), Ne(x, y)) assert And(Eq(x - 1, 0), Ne(x, y)).simplify() == And(Eq(x, 1), Ne(y, 1)) assert And(Eq(x - 1, 0), Eq(x, z + y), Eq(y + x, 0)).simplify() == And(Eq(x, 1), Eq(y, -1), Eq(z, 2)) assert And(Eq(x - 1, 0), Eq(x + 2, 3)).simplify() == Eq(x, 1) assert And(Ne(x - 1, 0), Ne(x + 2, 3)).simplify() == Ne(x, 1) assert And(Eq(x - 1, 0), Eq(x + 2, 2)).simplify() == False assert And(Ne(x - 1, 0), Ne(x + 2, 2)).simplify() == And(Ne(x, 1), Ne(x, 0))
def test_relational_simplification(): w, x, y, z = symbols('w x y z', real=True) d, e = symbols('d e', real=False) # Test all combinations or sign and order assert Or(x >= y, x < y).simplify() == S.true assert Or(x >= y, y > x).simplify() == S.true assert Or(x >= y, -x > -y).simplify() == S.true assert Or(x >= y, -y < -x).simplify() == S.true assert Or(-x <= -y, x < y).simplify() == S.true assert Or(-x <= -y, -x > -y).simplify() == S.true assert Or(-x <= -y, y > x).simplify() == S.true assert Or(-x <= -y, -y < -x).simplify() == S.true assert Or(y <= x, x < y).simplify() == S.true assert Or(y <= x, y > x).simplify() == S.true assert Or(y <= x, -x > -y).simplify() == S.true assert Or(y <= x, -y < -x).simplify() == S.true assert Or(-y >= -x, x < y).simplify() == S.true assert Or(-y >= -x, y > x).simplify() == S.true assert Or(-y >= -x, -x > -y).simplify() == S.true assert Or(-y >= -x, -y < -x).simplify() == S.true assert Or(x < y, x >= y).simplify() == S.true assert Or(y > x, x >= y).simplify() == S.true assert Or(-x > -y, x >= y).simplify() == S.true assert Or(-y < -x, x >= y).simplify() == S.true assert Or(x < y, -x <= -y).simplify() == S.true assert Or(-x > -y, -x <= -y).simplify() == S.true assert Or(y > x, -x <= -y).simplify() == S.true assert Or(-y < -x, -x <= -y).simplify() == S.true assert Or(x < y, y <= x).simplify() == S.true assert Or(y > x, y <= x).simplify() == S.true assert Or(-x > -y, y <= x).simplify() == S.true assert Or(-y < -x, y <= x).simplify() == S.true assert Or(x < y, -y >= -x).simplify() == S.true assert Or(y > x, -y >= -x).simplify() == S.true assert Or(-x > -y, -y >= -x).simplify() == S.true assert Or(-y < -x, -y >= -x).simplify() == S.true # Some other tests assert Or(x >= y, w < z, x <= y).simplify() == S.true assert And(x >= y, x < y).simplify() == S.false assert Or(x >= y, Eq(y, x)).simplify() == (x >= y) assert And(x >= y, Eq(y, x)).simplify() == Eq(x, y) assert Or(Eq(x, y), x >= y, w < y, z < y).simplify() == \ Or(x >= y, y > Min(w, z)) assert And(Eq(x, y), x >= y, w < y, y >= z, z < y).simplify() == \ And(Eq(x, y), y > Max(w, z)) assert Or(Eq(x, y), x >= 1, 2 < y, y >= 5, z < y).simplify() == \ (Eq(x, y) | (x >= 1) | (y > Min(2, z))) assert And(Eq(x, y), x >= 1, 2 < y, y >= 5, z < y).simplify() == \ (Eq(x, y) & (x >= 1) & (y >= 5) & (y > z)) assert (Eq(x, y) & Eq(d, e) & (x >= y) & (d >= e)).simplify() == \ (Eq(x, y) & Eq(d, e) & (d >= e)) assert And(Eq(x, y), Eq(x, -y)).simplify() == And(Eq(x, 0), Eq(y, 0)) assert Xor(x >= y, x <= y).simplify() == Ne(x, y)
def test_Piecewise(): assert refine(Piecewise((1, x < 0), (3, True)), Q.is_true(x < 0)) == 1 assert refine(Piecewise((1, x < 0), (3, True)), ~Q.is_true(x < 0)) == 3 assert refine(Piecewise((1, x < 0), (3, True)), Q.is_true(y < 0)) == \ Piecewise((1, x < 0), (3, True)) assert refine(Piecewise((1, x > 0), (3, True)), Q.is_true(x > 0)) == 1 assert refine(Piecewise((1, x > 0), (3, True)), ~Q.is_true(x > 0)) == 3 assert refine(Piecewise((1, x > 0), (3, True)), Q.is_true(y > 0)) == \ Piecewise((1, x > 0), (3, True)) assert refine(Piecewise((1, x <= 0), (3, True)), Q.is_true(x <= 0)) == 1 assert refine(Piecewise((1, x <= 0), (3, True)), ~Q.is_true(x <= 0)) == 3 assert refine(Piecewise((1, x <= 0), (3, True)), Q.is_true(y <= 0)) == \ Piecewise((1, x <= 0), (3, True)) assert refine(Piecewise((1, x >= 0), (3, True)), Q.is_true(x >= 0)) == 1 assert refine(Piecewise((1, x >= 0), (3, True)), ~Q.is_true(x >= 0)) == 3 assert refine(Piecewise((1, x >= 0), (3, True)), Q.is_true(y >= 0)) == \ Piecewise((1, x >= 0), (3, True)) assert refine(Piecewise((1, Eq(x, 0)), (3, True)), Q.is_true(Eq(x, 0)))\ == 1 assert refine(Piecewise((1, Eq(x, 0)), (3, True)), Q.is_true(Eq(0, x)))\ == 1 assert refine(Piecewise((1, Eq(x, 0)), (3, True)), ~Q.is_true(Eq(x, 0)))\ == 3 assert refine(Piecewise((1, Eq(x, 0)), (3, True)), ~Q.is_true(Eq(0, x)))\ == 3 assert refine(Piecewise((1, Eq(x, 0)), (3, True)), Q.is_true(Eq(y, 0)))\ == Piecewise((1, Eq(x, 0)), (3, True)) assert refine(Piecewise((1, Ne(x, 0)), (3, True)), Q.is_true(Ne(x, 0)))\ == 1 assert refine(Piecewise((1, Ne(x, 0)), (3, True)), ~Q.is_true(Ne(x, 0)))\ == 3 assert refine(Piecewise((1, Ne(x, 0)), (3, True)), Q.is_true(Ne(y, 0)))\ == Piecewise((1, Ne(x, 0)), (3, 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 sympy.core import symbols >>> from sympy.functions import cos >>> from sympy.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, n == 0), (sin(n*x)/n, True)) See Also ======== heurisch """ 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.iteritems()]) 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.iteritems()]) pairs.append((expr, cond)) pairs.append((heurisch(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations), True)) return Piecewise(*pairs)
def eval_sum_symbolic(f, limits): from sympy.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: # Try factor out everything not including i without_i, with_i = f.as_independent(i) if without_i != 1: s = eval_sum_symbolic(with_i, (i, a, b)) if s: r = without_i * s if r is not S.NaN: return r else: # Try term by term 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 sL * R 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 # Try factor out everything not including i without_i, with_i = f.as_independent(i) if without_i != 0: s = eval_sum_symbolic(with_i, (i, a, b)) if s: r = without_i * (b - a + 1) + s if r is not S.NaN: return r else: # Try term by term 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 not a is S.NegativeInfinity) or \ (a is S.NegativeInfinity and not b is 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]) wexp = Wild('wexp') # Here we first attempt powsimp on f for easier matching with the # exponential pattern, and attempt expansion on the exponent for easier # matching with the linear pattern. e = f.powsimp().match(c1**wexp) if e is not None: e_exp = e.pop(wexp).expand().match(c2 * i + c3) if e_exp is not None: e.update(e_exp) 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 isinstance(r, (Mul, Add)): from sympy import ordered, Tuple non_limit = r.free_symbols - Tuple(*limits[1:]).free_symbols den = denom(together(r)) den_sym = non_limit & den.free_symbols args = [] for v in ordered(den_sym): try: s = solve(den, v) m = Eq(v, s[0]) if s else S.false if m != False: args.append((Sum(f_orig.subs(*m.args), limits).doit(), m)) break except NotImplementedError: continue args.append((r, True)) return Piecewise(*args) if not r in (None, S.NaN): return r h = eval_sum_hyper(f_orig, (i, a, b)) if h is not None: return h factored = f_orig.factor() if factored != f_orig: return eval_sum_symbolic(factored, (i, a, b))
def recurrence(self): """Equation defining recurrence.""" return Eq(self.y(self.n), self._recurrence)
def _eval_is_eq(lhs, rhs): # noqa: F811 return And(Eq(lhs.left, rhs.left), Eq(lhs.right, rhs.right), lhs.left_open == rhs.left_open, lhs.right_open == rhs.right_open)
def check(pdf, set): x = Dummy('x') val = Sum(pdf(x), (x, set._inf, set._sup)).doit() _value_check(Eq(val, 1) != S.false, "The pdf is incorrect on the given set.")
def canonical_odes(eqs, funcs, t): r""" Function that solves for highest order derivatives in a system Explanation =========== This function inputs a system of ODEs and based on the system, the dependent variables and their highest order, returns the system in the following form: .. math:: X'(t) = A(t) X(t) + b(t) Here, $X(t)$ is the vector of dependent variables of lower order, $A(t)$ is the coefficient matrix, $b(t)$ is the non-homogeneous term and $X'(t)$ is the vector of dependent variables in their respective highest order. We use the term canonical form to imply the system of ODEs which is of the above form. If the system passed has a non-linear term with multiple solutions, then a list of systems is returned in its canonical form. Parameters ========== eqs : List List of the ODEs funcs : List List of dependent variables t : Symbol Independent variable Examples ======== >>> from sympy import symbols, Function, Eq, Derivative >>> from sympy.solvers.ode.systems import canonical_odes >>> f, g = symbols("f g", cls=Function) >>> x, y = symbols("x y") >>> funcs = [f(x), g(x)] >>> eqs = [Eq(f(x).diff(x) - 7*f(x), 12*g(x)), Eq(g(x).diff(x) + g(x), 20*f(x))] >>> canonical_eqs = canonical_odes(eqs, funcs, x) >>> canonical_eqs [Eq(Derivative(f(x), x), 7*f(x) + 12*g(x)), Eq(Derivative(g(x), x), 20*f(x) - g(x))] >>> system = [Eq(Derivative(f(x), x)**2 - 2*Derivative(f(x), x) + 1, 4), Eq(-y*f(x) + Derivative(g(x), x), 0)] >>> canonical_system = canonical_odes(system, funcs, x) >>> canonical_system [[Eq(Derivative(f(x), x), -1), Eq(Derivative(g(x), x), y*f(x))], [Eq(Derivative(f(x), x), 3), Eq(Derivative(g(x), x), y*f(x))]] Returns ======= List """ from sympy.solvers.solvers import solve order = _get_func_order(eqs, funcs) canon_eqs = solve(eqs, *[func.diff(t, order[func]) for func in funcs], dict=True) systems = [] for eq in canon_eqs: system = [ Eq(func.diff(t, order[func]), eq[func.diff(t, order[func])]) for func in funcs ] systems.append(system) if len(canon_eqs) == 1: systems = systems[0] return systems
def test_reduce_inequalities_boolean(): assert reduce_inequalities( [Eq(x**2, 0), True]) == Eq(x, 0) assert reduce_inequalities([Eq(x**2, 0), False]) == False assert reduce_inequalities(x**2 >= 0) is S.true # issue 10196
def test_equals(): w, x, y, z = symbols('w:z') 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) == 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) == 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) == True assert (x < y).equals(y >= x, True) == False assert (x < y).equals(z < y, True) == False assert (x < y).equals(x < z, True) == 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 test__solve_inequalities(): assert reduce_inequalities(x + y < 1, symbols=[x]) == (x < 1 - y) assert reduce_inequalities(x + y >= 1, symbols=[x]) == (x < oo) & (x >= -y + 1) assert reduce_inequalities(Eq(0, x - y), symbols=[x]) == Eq(x, y) assert reduce_inequalities(Ne(0, x - y), symbols=[x]) == Ne(x, y)
def test_issue_10401(): x = symbols('x') fin = symbols('inf', finite=True) inf = symbols('inf', infinite=True) inf2 = symbols('inf2', infinite=True) zero = symbols('z', zero=True) nonzero = symbols('nz', zero=False, finite=True) assert Eq(1 / (1 / x + 1), 1).func is Eq assert Eq(1 / (1 / x + 1), 1).subs(x, S.ComplexInfinity) is S.true assert Eq(1 / (1 / fin + 1), 1) is S.false T, F = S.true, S.false assert Eq(fin, inf) is F assert Eq(inf, inf2) is T and inf != inf2 assert Eq(inf / inf2, 0) is F assert Eq(inf / fin, 0) is F assert Eq(fin / inf, 0) is T assert Eq(zero / nonzero, 0) is T and ((zero / nonzero) != 0) assert Eq(inf, -inf) is F assert Eq(fin / (fin + 1), 1) is S.false o = symbols('o', odd=True) assert Eq(o, 2 * o) is S.false p = symbols('p', positive=True) assert Eq(p / (p - 1), 1) is F
def test_reduce_poly_inequalities_real_interval(): assert reduce_rational_inequalities( [[Eq(x**2, 0)]], x, relational=False) == FiniteSet(0) assert reduce_rational_inequalities( [[Le(x**2, 0)]], x, relational=False) == FiniteSet(0) assert reduce_rational_inequalities( [[Lt(x**2, 0)]], x, relational=False) == S.EmptySet assert reduce_rational_inequalities( [[Ge(x**2, 0)]], x, relational=False) == \ S.Reals if x.is_real else Interval(-oo, oo) assert reduce_rational_inequalities( [[Gt(x**2, 0)]], x, relational=False) == \ FiniteSet(0).complement(S.Reals) assert reduce_rational_inequalities( [[Ne(x**2, 0)]], x, relational=False) == \ FiniteSet(0).complement(S.Reals) assert reduce_rational_inequalities( [[Eq(x**2, 1)]], x, relational=False) == FiniteSet(-1, 1) assert reduce_rational_inequalities( [[Le(x**2, 1)]], x, relational=False) == Interval(-1, 1) assert reduce_rational_inequalities( [[Lt(x**2, 1)]], x, relational=False) == Interval(-1, 1, True, True) assert reduce_rational_inequalities( [[Ge(x**2, 1)]], x, relational=False) == \ Union(Interval(-oo, -1), Interval(1, oo)) assert reduce_rational_inequalities( [[Gt(x**2, 1)]], x, relational=False) == \ Interval(-1, 1).complement(S.Reals) assert reduce_rational_inequalities( [[Ne(x**2, 1)]], x, relational=False) == \ FiniteSet(-1, 1).complement(S.Reals) assert reduce_rational_inequalities([[Eq( x**2, 1.0)]], x, relational=False) == FiniteSet(-1.0, 1.0).evalf() assert reduce_rational_inequalities( [[Le(x**2, 1.0)]], x, relational=False) == Interval(-1.0, 1.0) assert reduce_rational_inequalities([[Lt( x**2, 1.0)]], x, relational=False) == Interval(-1.0, 1.0, True, True) assert reduce_rational_inequalities( [[Ge(x**2, 1.0)]], x, relational=False) == \ Union(Interval(-inf, -1.0), Interval(1.0, inf)) assert reduce_rational_inequalities( [[Gt(x**2, 1.0)]], x, relational=False) == \ Union(Interval(-inf, -1.0, right_open=True), Interval(1.0, inf, left_open=True)) assert reduce_rational_inequalities([[Ne( x**2, 1.0)]], x, relational=False) == \ FiniteSet(-1.0, 1.0).complement(S.Reals) s = sqrt(2) assert reduce_rational_inequalities([[Lt( x**2 - 1, 0), Gt(x**2 - 1, 0)]], x, relational=False) == S.EmptySet assert reduce_rational_inequalities([[Le(x**2 - 1, 0), Ge( x**2 - 1, 0)]], x, relational=False) == FiniteSet(-1, 1) assert reduce_rational_inequalities( [[Le(x**2 - 2, 0), Ge(x**2 - 1, 0)]], x, relational=False ) == Union(Interval(-s, -1, False, False), Interval(1, s, False, False)) assert reduce_rational_inequalities( [[Le(x**2 - 2, 0), Gt(x**2 - 1, 0)]], x, relational=False ) == Union(Interval(-s, -1, False, True), Interval(1, s, True, False)) assert reduce_rational_inequalities( [[Lt(x**2 - 2, 0), Ge(x**2 - 1, 0)]], x, relational=False ) == Union(Interval(-s, -1, True, False), Interval(1, s, False, True)) assert reduce_rational_inequalities( [[Lt(x**2 - 2, 0), Gt(x**2 - 1, 0)]], x, relational=False ) == Union(Interval(-s, -1, True, True), Interval(1, s, True, True)) assert reduce_rational_inequalities( [[Lt(x**2 - 2, 0), Ne(x**2 - 1, 0)]], x, relational=False ) == Union(Interval(-s, -1, True, True), Interval(-1, 1, True, True), Interval(1, s, True, True)) assert reduce_rational_inequalities([[Lt(x**2, -1.)]], x) is S.false
def test_issue_10927(): x = symbols('x') assert str(Eq(x, oo)) == 'Eq(x, oo)' assert str(Eq(x, -oo)) == 'Eq(x, -oo)'
def test_nonpolymonial_relations(): assert Eq(cos(x), 0).simplify() == Eq(cos(x), 0)
def _linear_neq_order1_type3(match_): r""" System of n first-order nonconstant-coefficient linear homogeneous differential equations .. math:: X' = A(t) X where $X$ is the vector of $n$ dependent variables, $t$ is the dependent variable, $X'$ is the first order differential of $X$ with respect to $t$ and $A(t)$ is a $n \times n$ coefficient matrix. Let us define $B$ as antiderivative of coefficient matrix $A$: .. math:: B(t) = \int A(t) dt If the system of ODEs defined above is such that its antiderivative $B(t)$ commutes with $A(t)$ itself, then, the solution of the above system is given as: .. math:: X = \exp(B(t)) C where $C$ is the vector of constants. """ # Some parts of code is repeated, this needs to be taken care of # The constant vector obtained here can be done so in the match # function itself. eq = match_['eq'] func = match_['func'] fc = match_['func_coeff'] n = len(eq) t = list(list(eq[0].atoms(Derivative))[0].atoms(Symbol))[0] constants = numbered_symbols(prefix='C', cls=Symbol, start=1) # This needs to be modified in future so that fc is only of type Matrix M = -fc if type(fc) is Matrix else Matrix(n, n, lambda i, j: -fc[i, func[j], 0]) Cvect = Matrix(list(next(constants) for _ in range(n))) # The code in if block will be removed when it is made sure # that the code works without the statements in if block. if "commutative_antiderivative" not in match_: B, is_commuting = _is_commutative_anti_derivative(M, t) # This course is subject to change if not is_commuting: return None else: B = match_['commutative_antiderivative'] sol_vector = B.exp() * Cvect # The expand_mul is added to handle the solutions so that # the exponential terms are collected properly. sol_vector = [ collect(expand_mul(s), ordered(s.atoms(exp)), exact=True) for s in sol_vector ] sol_dict = [Eq(func[i], sol_vector[i]) for i in range(n)] return sol_dict
def test_simplify_relational(): assert simplify(x * (y + 1) - x * y - x + 1 < x) == (x > 1) assert simplify(x * (y + 1) - x * y - x - 1 < x) == (x > -1) assert simplify(x < x * (y + 1) - x * y - x + 1) == (x < 1) r = S.One < x # canonical operations are not the same as simplification, # so if there is no simplification, canonicalization will # be done unless the measure forbids it assert simplify(r) == r.canonical assert simplify(r, ratio=0) != r.canonical # this is not a random test; in _eval_simplify # this will simplify to S.false and that is the # reason for the 'if r.is_Relational' in Relational's # _eval_simplify routine assert simplify(-(2**(pi * Rational(3, 2)) + 6**pi)**(1 / pi) + 2 * (2**(pi / 2) + 3**pi)**(1 / pi) < 0) is S.false # canonical at least assert Eq(y, x).simplify() == Eq(x, y) assert Eq(x - 1, 0).simplify() == Eq(x, 1) assert Eq(x - 1, x).simplify() == S.false assert Eq(2 * x - 1, x).simplify() == Eq(x, 1) assert Eq(2 * x, 4).simplify() == Eq(x, 2) z = cos(1)**2 + sin(1)**2 - 1 # z.is_zero is None assert Eq(z * x, 0).simplify() == S.true assert Ne(y, x).simplify() == Ne(x, y) assert Ne(x - 1, 0).simplify() == Ne(x, 1) assert Ne(x - 1, x).simplify() == S.true assert Ne(2 * x - 1, x).simplify() == Ne(x, 1) assert Ne(2 * x, 4).simplify() == Ne(x, 2) assert Ne(z * x, 0).simplify() == S.false # No real-valued assumptions assert Ge(y, x).simplify() == Le(x, y) assert Ge(x - 1, 0).simplify() == Ge(x, 1) assert Ge(x - 1, x).simplify() == S.false assert Ge(2 * x - 1, x).simplify() == Ge(x, 1) assert Ge(2 * x, 4).simplify() == Ge(x, 2) assert Ge(z * x, 0).simplify() == S.true assert Ge(x, -2).simplify() == Ge(x, -2) assert Ge(-x, -2).simplify() == Le(x, 2) assert Ge(x, 2).simplify() == Ge(x, 2) assert Ge(-x, 2).simplify() == Le(x, -2) assert Le(y, x).simplify() == Ge(x, y) assert Le(x - 1, 0).simplify() == Le(x, 1) assert Le(x - 1, x).simplify() == S.true assert Le(2 * x - 1, x).simplify() == Le(x, 1) assert Le(2 * x, 4).simplify() == Le(x, 2) assert Le(z * x, 0).simplify() == S.true assert Le(x, -2).simplify() == Le(x, -2) assert Le(-x, -2).simplify() == Ge(x, 2) assert Le(x, 2).simplify() == Le(x, 2) assert Le(-x, 2).simplify() == Ge(x, -2) assert Gt(y, x).simplify() == Lt(x, y) assert Gt(x - 1, 0).simplify() == Gt(x, 1) assert Gt(x - 1, x).simplify() == S.false assert Gt(2 * x - 1, x).simplify() == Gt(x, 1) assert Gt(2 * x, 4).simplify() == Gt(x, 2) assert Gt(z * x, 0).simplify() == S.false assert Gt(x, -2).simplify() == Gt(x, -2) assert Gt(-x, -2).simplify() == Lt(x, 2) assert Gt(x, 2).simplify() == Gt(x, 2) assert Gt(-x, 2).simplify() == Lt(x, -2) assert Lt(y, x).simplify() == Gt(x, y) assert Lt(x - 1, 0).simplify() == Lt(x, 1) assert Lt(x - 1, x).simplify() == S.true assert Lt(2 * x - 1, x).simplify() == Lt(x, 1) assert Lt(2 * x, 4).simplify() == Lt(x, 2) assert Lt(z * x, 0).simplify() == S.false assert Lt(x, -2).simplify() == Lt(x, -2) assert Lt(-x, -2).simplify() == Gt(x, 2) assert Lt(x, 2).simplify() == Lt(x, 2) assert Lt(-x, 2).simplify() == Gt(x, -2)
def as_relational(self, symbol): """Rewrite a FiniteSet in terms of equalities and logic operators. """ from sympy.core.relational import Eq from sympy.logic.boolalg import Or return Or(*[Eq(symbol, elem) for elem in self])
def test_issue_10401(): x = symbols('x') fin = symbols('inf', finite=True) inf = symbols('inf', infinite=True) inf2 = symbols('inf2', infinite=True) infx = symbols('infx', infinite=True, extended_real=True) infx2 = symbols('infx2', infinite=True, extended_real=True) infnx = symbols('inf~x', infinite=True, extended_real=False) infnx2 = symbols('inf~x2', infinite=True, extended_real=False) infp = symbols('infp', infinite=True, extended_positive=True) infp1 = symbols('infp1', infinite=True, extended_positive=True) infn = symbols('infn', infinite=True, extended_negative=True) zero = symbols('z', zero=True) nonzero = symbols('nz', zero=False, finite=True) assert Eq(1 / (1 / x + 1), 1).func is Eq assert Eq(1 / (1 / x + 1), 1).subs(x, S.ComplexInfinity) is S.true assert Eq(1 / (1 / fin + 1), 1) is S.false T, F = S.true, S.false assert Eq(fin, inf) is F assert Eq(inf, inf2) not in (T, F) and inf != inf2 assert Eq(1 + inf, 2 + inf2) not in (T, F) and inf != inf2 assert Eq(infp, infp1) is T assert Eq(infp, infn) is F assert Eq(1 + I * oo, I * oo) is F assert Eq(I * oo, 1 + I * oo) is F assert Eq(1 + I * oo, 2 + I * oo) is F assert Eq(1 + I * oo, 2 + I * infx) is F assert Eq(1 + I * oo, 2 + infx) is F # FIXME: The test below fails because (-infx).is_extended_positive is True # (should be None) #assert Eq(1 + I*infx, 1 + I*infx2) not in (T, F) and infx != infx2 # assert Eq(zoo, sqrt(2) + I * oo) is F assert Eq(zoo, oo) is F r = Symbol('r', real=True) i = Symbol('i', imaginary=True) assert Eq(i * I, r) not in (T, F) assert Eq(infx, infnx) is F assert Eq(infnx, infnx2) not in (T, F) and infnx != infnx2 assert Eq(zoo, oo) is F assert Eq(inf / inf2, 0) is F assert Eq(inf / fin, 0) is F assert Eq(fin / inf, 0) is T assert Eq(zero / nonzero, 0) is T and ((zero / nonzero) != 0) # The commented out test below is incorrect because: assert zoo == -zoo assert Eq(zoo, -zoo) is T assert Eq(oo, -oo) is F assert Eq(inf, -inf) not in (T, F) assert Eq(fin / (fin + 1), 1) is S.false o = symbols('o', odd=True) assert Eq(o, 2 * o) is S.false p = symbols('p', positive=True) assert Eq(p / (p - 1), 1) is F
def test_Equality_rewrite_as_Add(): eq = Eq(x + y, y - x) assert eq.rewrite(Add) == 2*x assert eq.rewrite(Add, evaluate=None).args == (x, x, y, -y) assert eq.rewrite(Add, evaluate=False).args == (x, y, x, -y)
class EllipticCurve: """ Create the following Elliptic Curve over domain. `y^{2} + a_{1} x y + a_{3} y = x^{3} + a_{2} x^{2} + a_{4} x + a_{6}` The default domain is ``QQ``. If no coefficient ``a1``, ``a2``, ``a3``, it create curve as following form. `y^{2} = x^{3} + a_{4} x + a_{6}` Examples ======== References ========== [1] J. Silverman "A Friendly Introduction to Number Theory" Third Edition [2] http://mathworld.wolfram.com/EllipticDiscriminant.html [3] G. Hardy, E. Wright "An Introduction to the Theory of Numbers" Sixth Edition """ def __init__(self, a4, a6, a1=0, a2=0, a3=0, modulus=0): if modulus == 0: domain = QQ else: domain = FF(modulus) a1, a2, a3, a4, a6 = map(domain.convert, (a1, a2, a3, a4, a6)) self._domain = domain self.modulus = modulus # Calculate discriminant b2 = a1**2 + 4 * a2 b4 = 2 * a4 + a1 * a3 b6 = a3**2 + 4 * a6 b8 = a1**2 * a6 + 4 * a2 * a6 - a1 * a3 * a4 + a2 * a3**2 - a4**2 self._b2, self._b4, self._b6, self._b8 = b2, b4, b6, b8 self._discrim = -b2**2 * b8 - 8 * b4**3 - 27 * b6**2 + 9 * b2 * b4 * b6 self._a1 = a1 self._a2 = a2 self._a3 = a3 self._a4 = a4 self._a6 = a6 x, y, z = symbols('x y z') self.x, self.y, self.z = x, y, z self._eq = Eq(y**2 * z + a1 * x * y * z + a3 * y * z**2, x**3 + a2 * x**2 * z + a4 * x * z**2 + a6 * z**3) if isinstance(self._domain, FiniteField): self._rank = 0 elif isinstance(self._domain, RationalField): self._rank = None def __call__(self, x, y, z=1): return EllipticCurvePoint(x, y, z, self) def __contains__(self, point): if is_sequence(point): if len(point) == 2: z1 = 1 else: z1 = point[2] x1, y1 = point[:2] elif isinstance(point, EllipticCurvePoint): x1, y1, z1 = point.x, point.y, point.z else: raise ValueError('Invalid point.') if self.characteristic == 0 and z1 == 0: return True return self._eq.subs({self.x: x1, self.y: y1, self.z: z1}) def __repr__(self): return 'E({}): {}'.format(self._domain, self._eq) def minimal(self): """ Return minimal Weierstrass equation. Examples ======== >>> from sympy.ntheory.elliptic_curve import EllipticCurve >>> e1 = EllipticCurve(-10, -20, 0, -1, 1) >>> e1.minimal() E(QQ): Eq(y**2*z, x**3 - 13392*x*z**2 - 1080432*z**3) """ char = self.characteristic if char == 2: return self if char == 3: return EllipticCurve(self._b4 / 2, self._b6 / 4, a2=self._b2 / 4, modulus=self.modulus) c4 = self._b2**2 - 24 * self._b4 c6 = -self._b2**3 + 36 * self._b2 * self._b4 - 216 * self._b6 return EllipticCurve(-27 * c4, -54 * c6, modulus=self.modulus) def points(self): """ Return points of curve over Finite Field. Examples ======== >>> from sympy.ntheory.elliptic_curve import EllipticCurve >>> e2 = EllipticCurve(1, 1, 1, 1, 1, modulus=5) >>> e2.points() {(0, 2), (1, 4), (2, 0), (2, 2), (3, 0), (3, 1), (4, 0)} """ char = self.characteristic all_pt = set() if char >= 1: for i in range(char): congruence_eq = ((self._eq.lhs - self._eq.rhs).subs({ self.x: i, self.z: 1 })) sol = polynomial_congruence(congruence_eq, char) for num in sol: all_pt.add((i, num)) return all_pt else: raise ValueError("Infinitely many points") def points_x(self, x): "Returns points on with curve where xcoordinate = x" pt = [] if self._domain == QQ: for y in solve(self._eq.subs(self.x, x)): pt.append((x, y)) congruence_eq = ((self._eq.lhs - self._eq.rhs).subs({ self.x: x, self.z: 1 })) for y in polynomial_congruence(congruence_eq, self.characteristic): pt.append((x, y)) return pt def torsion_points(self): """ Return torsion points of curve over Rational number. Return point objects those are finite order. According to Nagell-Lutz theorem, torsion point p(x, y) x and y are integers, either y = 0 or y**2 is divisor of discriminent. According to Mazur's theorem, there are at most 15 points in torsion collection. Examples ======== >>> from sympy.ntheory.elliptic_curve import EllipticCurve >>> e2 = EllipticCurve(-43, 166) >>> sorted(e2.torsion_points()) [(-5, -16), (-5, 16), O, (3, -8), (3, 8), (11, -32), (11, 32)] """ if self.characteristic > 0: raise ValueError("No torsion point for Finite Field.") l = [EllipticCurvePoint.point_at_infinity(self)] for xx in solve(self._eq.subs({self.y: 0, self.z: 1})): if xx.is_rational: l.append(self(xx, 0)) for i in divisors(self.discriminant, generator=True): j = int(i**.5) if j**2 == i: for xx in solve(self._eq.subs({self.y: j, self.z: 1})): if not xx.is_rational: continue p = self(xx, j) if p.order() != oo: l.extend([p, -p]) return l @property def characteristic(self): """ Return domain characteristic. Examples ======== >>> from sympy.ntheory.elliptic_curve import EllipticCurve >>> e2 = EllipticCurve(-43, 166) >>> e2.characteristic 0 """ return self._domain.characteristic() @property def discriminant(self): """ Return curve discriminant. Examples ======== >>> from sympy.ntheory.elliptic_curve import EllipticCurve >>> e2 = EllipticCurve(0, 17) >>> e2.discriminant -124848 """ return int(self._discrim) @property def is_singular(self): """ Return True if curve discriminant is equal to zero. """ return self.discriminant == 0 @property def j_invariant(self): """ Return curve j-invariant. Examples ======== >>> from sympy.ntheory.elliptic_curve import EllipticCurve >>> e1 = EllipticCurve(-2, 0, 0, 1, 1) >>> e1.j_invariant 1404928/389 """ c4 = self._b2**2 - 24 * self._b4 return self._domain.to_sympy(c4**3 / self._discrim) @property def order(self): """ Number of points in Finite field. Examples ======== >>> from sympy.polys.domains import FF >>> from sympy.ntheory.elliptic_curve import EllipticCurve >>> e2 = EllipticCurve(1, 0, modulus=19) >>> e2.order 19 """ if self.characteristic == 0: raise NotImplementedError("Still not implemented") return len(list(self.points())) @property def rank(self): """ Number of independent points of infinite order. For Finite field, it must be 0. """ if self._rank is not None: return self._rank raise NotImplementedError("Still not implemented")
def checkpdesol(pde, sol, func=None, solve_for_func=True): """ Checks if the given solution satisfies the partial differential equation. pde is the partial differential equation which can be given in the form of an equation or an expression. sol is the solution for which the pde is to be checked. This can also be given in an equation or an expression form. If the function is not provided, the helper function _preprocess from deutils is used to identify the function. If a sequence of solutions is passed, the same sort of container will be used to return the result for each solution. The following methods are currently being implemented to check if the solution satisfies the PDE: 1. Directly substitute the solution in the PDE and check. If the solution hasn't been solved for f, then it will solve for f provided solve_for_func hasn't been set to False. If the solution satisfies the PDE, then a tuple (True, 0) is returned. Otherwise a tuple (False, expr) where expr is the value obtained after substituting the solution in the PDE. However if a known solution returns False, it may be due to the inability of doit() to simplify it to zero. Examples ======== >>> from sympy import Function, symbols, diff >>> from sympy.solvers.pde import checkpdesol, pdsolve >>> x, y = symbols('x y') >>> f = Function('f') >>> eq = 2*f(x,y) + 3*f(x,y).diff(x) + 4*f(x,y).diff(y) >>> sol = pdsolve(eq) >>> assert checkpdesol(eq, sol)[0] >>> eq = x*f(x,y) + f(x,y).diff(x) >>> checkpdesol(eq, sol) (False, (x*F(4*x - 3*y) - 6*F(4*x - 3*y)/25 + 4*Subs(Derivative(F(_xi_1), _xi_1), (_xi_1,), (4*x - 3*y,)))*exp(-6*x/25 - 8*y/25)) """ # Converting the pde into an equation if not isinstance(pde, Equality): pde = Eq(pde, 0) # If no function is given, try finding the function present. if func is None: try: _, func = _preprocess(pde.lhs) except ValueError: funcs = [s.atoms(AppliedUndef) for s in ( sol if is_sequence(sol, set) else [sol])] funcs = reduce(set.union, funcs, set()) if len(funcs) != 1: raise ValueError( 'must pass func arg to checkpdesol for this case.') func = funcs.pop() # If the given solution is in the form of a list or a set # then return a list or set of tuples. if is_sequence(sol, set): return type(sol)(map(lambda i: checkpdesol(pde, i, solve_for_func=solve_for_func), sol)) # Convert solution into an equation if not isinstance(sol, Equality): sol = Eq(func, sol) # Try solving for the function if solve_for_func and not (sol.lhs == func and not sol.rhs.has(func)) and not \ (sol.rhs == func and not sol.lhs.has(func)): try: solved = solve(sol, func) if not solved: raise NotImplementedError except NotImplementedError: pass else: if len(solved) == 1: result = checkpdesol(pde, Eq(func, solved[0]), order=order, solve_for_func=False) else: result = checkpdesol(pde, [Eq(func, t) for t in solved], order=order, solve_for_func=False) # The first method includes direct substitution of the solution in # the PDE and simplifying. pde = pde.lhs - pde.rhs if sol.lhs == func: s = pde.subs(func, sol.rhs).doit() elif sol.rhs == func: s = pde.subs(func, sol.lhs).doit() if s: ss = simplify(s) if ss: return False, ss else: return True, 0 else: return True, 0
def ufuncify(args, expr, language=None, backend='numpy', tempdir=None, flags=None, verbose=False, helpers=None, **kwargs): """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 SymPy 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 auxiliary 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>, <sympy_expression>, <arguments>). It is mandatory to supply an argument sequence to helper routines. kwargs : dict These kwargs will be passed to autowrap if the `f2py` or `cython` backend is used and ignored if the `numpy` backend is used. Note ---- 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 sympy.utilities.autowrap import ufuncify >>> from sympy.abc import x, y >>> import numpy as np >>> f = ufuncify((x, y), y + x**2) >>> type(f) <class 'numpy.ufunc'> >>> 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) array([ 3.]) >>> f_fortran(np.array([1, 2, 3]), np.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) # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError: Argument '_x' has incorrect type (expected numpy.ndarray, got int) >>> f_cython(np.array([1.0]), np.array([2.0])) array([ 3.]) """ if isinstance(args, 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': # maxargs is set by numpy compile-time constant NPY_MAXARGS # If a future version of numpy modifies or removes this restriction # this variable should be changed or removed maxargs = 32 helps = [] for name, expr, args in helpers: helps.append(make_routine(name, expr, args)) code_wrapper = UfuncifyCodeWrapper(C99CodeGen("ufuncify"), tempdir, flags, verbose) if not isinstance(expr, (list, tuple)): expr = [expr] if len(expr) == 0: raise ValueError('Expression iterable has zero length') if (len(expr) + len(args)) > maxargs: msg = ('Cannot create ufunc with more than {0} total arguments: ' 'got {1} in, {2} out') raise ValueError(msg.format(maxargs, len(args), len(expr))) routines = [make_routine('autofunc{}'.format(idx), exprx, args) for idx, exprx in enumerate(expr)] return code_wrapper.wrap_code(routines, helpers=helps) else: # Dummies are used for all added expressions to prevent name clashes # within the original expression. y = IndexedBase(Dummy('y')) m = Dummy('m', integer=True) i = Idx(Dummy('i', integer=True), m) f_dummy = Dummy('f') f = implemented_function('%s_%d' % (f_dummy.name, f_dummy.dummy_index), 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, args, flags, verbose, helpers, **kwargs)