test_util.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. from sympy.core.numbers import (E, I, Rational, oo, pi)
  2. from sympy.core.singleton import S
  3. from sympy.core.symbol import (Symbol, symbols)
  4. from sympy.functions.elementary.complexes import (Abs, re)
  5. from sympy.functions.elementary.exponential import (exp, log)
  6. from sympy.functions.elementary.miscellaneous import sqrt
  7. from sympy.functions.elementary.piecewise import Piecewise
  8. from sympy.functions.elementary.trigonometric import (cos, cot, csc, sec, sin, tan)
  9. from sympy.functions.special.error_functions import expint
  10. from sympy.matrices.expressions.matexpr import MatrixSymbol
  11. from sympy.simplify.simplify import simplify
  12. from sympy.calculus.util import (function_range, continuous_domain, not_empty_in,
  13. periodicity, lcim, is_convex,
  14. stationary_points, minimum, maximum)
  15. from sympy.sets.sets import (Interval, FiniteSet, Complement, Union)
  16. from sympy.testing.pytest import raises, _both_exp_pow
  17. from sympy.abc import x
  18. a = Symbol('a', real=True)
  19. def test_function_range():
  20. x, y, a, b = symbols('x y a b')
  21. assert function_range(sin(x), x, Interval(-pi/2, pi/2)
  22. ) == Interval(-1, 1)
  23. assert function_range(sin(x), x, Interval(0, pi)
  24. ) == Interval(0, 1)
  25. assert function_range(tan(x), x, Interval(0, pi)
  26. ) == Interval(-oo, oo)
  27. assert function_range(tan(x), x, Interval(pi/2, pi)
  28. ) == Interval(-oo, 0)
  29. assert function_range((x + 3)/(x - 2), x, Interval(-5, 5)
  30. ) == Union(Interval(-oo, Rational(2, 7)), Interval(Rational(8, 3), oo))
  31. assert function_range(1/(x**2), x, Interval(-1, 1)
  32. ) == Interval(1, oo)
  33. assert function_range(exp(x), x, Interval(-1, 1)
  34. ) == Interval(exp(-1), exp(1))
  35. assert function_range(log(x) - x, x, S.Reals
  36. ) == Interval(-oo, -1)
  37. assert function_range(sqrt(3*x - 1), x, Interval(0, 2)
  38. ) == Interval(0, sqrt(5))
  39. assert function_range(x*(x - 1) - (x**2 - x), x, S.Reals
  40. ) == FiniteSet(0)
  41. assert function_range(x*(x - 1) - (x**2 - x) + y, x, S.Reals
  42. ) == FiniteSet(y)
  43. assert function_range(sin(x), x, Union(Interval(-5, -3), FiniteSet(4))
  44. ) == Union(Interval(-sin(3), 1), FiniteSet(sin(4)))
  45. assert function_range(cos(x), x, Interval(-oo, -4)
  46. ) == Interval(-1, 1)
  47. assert function_range(cos(x), x, S.EmptySet) == S.EmptySet
  48. assert function_range(x/sqrt(x**2+1), x, S.Reals) == Interval.open(-1,1)
  49. raises(NotImplementedError, lambda : function_range(
  50. exp(x)*(sin(x) - cos(x))/2 - x, x, S.Reals))
  51. raises(NotImplementedError, lambda : function_range(
  52. sin(x) + x, x, S.Reals)) # issue 13273
  53. raises(NotImplementedError, lambda : function_range(
  54. log(x), x, S.Integers))
  55. raises(NotImplementedError, lambda : function_range(
  56. sin(x)/2, x, S.Naturals))
  57. def test_continuous_domain():
  58. x = Symbol('x')
  59. assert continuous_domain(sin(x), x, Interval(0, 2*pi)) == Interval(0, 2*pi)
  60. assert continuous_domain(tan(x), x, Interval(0, 2*pi)) == \
  61. Union(Interval(0, pi/2, False, True), Interval(pi/2, pi*Rational(3, 2), True, True),
  62. Interval(pi*Rational(3, 2), 2*pi, True, False))
  63. assert continuous_domain((x - 1)/((x - 1)**2), x, S.Reals) == \
  64. Union(Interval(-oo, 1, True, True), Interval(1, oo, True, True))
  65. assert continuous_domain(log(x) + log(4*x - 1), x, S.Reals) == \
  66. Interval(Rational(1, 4), oo, True, True)
  67. assert continuous_domain(1/sqrt(x - 3), x, S.Reals) == Interval(3, oo, True, True)
  68. assert continuous_domain(1/x - 2, x, S.Reals) == \
  69. Union(Interval.open(-oo, 0), Interval.open(0, oo))
  70. assert continuous_domain(1/(x**2 - 4) + 2, x, S.Reals) == \
  71. Union(Interval.open(-oo, -2), Interval.open(-2, 2), Interval.open(2, oo))
  72. domain = continuous_domain(log(tan(x)**2 + 1), x, S.Reals)
  73. assert not domain.contains(3*pi/2)
  74. assert domain.contains(5)
  75. d = Symbol('d', even=True, zero=False)
  76. assert continuous_domain(x**(1/d), x, S.Reals) == Interval(0, oo)
  77. def test_not_empty_in():
  78. assert not_empty_in(FiniteSet(x, 2*x).intersect(Interval(1, 2, True, False)), x) == \
  79. Interval(S.Half, 2, True, False)
  80. assert not_empty_in(FiniteSet(x, x**2).intersect(Interval(1, 2)), x) == \
  81. Union(Interval(-sqrt(2), -1), Interval(1, 2))
  82. assert not_empty_in(FiniteSet(x**2 + x, x).intersect(Interval(2, 4)), x) == \
  83. Union(Interval(-sqrt(17)/2 - S.Half, -2),
  84. Interval(1, Rational(-1, 2) + sqrt(17)/2), Interval(2, 4))
  85. assert not_empty_in(FiniteSet(x/(x - 1)).intersect(S.Reals), x) == \
  86. Complement(S.Reals, FiniteSet(1))
  87. assert not_empty_in(FiniteSet(a/(a - 1)).intersect(S.Reals), a) == \
  88. Complement(S.Reals, FiniteSet(1))
  89. assert not_empty_in(FiniteSet((x**2 - 3*x + 2)/(x - 1)).intersect(S.Reals), x) == \
  90. Complement(S.Reals, FiniteSet(1))
  91. assert not_empty_in(FiniteSet(3, 4, x/(x - 1)).intersect(Interval(2, 3)), x) == \
  92. Interval(-oo, oo)
  93. assert not_empty_in(FiniteSet(4, x/(x - 1)).intersect(Interval(2, 3)), x) == \
  94. Interval(S(3)/2, 2)
  95. assert not_empty_in(FiniteSet(x/(x**2 - 1)).intersect(S.Reals), x) == \
  96. Complement(S.Reals, FiniteSet(-1, 1))
  97. assert not_empty_in(FiniteSet(x, x**2).intersect(Union(Interval(1, 3, True, True),
  98. Interval(4, 5))), x) == \
  99. Union(Interval(-sqrt(5), -2), Interval(-sqrt(3), -1, True, True),
  100. Interval(1, 3, True, True), Interval(4, 5))
  101. assert not_empty_in(FiniteSet(1).intersect(Interval(3, 4)), x) == S.EmptySet
  102. assert not_empty_in(FiniteSet(x**2/(x + 2)).intersect(Interval(1, oo)), x) == \
  103. Union(Interval(-2, -1, True, False), Interval(2, oo))
  104. raises(ValueError, lambda: not_empty_in(x))
  105. raises(ValueError, lambda: not_empty_in(Interval(0, 1), x))
  106. raises(NotImplementedError,
  107. lambda: not_empty_in(FiniteSet(x).intersect(S.Reals), x, a))
  108. @_both_exp_pow
  109. def test_periodicity():
  110. x = Symbol('x')
  111. y = Symbol('y')
  112. z = Symbol('z', real=True)
  113. assert periodicity(sin(2*x), x) == pi
  114. assert periodicity((-2)*tan(4*x), x) == pi/4
  115. assert periodicity(sin(x)**2, x) == 2*pi
  116. assert periodicity(3**tan(3*x), x) == pi/3
  117. assert periodicity(tan(x)*cos(x), x) == 2*pi
  118. assert periodicity(sin(x)**(tan(x)), x) == 2*pi
  119. assert periodicity(tan(x)*sec(x), x) == 2*pi
  120. assert periodicity(sin(2*x)*cos(2*x) - y, x) == pi/2
  121. assert periodicity(tan(x) + cot(x), x) == pi
  122. assert periodicity(sin(x) - cos(2*x), x) == 2*pi
  123. assert periodicity(sin(x) - 1, x) == 2*pi
  124. assert periodicity(sin(4*x) + sin(x)*cos(x), x) == pi
  125. assert periodicity(exp(sin(x)), x) == 2*pi
  126. assert periodicity(log(cot(2*x)) - sin(cos(2*x)), x) == pi
  127. assert periodicity(sin(2*x)*exp(tan(x) - csc(2*x)), x) == pi
  128. assert periodicity(cos(sec(x) - csc(2*x)), x) == 2*pi
  129. assert periodicity(tan(sin(2*x)), x) == pi
  130. assert periodicity(2*tan(x)**2, x) == pi
  131. assert periodicity(sin(x%4), x) == 4
  132. assert periodicity(sin(x)%4, x) == 2*pi
  133. assert periodicity(tan((3*x-2)%4), x) == Rational(4, 3)
  134. assert periodicity((sqrt(2)*(x+1)+x) % 3, x) == 3 / (sqrt(2)+1)
  135. assert periodicity((x**2+1) % x, x) is None
  136. assert periodicity(sin(re(x)), x) == 2*pi
  137. assert periodicity(sin(x)**2 + cos(x)**2, x) is S.Zero
  138. assert periodicity(tan(x), y) is S.Zero
  139. assert periodicity(sin(x) + I*cos(x), x) == 2*pi
  140. assert periodicity(x - sin(2*y), y) == pi
  141. assert periodicity(exp(x), x) is None
  142. assert periodicity(exp(I*x), x) == 2*pi
  143. assert periodicity(exp(I*z), z) == 2*pi
  144. assert periodicity(exp(z), z) is None
  145. assert periodicity(exp(log(sin(z) + I*cos(2*z)), evaluate=False), z) == 2*pi
  146. assert periodicity(exp(log(sin(2*z) + I*cos(z)), evaluate=False), z) == 2*pi
  147. assert periodicity(exp(sin(z)), z) == 2*pi
  148. assert periodicity(exp(2*I*z), z) == pi
  149. assert periodicity(exp(z + I*sin(z)), z) is None
  150. assert periodicity(exp(cos(z/2) + sin(z)), z) == 4*pi
  151. assert periodicity(log(x), x) is None
  152. assert periodicity(exp(x)**sin(x), x) is None
  153. assert periodicity(sin(x)**y, y) is None
  154. assert periodicity(Abs(sin(Abs(sin(x)))), x) == pi
  155. assert all(periodicity(Abs(f(x)), x) == pi for f in (
  156. cos, sin, sec, csc, tan, cot))
  157. assert periodicity(Abs(sin(tan(x))), x) == pi
  158. assert periodicity(Abs(sin(sin(x) + tan(x))), x) == 2*pi
  159. assert periodicity(sin(x) > S.Half, x) == 2*pi
  160. assert periodicity(x > 2, x) is None
  161. assert periodicity(x**3 - x**2 + 1, x) is None
  162. assert periodicity(Abs(x), x) is None
  163. assert periodicity(Abs(x**2 - 1), x) is None
  164. assert periodicity((x**2 + 4)%2, x) is None
  165. assert periodicity((E**x)%3, x) is None
  166. assert periodicity(sin(expint(1, x))/expint(1, x), x) is None
  167. # returning `None` for any Piecewise
  168. p = Piecewise((0, x < -1), (x**2, x <= 1), (log(x), True))
  169. assert periodicity(p, x) is None
  170. m = MatrixSymbol('m', 3, 3)
  171. raises(NotImplementedError, lambda: periodicity(sin(m), m))
  172. raises(NotImplementedError, lambda: periodicity(sin(m[0, 0]), m))
  173. raises(NotImplementedError, lambda: periodicity(sin(m), m[0, 0]))
  174. raises(NotImplementedError, lambda: periodicity(sin(m[0, 0]), m[0, 0]))
  175. def test_periodicity_check():
  176. x = Symbol('x')
  177. y = Symbol('y')
  178. assert periodicity(tan(x), x, check=True) == pi
  179. assert periodicity(sin(x) + cos(x), x, check=True) == 2*pi
  180. assert periodicity(sec(x), x) == 2*pi
  181. assert periodicity(sin(x*y), x) == 2*pi/abs(y)
  182. assert periodicity(Abs(sec(sec(x))), x) == pi
  183. def test_lcim():
  184. assert lcim([S.Half, S(2), S(3)]) == 6
  185. assert lcim([pi/2, pi/4, pi]) == pi
  186. assert lcim([2*pi, pi/2]) == 2*pi
  187. assert lcim([S.One, 2*pi]) is None
  188. assert lcim([S(2) + 2*E, E/3 + Rational(1, 3), S.One + E]) == S(2) + 2*E
  189. def test_is_convex():
  190. assert is_convex(1/x, x, domain=Interval.open(0, oo)) == True
  191. assert is_convex(1/x, x, domain=Interval(-oo, 0)) == False
  192. assert is_convex(x**2, x, domain=Interval(0, oo)) == True
  193. assert is_convex(1/x**3, x, domain=Interval.Lopen(0, oo)) == True
  194. assert is_convex(-1/x**3, x, domain=Interval.Ropen(-oo, 0)) == True
  195. assert is_convex(log(x), x) == False
  196. raises(NotImplementedError, lambda: is_convex(log(x), x, a))
  197. def test_stationary_points():
  198. x, y = symbols('x y')
  199. assert stationary_points(sin(x), x, Interval(-pi/2, pi/2)
  200. ) == {-pi/2, pi/2}
  201. assert stationary_points(sin(x), x, Interval.Ropen(0, pi/4)
  202. ) is S.EmptySet
  203. assert stationary_points(tan(x), x,
  204. ) is S.EmptySet
  205. assert stationary_points(sin(x)*cos(x), x, Interval(0, pi)
  206. ) == {pi/4, pi*Rational(3, 4)}
  207. assert stationary_points(sec(x), x, Interval(0, pi)
  208. ) == {0, pi}
  209. assert stationary_points((x+3)*(x-2), x
  210. ) == FiniteSet(Rational(-1, 2))
  211. assert stationary_points((x + 3)/(x - 2), x, Interval(-5, 5)
  212. ) is S.EmptySet
  213. assert stationary_points((x**2+3)/(x-2), x
  214. ) == {2 - sqrt(7), 2 + sqrt(7)}
  215. assert stationary_points((x**2+3)/(x-2), x, Interval(0, 5)
  216. ) == {2 + sqrt(7)}
  217. assert stationary_points(x**4 + x**3 - 5*x**2, x, S.Reals
  218. ) == FiniteSet(-2, 0, Rational(5, 4))
  219. assert stationary_points(exp(x), x
  220. ) is S.EmptySet
  221. assert stationary_points(log(x) - x, x, S.Reals
  222. ) == {1}
  223. assert stationary_points(cos(x), x, Union(Interval(0, 5), Interval(-6, -3))
  224. ) == {0, -pi, pi}
  225. assert stationary_points(y, x, S.Reals
  226. ) == S.Reals
  227. assert stationary_points(y, x, S.EmptySet) == S.EmptySet
  228. def test_maximum():
  229. x, y = symbols('x y')
  230. assert maximum(sin(x), x) is S.One
  231. assert maximum(sin(x), x, Interval(0, 1)) == sin(1)
  232. assert maximum(tan(x), x) is oo
  233. assert maximum(tan(x), x, Interval(-pi/4, pi/4)) is S.One
  234. assert maximum(sin(x)*cos(x), x, S.Reals) == S.Half
  235. assert simplify(maximum(sin(x)*cos(x), x, Interval(pi*Rational(3, 8), pi*Rational(5, 8)))
  236. ) == sqrt(2)/4
  237. assert maximum((x+3)*(x-2), x) is oo
  238. assert maximum((x+3)*(x-2), x, Interval(-5, 0)) == S(14)
  239. assert maximum((x+3)/(x-2), x, Interval(-5, 0)) == Rational(2, 7)
  240. assert simplify(maximum(-x**4-x**3+x**2+10, x)
  241. ) == 41*sqrt(41)/512 + Rational(5419, 512)
  242. assert maximum(exp(x), x, Interval(-oo, 2)) == exp(2)
  243. assert maximum(log(x) - x, x, S.Reals) is S.NegativeOne
  244. assert maximum(cos(x), x, Union(Interval(0, 5), Interval(-6, -3))
  245. ) is S.One
  246. assert maximum(cos(x)-sin(x), x, S.Reals) == sqrt(2)
  247. assert maximum(y, x, S.Reals) == y
  248. assert maximum(abs(a**3 + a), a, Interval(0, 2)) == 10
  249. assert maximum(abs(60*a**3 + 24*a), a, Interval(0, 2)) == 528
  250. assert maximum(abs(12*a*(5*a**2 + 2)), a, Interval(0, 2)) == 528
  251. assert maximum(x/sqrt(x**2+1), x, S.Reals) == 1
  252. raises(ValueError, lambda : maximum(sin(x), x, S.EmptySet))
  253. raises(ValueError, lambda : maximum(log(cos(x)), x, S.EmptySet))
  254. raises(ValueError, lambda : maximum(1/(x**2 + y**2 + 1), x, S.EmptySet))
  255. raises(ValueError, lambda : maximum(sin(x), sin(x)))
  256. raises(ValueError, lambda : maximum(sin(x), x*y, S.EmptySet))
  257. raises(ValueError, lambda : maximum(sin(x), S.One))
  258. def test_minimum():
  259. x, y = symbols('x y')
  260. assert minimum(sin(x), x) is S.NegativeOne
  261. assert minimum(sin(x), x, Interval(1, 4)) == sin(4)
  262. assert minimum(tan(x), x) is -oo
  263. assert minimum(tan(x), x, Interval(-pi/4, pi/4)) is S.NegativeOne
  264. assert minimum(sin(x)*cos(x), x, S.Reals) == Rational(-1, 2)
  265. assert simplify(minimum(sin(x)*cos(x), x, Interval(pi*Rational(3, 8), pi*Rational(5, 8)))
  266. ) == -sqrt(2)/4
  267. assert minimum((x+3)*(x-2), x) == Rational(-25, 4)
  268. assert minimum((x+3)/(x-2), x, Interval(-5, 0)) == Rational(-3, 2)
  269. assert minimum(x**4-x**3+x**2+10, x) == S(10)
  270. assert minimum(exp(x), x, Interval(-2, oo)) == exp(-2)
  271. assert minimum(log(x) - x, x, S.Reals) is -oo
  272. assert minimum(cos(x), x, Union(Interval(0, 5), Interval(-6, -3))
  273. ) is S.NegativeOne
  274. assert minimum(cos(x)-sin(x), x, S.Reals) == -sqrt(2)
  275. assert minimum(y, x, S.Reals) == y
  276. assert minimum(x/sqrt(x**2+1), x, S.Reals) == -1
  277. raises(ValueError, lambda : minimum(sin(x), x, S.EmptySet))
  278. raises(ValueError, lambda : minimum(log(cos(x)), x, S.EmptySet))
  279. raises(ValueError, lambda : minimum(1/(x**2 + y**2 + 1), x, S.EmptySet))
  280. raises(ValueError, lambda : minimum(sin(x), sin(x)))
  281. raises(ValueError, lambda : minimum(sin(x), x*y, S.EmptySet))
  282. raises(ValueError, lambda : minimum(sin(x), S.One))
  283. def test_issue_19869():
  284. t = symbols('t')
  285. assert (maximum(sqrt(3)*(t - 1)/(3*sqrt(t**2 + 1)), t)
  286. ) == sqrt(3)/3
  287. def test_issue_16469():
  288. x = Symbol("x", real=True)
  289. f = abs(x)
  290. assert function_range(f, x, S.Reals) == Interval(0, oo, False, True)
  291. @_both_exp_pow
  292. def test_issue_18747():
  293. assert periodicity(exp(pi*I*(x/4+S.Half/2)), x) == 8