import itertools as it from sympy.core.expr import unchanged from sympy.core.function import Function from sympy.core.numbers import I, oo, Rational from sympy.core.power import Pow from sympy.core.singleton import S from sympy.core.symbol import Symbol from sympy.external import import_module from sympy.functions.elementary.exponential import log from sympy.functions.elementary.integers import floor, ceiling from sympy.functions.elementary.miscellaneous import (sqrt, cbrt, root, Min, Max, real_root, Rem) from sympy.functions.elementary.trigonometric import cos, sin from sympy.functions.special.delta_functions import Heaviside from sympy.utilities.lambdify import lambdify from sympy.testing.pytest import raises, skip, ignore_warnings def test_Min(): from sympy.abc import x, y, z n = Symbol('n', negative=True) n_ = Symbol('n_', negative=True) nn = Symbol('nn', nonnegative=True) nn_ = Symbol('nn_', nonnegative=True) p = Symbol('p', positive=True) p_ = Symbol('p_', positive=True) np = Symbol('np', nonpositive=True) np_ = Symbol('np_', nonpositive=True) r = Symbol('r', real=True) assert Min(5, 4) == 4 assert Min(-oo, -oo) is -oo assert Min(-oo, n) is -oo assert Min(n, -oo) is -oo assert Min(-oo, np) is -oo assert Min(np, -oo) is -oo assert Min(-oo, 0) is -oo assert Min(0, -oo) is -oo assert Min(-oo, nn) is -oo assert Min(nn, -oo) is -oo assert Min(-oo, p) is -oo assert Min(p, -oo) is -oo assert Min(-oo, oo) is -oo assert Min(oo, -oo) is -oo assert Min(n, n) == n assert unchanged(Min, n, np) assert Min(np, n) == Min(n, np) assert Min(n, 0) == n assert Min(0, n) == n assert Min(n, nn) == n assert Min(nn, n) == n assert Min(n, p) == n assert Min(p, n) == n assert Min(n, oo) == n assert Min(oo, n) == n assert Min(np, np) == np assert Min(np, 0) == np assert Min(0, np) == np assert Min(np, nn) == np assert Min(nn, np) == np assert Min(np, p) == np assert Min(p, np) == np assert Min(np, oo) == np assert Min(oo, np) == np assert Min(0, 0) == 0 assert Min(0, nn) == 0 assert Min(nn, 0) == 0 assert Min(0, p) == 0 assert Min(p, 0) == 0 assert Min(0, oo) == 0 assert Min(oo, 0) == 0 assert Min(nn, nn) == nn assert unchanged(Min, nn, p) assert Min(p, nn) == Min(nn, p) assert Min(nn, oo) == nn assert Min(oo, nn) == nn assert Min(p, p) == p assert Min(p, oo) == p assert Min(oo, p) == p assert Min(oo, oo) is oo assert Min(n, n_).func is Min assert Min(nn, nn_).func is Min assert Min(np, np_).func is Min assert Min(p, p_).func is Min # lists assert Min() is S.Infinity assert Min(x) == x assert Min(x, y) == Min(y, x) assert Min(x, y, z) == Min(z, y, x) assert Min(x, Min(y, z)) == Min(z, y, x) assert Min(x, Max(y, -oo)) == Min(x, y) assert Min(p, oo, n, p, p, p_) == n assert Min(p_, n_, p) == n_ assert Min(n, oo, -7, p, p, 2) == Min(n, -7) assert Min(2, x, p, n, oo, n_, p, 2, -2, -2) == Min(-2, x, n, n_) assert Min(0, x, 1, y) == Min(0, x, y) assert Min(1000, 100, -100, x, p, n) == Min(n, x, -100) assert unchanged(Min, sin(x), cos(x)) assert Min(sin(x), cos(x)) == Min(cos(x), sin(x)) assert Min(cos(x), sin(x)).subs(x, 1) == cos(1) assert Min(cos(x), sin(x)).subs(x, S.Half) == sin(S.Half) raises(ValueError, lambda: Min(cos(x), sin(x)).subs(x, I)) raises(ValueError, lambda: Min(I)) raises(ValueError, lambda: Min(I, x)) raises(ValueError, lambda: Min(S.ComplexInfinity, x)) assert Min(1, x).diff(x) == Heaviside(1 - x) assert Min(x, 1).diff(x) == Heaviside(1 - x) assert Min(0, -x, 1 - 2*x).diff(x) == -Heaviside(x + Min(0, -2*x + 1)) \ - 2*Heaviside(2*x + Min(0, -x) - 1) # issue 7619 f = Function('f') assert Min(1, 2*Min(f(1), 2)) # doesn't fail # issue 7233 e = Min(0, x) assert e.n().args == (0, x) # issue 8643 m = Min(n, p_, n_, r) assert m.is_positive is False assert m.is_nonnegative is False assert m.is_negative is True m = Min(p, p_) assert m.is_positive is True assert m.is_nonnegative is True assert m.is_negative is False m = Min(p, nn_, p_) assert m.is_positive is None assert m.is_nonnegative is True assert m.is_negative is False m = Min(nn, p, r) assert m.is_positive is None assert m.is_nonnegative is None assert m.is_negative is None def test_Max(): from sympy.abc import x, y, z n = Symbol('n', negative=True) n_ = Symbol('n_', negative=True) nn = Symbol('nn', nonnegative=True) p = Symbol('p', positive=True) p_ = Symbol('p_', positive=True) r = Symbol('r', real=True) assert Max(5, 4) == 5 # lists assert Max() is S.NegativeInfinity assert Max(x) == x assert Max(x, y) == Max(y, x) assert Max(x, y, z) == Max(z, y, x) assert Max(x, Max(y, z)) == Max(z, y, x) assert Max(x, Min(y, oo)) == Max(x, y) assert Max(n, -oo, n_, p, 2) == Max(p, 2) assert Max(n, -oo, n_, p) == p assert Max(2, x, p, n, -oo, S.NegativeInfinity, n_, p, 2) == Max(2, x, p) assert Max(0, x, 1, y) == Max(1, x, y) assert Max(r, r + 1, r - 1) == 1 + r assert Max(1000, 100, -100, x, p, n) == Max(p, x, 1000) assert Max(cos(x), sin(x)) == Max(sin(x), cos(x)) assert Max(cos(x), sin(x)).subs(x, 1) == sin(1) assert Max(cos(x), sin(x)).subs(x, S.Half) == cos(S.Half) raises(ValueError, lambda: Max(cos(x), sin(x)).subs(x, I)) raises(ValueError, lambda: Max(I)) raises(ValueError, lambda: Max(I, x)) raises(ValueError, lambda: Max(S.ComplexInfinity, 1)) assert Max(n, -oo, n_, p, 2) == Max(p, 2) assert Max(n, -oo, n_, p, 1000) == Max(p, 1000) assert Max(1, x).diff(x) == Heaviside(x - 1) assert Max(x, 1).diff(x) == Heaviside(x - 1) assert Max(x**2, 1 + x, 1).diff(x) == \ 2*x*Heaviside(x**2 - Max(1, x + 1)) \ + Heaviside(x - Max(1, x**2) + 1) e = Max(0, x) assert e.n().args == (0, x) # issue 8643 m = Max(p, p_, n, r) assert m.is_positive is True assert m.is_nonnegative is True assert m.is_negative is False m = Max(n, n_) assert m.is_positive is False assert m.is_nonnegative is False assert m.is_negative is True m = Max(n, n_, r) assert m.is_positive is None assert m.is_nonnegative is None assert m.is_negative is None m = Max(n, nn, r) assert m.is_positive is None assert m.is_nonnegative is True assert m.is_negative is False def test_minmax_assumptions(): r = Symbol('r', real=True) a = Symbol('a', real=True, algebraic=True) t = Symbol('t', real=True, transcendental=True) q = Symbol('q', rational=True) p = Symbol('p', irrational=True) n = Symbol('n', rational=True, integer=False) i = Symbol('i', integer=True) o = Symbol('o', odd=True) e = Symbol('e', even=True) k = Symbol('k', prime=True) reals = [r, a, t, q, p, n, i, o, e, k] for ext in (Max, Min): for x, y in it.product(reals, repeat=2): # Must be real assert ext(x, y).is_real # Algebraic? if x.is_algebraic and y.is_algebraic: assert ext(x, y).is_algebraic elif x.is_transcendental and y.is_transcendental: assert ext(x, y).is_transcendental else: assert ext(x, y).is_algebraic is None # Rational? if x.is_rational and y.is_rational: assert ext(x, y).is_rational elif x.is_irrational and y.is_irrational: assert ext(x, y).is_irrational else: assert ext(x, y).is_rational is None # Integer? if x.is_integer and y.is_integer: assert ext(x, y).is_integer elif x.is_noninteger and y.is_noninteger: assert ext(x, y).is_noninteger else: assert ext(x, y).is_integer is None # Odd? if x.is_odd and y.is_odd: assert ext(x, y).is_odd elif x.is_odd is False and y.is_odd is False: assert ext(x, y).is_odd is False else: assert ext(x, y).is_odd is None # Even? if x.is_even and y.is_even: assert ext(x, y).is_even elif x.is_even is False and y.is_even is False: assert ext(x, y).is_even is False else: assert ext(x, y).is_even is None # Prime? if x.is_prime and y.is_prime: assert ext(x, y).is_prime elif x.is_prime is False and y.is_prime is False: assert ext(x, y).is_prime is False else: assert ext(x, y).is_prime is None def test_issue_8413(): x = Symbol('x', real=True) # we can't evaluate in general because non-reals are not # comparable: Min(floor(3.2 + I), 3.2 + I) -> ValueError assert Min(floor(x), x) == floor(x) assert Min(ceiling(x), x) == x assert Max(floor(x), x) == x assert Max(ceiling(x), x) == ceiling(x) def test_root(): from sympy.abc import x n = Symbol('n', integer=True) k = Symbol('k', integer=True) assert root(2, 2) == sqrt(2) assert root(2, 1) == 2 assert root(2, 3) == 2**Rational(1, 3) assert root(2, 3) == cbrt(2) assert root(2, -5) == 2**Rational(4, 5)/2 assert root(-2, 1) == -2 assert root(-2, 2) == sqrt(2)*I assert root(-2, 1) == -2 assert root(x, 2) == sqrt(x) assert root(x, 1) == x assert root(x, 3) == x**Rational(1, 3) assert root(x, 3) == cbrt(x) assert root(x, -5) == x**Rational(-1, 5) assert root(x, n) == x**(1/n) assert root(x, -n) == x**(-1/n) assert root(x, n, k) == (-1)**(2*k/n)*x**(1/n) def test_real_root(): assert real_root(-8, 3) == -2 assert real_root(-16, 4) == root(-16, 4) r = root(-7, 4) assert real_root(r) == r r1 = root(-1, 3) r2 = r1**2 r3 = root(-1, 4) assert real_root(r1 + r2 + r3) == -1 + r2 + r3 assert real_root(root(-2, 3)) == -root(2, 3) assert real_root(-8., 3) == -2.0 x = Symbol('x') n = Symbol('n') g = real_root(x, n) assert g.subs({"x": -8, "n": 3}) == -2 assert g.subs({"x": 8, "n": 3}) == 2 # give principle root if there is no real root -- if this is not desired # then maybe a Root class is needed to raise an error instead assert g.subs({"x": I, "n": 3}) == cbrt(I) assert g.subs({"x": -8, "n": 2}) == sqrt(-8) assert g.subs({"x": I, "n": 2}) == sqrt(I) def test_issue_11463(): numpy = import_module('numpy') if not numpy: skip("numpy not installed.") x = Symbol('x') f = lambdify(x, real_root((log(x/(x-2))), 3), 'numpy') # numpy.select evaluates all options before considering conditions, # so it raises a warning about root of negative number which does # not affect the outcome. This warning is suppressed here with ignore_warnings(RuntimeWarning): assert f(numpy.array(-1)) < -1 def test_rewrite_MaxMin_as_Heaviside(): from sympy.abc import x assert Max(0, x).rewrite(Heaviside) == x*Heaviside(x) assert Max(3, x).rewrite(Heaviside) == x*Heaviside(x - 3) + \ 3*Heaviside(-x + 3) assert Max(0, x+2, 2*x).rewrite(Heaviside) == \ 2*x*Heaviside(2*x)*Heaviside(x - 2) + \ (x + 2)*Heaviside(-x + 2)*Heaviside(x + 2) assert Min(0, x).rewrite(Heaviside) == x*Heaviside(-x) assert Min(3, x).rewrite(Heaviside) == x*Heaviside(-x + 3) + \ 3*Heaviside(x - 3) assert Min(x, -x, -2).rewrite(Heaviside) == \ x*Heaviside(-2*x)*Heaviside(-x - 2) - \ x*Heaviside(2*x)*Heaviside(x - 2) \ - 2*Heaviside(-x + 2)*Heaviside(x + 2) def test_rewrite_MaxMin_as_Piecewise(): from sympy.core.symbol import symbols from sympy.functions.elementary.piecewise import Piecewise x, y, z, a, b = symbols('x y z a b', real=True) vx, vy, va = symbols('vx vy va') assert Max(a, b).rewrite(Piecewise) == Piecewise((a, a >= b), (b, True)) assert Max(x, y, z).rewrite(Piecewise) == Piecewise((x, (x >= y) & (x >= z)), (y, y >= z), (z, True)) assert Max(x, y, a, b).rewrite(Piecewise) == Piecewise((a, (a >= b) & (a >= x) & (a >= y)), (b, (b >= x) & (b >= y)), (x, x >= y), (y, True)) assert Min(a, b).rewrite(Piecewise) == Piecewise((a, a <= b), (b, True)) assert Min(x, y, z).rewrite(Piecewise) == Piecewise((x, (x <= y) & (x <= z)), (y, y <= z), (z, True)) assert Min(x, y, a, b).rewrite(Piecewise) == Piecewise((a, (a <= b) & (a <= x) & (a <= y)), (b, (b <= x) & (b <= y)), (x, x <= y), (y, True)) # Piecewise rewriting of Min/Max does also takes place for not explicitly real arguments assert Max(vx, vy).rewrite(Piecewise) == Piecewise((vx, vx >= vy), (vy, True)) assert Min(va, vx, vy).rewrite(Piecewise) == Piecewise((va, (va <= vx) & (va <= vy)), (vx, vx <= vy), (vy, True)) def test_issue_11099(): from sympy.abc import x, y # some fixed value tests fixed_test_data = {x: -2, y: 3} assert Min(x, y).evalf(subs=fixed_test_data) == \ Min(x, y).subs(fixed_test_data).evalf() assert Max(x, y).evalf(subs=fixed_test_data) == \ Max(x, y).subs(fixed_test_data).evalf() # randomly generate some test data from sympy.core.random import randint for i in range(20): random_test_data = {x: randint(-100, 100), y: randint(-100, 100)} assert Min(x, y).evalf(subs=random_test_data) == \ Min(x, y).subs(random_test_data).evalf() assert Max(x, y).evalf(subs=random_test_data) == \ Max(x, y).subs(random_test_data).evalf() def test_issue_12638(): from sympy.abc import a, b, c assert Min(a, b, c, Max(a, b)) == Min(a, b, c) assert Min(a, b, Max(a, b, c)) == Min(a, b) assert Min(a, b, Max(a, c)) == Min(a, b) def test_issue_21399(): from sympy.abc import a, b, c assert Max(Min(a, b), Min(a, b, c)) == Min(a, b) def test_instantiation_evaluation(): from sympy.abc import v, w, x, y, z assert Min(1, Max(2, x)) == 1 assert Max(3, Min(2, x)) == 3 assert Min(Max(x, y), Max(x, z)) == Max(x, Min(y, z)) assert set(Min(Max(w, x), Max(y, z)).args) == { Max(w, x), Max(y, z)} assert Min(Max(x, y), Max(x, z), w) == Min( w, Max(x, Min(y, z))) A, B = Min, Max for i in range(2): assert A(x, B(x, y)) == x assert A(x, B(y, A(x, w, z))) == A(x, B(y, A(w, z))) A, B = B, A assert Min(w, Max(x, y), Max(v, x, z)) == Min( w, Max(x, Min(y, Max(v, z)))) def test_rewrite_as_Abs(): from itertools import permutations from sympy.functions.elementary.complexes import Abs from sympy.abc import x, y, z, w def test(e): free = e.free_symbols a = e.rewrite(Abs) assert not a.has(Min, Max) for i in permutations(range(len(free))): reps = dict(zip(free, i)) assert a.xreplace(reps) == e.xreplace(reps) test(Min(x, y)) test(Max(x, y)) test(Min(x, y, z)) test(Min(Max(w, x), Max(y, z))) def test_issue_14000(): assert isinstance(sqrt(4, evaluate=False), Pow) == True assert isinstance(cbrt(3.5, evaluate=False), Pow) == True assert isinstance(root(16, 4, evaluate=False), Pow) == True assert sqrt(4, evaluate=False) == Pow(4, S.Half, evaluate=False) assert cbrt(3.5, evaluate=False) == Pow(3.5, Rational(1, 3), evaluate=False) assert root(4, 2, evaluate=False) == Pow(4, S.Half, evaluate=False) assert root(16, 4, 2, evaluate=False).has(Pow) == True assert real_root(-8, 3, evaluate=False).has(Pow) == True def test_issue_6899(): from sympy.core.function import Lambda x = Symbol('x') eqn = Lambda(x, x) assert eqn.func(*eqn.args) == eqn def test_Rem(): from sympy.abc import x, y assert Rem(5, 3) == 2 assert Rem(-5, 3) == -2 assert Rem(5, -3) == 2 assert Rem(-5, -3) == -2 assert Rem(x**3, y) == Rem(x**3, y) assert Rem(Rem(-5, 3) + 3, 3) == 1 def test_minmax_no_evaluate(): from sympy import evaluate p = Symbol('p', positive=True) assert Max(1, 3) == 3 assert Max(1, 3).args == () assert Max(0, p) == p assert Max(0, p).args == () assert Min(0, p) == 0 assert Min(0, p).args == () assert Max(1, 3, evaluate=False) != 3 assert Max(1, 3, evaluate=False).args == (1, 3) assert Max(0, p, evaluate=False) != p assert Max(0, p, evaluate=False).args == (0, p) assert Min(0, p, evaluate=False) != 0 assert Min(0, p, evaluate=False).args == (0, p) with evaluate(False): assert Max(1, 3) != 3 assert Max(1, 3).args == (1, 3) assert Max(0, p) != p assert Max(0, p).args == (0, p) assert Min(0, p) != 0 assert Min(0, p).args == (0, p)