relational.py 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622
  1. from __future__ import annotations
  2. from .basic import Atom, Basic
  3. from .coreerrors import LazyExceptionMessage
  4. from .sorting import ordered
  5. from .evalf import EvalfMixin
  6. from .function import AppliedUndef
  7. from .numbers import int_valued
  8. from .singleton import S
  9. from .sympify import _sympify, SympifyError
  10. from .parameters import global_parameters
  11. from .logic import fuzzy_bool, fuzzy_xor, fuzzy_and, fuzzy_not
  12. from sympy.logic.boolalg import Boolean, BooleanAtom
  13. from sympy.utilities.iterables import sift
  14. from sympy.utilities.misc import filldedent
  15. from sympy.utilities.exceptions import sympy_deprecation_warning
  16. __all__ = (
  17. 'Rel', 'Eq', 'Ne', 'Lt', 'Le', 'Gt', 'Ge',
  18. 'Relational', 'Equality', 'Unequality', 'StrictLessThan', 'LessThan',
  19. 'StrictGreaterThan', 'GreaterThan',
  20. )
  21. from .expr import Expr
  22. from sympy.multipledispatch import dispatch
  23. from .containers import Tuple
  24. from .symbol import Symbol
  25. def _nontrivBool(side):
  26. return isinstance(side, Boolean) and \
  27. not isinstance(side, Atom)
  28. # Note, see issue 4986. Ideally, we wouldn't want to subclass both Boolean
  29. # and Expr.
  30. # from .. import Expr
  31. def _canonical(cond):
  32. # return a condition in which all relationals are canonical
  33. reps = {r: r.canonical for r in cond.atoms(Relational)}
  34. return cond.xreplace(reps)
  35. # XXX: AttributeError was being caught here but it wasn't triggered by any of
  36. # the tests so I've removed it...
  37. def _canonical_coeff(rel):
  38. # return -2*x + 1 < 0 as x > 1/2
  39. # XXX make this part of Relational.canonical?
  40. rel = rel.canonical
  41. if not rel.is_Relational or rel.rhs.is_Boolean:
  42. return rel # Eq(x, True)
  43. if not isinstance(rel.lhs, Expr):
  44. return rel.reversed # e.g.: Eq(True, x) -> Eq(x, True)
  45. b, l = rel.lhs.as_coeff_Add(rational=True)
  46. m, lhs = l.as_coeff_Mul(rational=True)
  47. rhs = (rel.rhs - b)/m
  48. if m < 0:
  49. return rel.reversed.func(lhs, rhs)
  50. return rel.func(lhs, rhs)
  51. class Relational(Boolean, EvalfMixin):
  52. """Base class for all relation types.
  53. Explanation
  54. ===========
  55. Subclasses of Relational should generally be instantiated directly, but
  56. Relational can be instantiated with a valid ``rop`` value to dispatch to
  57. the appropriate subclass.
  58. Parameters
  59. ==========
  60. rop : str or None
  61. Indicates what subclass to instantiate. Valid values can be found
  62. in the keys of Relational.ValidRelationOperator.
  63. Examples
  64. ========
  65. >>> from sympy import Rel
  66. >>> from sympy.abc import x, y
  67. >>> Rel(y, x + x**2, '==')
  68. Eq(y, x**2 + x)
  69. A relation's type can be defined upon creation using ``rop``.
  70. The relation type of an existing expression can be obtained
  71. using its ``rel_op`` property.
  72. Here is a table of all the relation types, along with their
  73. ``rop`` and ``rel_op`` values:
  74. +---------------------+----------------------------+------------+
  75. |Relation |``rop`` |``rel_op`` |
  76. +=====================+============================+============+
  77. |``Equality`` |``==`` or ``eq`` or ``None``|``==`` |
  78. +---------------------+----------------------------+------------+
  79. |``Unequality`` |``!=`` or ``ne`` |``!=`` |
  80. +---------------------+----------------------------+------------+
  81. |``GreaterThan`` |``>=`` or ``ge`` |``>=`` |
  82. +---------------------+----------------------------+------------+
  83. |``LessThan`` |``<=`` or ``le`` |``<=`` |
  84. +---------------------+----------------------------+------------+
  85. |``StrictGreaterThan``|``>`` or ``gt`` |``>`` |
  86. +---------------------+----------------------------+------------+
  87. |``StrictLessThan`` |``<`` or ``lt`` |``<`` |
  88. +---------------------+----------------------------+------------+
  89. For example, setting ``rop`` to ``==`` produces an
  90. ``Equality`` relation, ``Eq()``.
  91. So does setting ``rop`` to ``eq``, or leaving ``rop`` unspecified.
  92. That is, the first three ``Rel()`` below all produce the same result.
  93. Using a ``rop`` from a different row in the table produces a
  94. different relation type.
  95. For example, the fourth ``Rel()`` below using ``lt`` for ``rop``
  96. produces a ``StrictLessThan`` inequality:
  97. >>> from sympy import Rel
  98. >>> from sympy.abc import x, y
  99. >>> Rel(y, x + x**2, '==')
  100. Eq(y, x**2 + x)
  101. >>> Rel(y, x + x**2, 'eq')
  102. Eq(y, x**2 + x)
  103. >>> Rel(y, x + x**2)
  104. Eq(y, x**2 + x)
  105. >>> Rel(y, x + x**2, 'lt')
  106. y < x**2 + x
  107. To obtain the relation type of an existing expression,
  108. get its ``rel_op`` property.
  109. For example, ``rel_op`` is ``==`` for the ``Equality`` relation above,
  110. and ``<`` for the strict less than inequality above:
  111. >>> from sympy import Rel
  112. >>> from sympy.abc import x, y
  113. >>> my_equality = Rel(y, x + x**2, '==')
  114. >>> my_equality.rel_op
  115. '=='
  116. >>> my_inequality = Rel(y, x + x**2, 'lt')
  117. >>> my_inequality.rel_op
  118. '<'
  119. """
  120. __slots__ = ()
  121. ValidRelationOperator: dict[str | None, type[Relational]] = {}
  122. is_Relational = True
  123. # ValidRelationOperator - Defined below, because the necessary classes
  124. # have not yet been defined
  125. def __new__(cls, lhs, rhs, rop=None, **assumptions):
  126. # If called by a subclass, do nothing special and pass on to Basic.
  127. if cls is not Relational:
  128. return Basic.__new__(cls, lhs, rhs, **assumptions)
  129. # XXX: Why do this? There should be a separate function to make a
  130. # particular subclass of Relational from a string.
  131. #
  132. # If called directly with an operator, look up the subclass
  133. # corresponding to that operator and delegate to it
  134. cls = cls.ValidRelationOperator.get(rop, None)
  135. if cls is None:
  136. raise ValueError("Invalid relational operator symbol: %r" % rop)
  137. if not issubclass(cls, (Eq, Ne)):
  138. # validate that Booleans are not being used in a relational
  139. # other than Eq/Ne;
  140. # Note: Symbol is a subclass of Boolean but is considered
  141. # acceptable here.
  142. if any(map(_nontrivBool, (lhs, rhs))):
  143. raise TypeError(filldedent('''
  144. A Boolean argument can only be used in
  145. Eq and Ne; all other relationals expect
  146. real expressions.
  147. '''))
  148. return cls(lhs, rhs, **assumptions)
  149. @property
  150. def lhs(self):
  151. """The left-hand side of the relation."""
  152. return self._args[0]
  153. @property
  154. def rhs(self):
  155. """The right-hand side of the relation."""
  156. return self._args[1]
  157. @property
  158. def reversed(self):
  159. """Return the relationship with sides reversed.
  160. Examples
  161. ========
  162. >>> from sympy import Eq
  163. >>> from sympy.abc import x
  164. >>> Eq(x, 1)
  165. Eq(x, 1)
  166. >>> _.reversed
  167. Eq(1, x)
  168. >>> x < 1
  169. x < 1
  170. >>> _.reversed
  171. 1 > x
  172. """
  173. ops = {Eq: Eq, Gt: Lt, Ge: Le, Lt: Gt, Le: Ge, Ne: Ne}
  174. a, b = self.args
  175. return Relational.__new__(ops.get(self.func, self.func), b, a)
  176. @property
  177. def reversedsign(self):
  178. """Return the relationship with signs reversed.
  179. Examples
  180. ========
  181. >>> from sympy import Eq
  182. >>> from sympy.abc import x
  183. >>> Eq(x, 1)
  184. Eq(x, 1)
  185. >>> _.reversedsign
  186. Eq(-x, -1)
  187. >>> x < 1
  188. x < 1
  189. >>> _.reversedsign
  190. -x > -1
  191. """
  192. a, b = self.args
  193. if not (isinstance(a, BooleanAtom) or isinstance(b, BooleanAtom)):
  194. ops = {Eq: Eq, Gt: Lt, Ge: Le, Lt: Gt, Le: Ge, Ne: Ne}
  195. return Relational.__new__(ops.get(self.func, self.func), -a, -b)
  196. else:
  197. return self
  198. @property
  199. def negated(self):
  200. """Return the negated relationship.
  201. Examples
  202. ========
  203. >>> from sympy import Eq
  204. >>> from sympy.abc import x
  205. >>> Eq(x, 1)
  206. Eq(x, 1)
  207. >>> _.negated
  208. Ne(x, 1)
  209. >>> x < 1
  210. x < 1
  211. >>> _.negated
  212. x >= 1
  213. Notes
  214. =====
  215. This works more or less identical to ``~``/``Not``. The difference is
  216. that ``negated`` returns the relationship even if ``evaluate=False``.
  217. Hence, this is useful in code when checking for e.g. negated relations
  218. to existing ones as it will not be affected by the `evaluate` flag.
  219. """
  220. ops = {Eq: Ne, Ge: Lt, Gt: Le, Le: Gt, Lt: Ge, Ne: Eq}
  221. # If there ever will be new Relational subclasses, the following line
  222. # will work until it is properly sorted out
  223. # return ops.get(self.func, lambda a, b, evaluate=False: ~(self.func(a,
  224. # b, evaluate=evaluate)))(*self.args, evaluate=False)
  225. return Relational.__new__(ops.get(self.func), *self.args)
  226. @property
  227. def weak(self):
  228. """return the non-strict version of the inequality or self
  229. EXAMPLES
  230. ========
  231. >>> from sympy.abc import x
  232. >>> (x < 1).weak
  233. x <= 1
  234. >>> _.weak
  235. x <= 1
  236. """
  237. return self
  238. @property
  239. def strict(self):
  240. """return the strict version of the inequality or self
  241. EXAMPLES
  242. ========
  243. >>> from sympy.abc import x
  244. >>> (x <= 1).strict
  245. x < 1
  246. >>> _.strict
  247. x < 1
  248. """
  249. return self
  250. def _eval_evalf(self, prec):
  251. return self.func(*[s._evalf(prec) for s in self.args])
  252. @property
  253. def canonical(self):
  254. """Return a canonical form of the relational by putting a
  255. number on the rhs, canonically removing a sign or else
  256. ordering the args canonically. No other simplification is
  257. attempted.
  258. Examples
  259. ========
  260. >>> from sympy.abc import x, y
  261. >>> x < 2
  262. x < 2
  263. >>> _.reversed.canonical
  264. x < 2
  265. >>> (-y < x).canonical
  266. x > -y
  267. >>> (-y > x).canonical
  268. x < -y
  269. >>> (-y < -x).canonical
  270. x < y
  271. The canonicalization is recursively applied:
  272. >>> from sympy import Eq
  273. >>> Eq(x < y, y > x).canonical
  274. True
  275. """
  276. args = tuple([i.canonical if isinstance(i, Relational) else i for i in self.args])
  277. if args != self.args:
  278. r = self.func(*args)
  279. if not isinstance(r, Relational):
  280. return r
  281. else:
  282. r = self
  283. if r.rhs.is_number:
  284. if r.rhs.is_Number and r.lhs.is_Number and r.lhs > r.rhs:
  285. r = r.reversed
  286. elif r.lhs.is_number:
  287. r = r.reversed
  288. elif tuple(ordered(args)) != args:
  289. r = r.reversed
  290. LHS_CEMS = getattr(r.lhs, 'could_extract_minus_sign', None)
  291. RHS_CEMS = getattr(r.rhs, 'could_extract_minus_sign', None)
  292. if isinstance(r.lhs, BooleanAtom) or isinstance(r.rhs, BooleanAtom):
  293. return r
  294. # Check if first value has negative sign
  295. if LHS_CEMS and LHS_CEMS():
  296. return r.reversedsign
  297. elif not r.rhs.is_number and RHS_CEMS and RHS_CEMS():
  298. # Right hand side has a minus, but not lhs.
  299. # How does the expression with reversed signs behave?
  300. # This is so that expressions of the type
  301. # Eq(x, -y) and Eq(-x, y)
  302. # have the same canonical representation
  303. expr1, _ = ordered([r.lhs, -r.rhs])
  304. if expr1 != r.lhs:
  305. return r.reversed.reversedsign
  306. return r
  307. def equals(self, other, failing_expression=False):
  308. """Return True if the sides of the relationship are mathematically
  309. identical and the type of relationship is the same.
  310. If failing_expression is True, return the expression whose truth value
  311. was unknown."""
  312. if isinstance(other, Relational):
  313. if other in (self, self.reversed):
  314. return True
  315. a, b = self, other
  316. if a.func in (Eq, Ne) or b.func in (Eq, Ne):
  317. if a.func != b.func:
  318. return False
  319. left, right = [i.equals(j,
  320. failing_expression=failing_expression)
  321. for i, j in zip(a.args, b.args)]
  322. if left is True:
  323. return right
  324. if right is True:
  325. return left
  326. lr, rl = [i.equals(j, failing_expression=failing_expression)
  327. for i, j in zip(a.args, b.reversed.args)]
  328. if lr is True:
  329. return rl
  330. if rl is True:
  331. return lr
  332. e = (left, right, lr, rl)
  333. if all(i is False for i in e):
  334. return False
  335. for i in e:
  336. if i not in (True, False):
  337. return i
  338. else:
  339. if b.func != a.func:
  340. b = b.reversed
  341. if a.func != b.func:
  342. return False
  343. left = a.lhs.equals(b.lhs,
  344. failing_expression=failing_expression)
  345. if left is False:
  346. return False
  347. right = a.rhs.equals(b.rhs,
  348. failing_expression=failing_expression)
  349. if right is False:
  350. return False
  351. if left is True:
  352. return right
  353. return left
  354. def _eval_simplify(self, **kwargs):
  355. from .add import Add
  356. from .expr import Expr
  357. r = self
  358. r = r.func(*[i.simplify(**kwargs) for i in r.args])
  359. if r.is_Relational:
  360. if not isinstance(r.lhs, Expr) or not isinstance(r.rhs, Expr):
  361. return r
  362. dif = r.lhs - r.rhs
  363. # replace dif with a valid Number that will
  364. # allow a definitive comparison with 0
  365. v = None
  366. if dif.is_comparable:
  367. v = dif.n(2)
  368. if any(i._prec == 1 for i in v.as_real_imag()):
  369. rv, iv = [i.n(2) for i in dif.as_real_imag()]
  370. v = rv + S.ImaginaryUnit*iv
  371. elif dif.equals(0): # XXX this is expensive
  372. v = S.Zero
  373. if v is not None:
  374. r = r.func._eval_relation(v, S.Zero)
  375. r = r.canonical
  376. # If there is only one symbol in the expression,
  377. # try to write it on a simplified form
  378. free = list(filter(lambda x: x.is_real is not False, r.free_symbols))
  379. if len(free) == 1:
  380. try:
  381. from sympy.solvers.solveset import linear_coeffs
  382. x = free.pop()
  383. dif = r.lhs - r.rhs
  384. m, b = linear_coeffs(dif, x)
  385. if m.is_zero is False:
  386. if m.is_negative:
  387. # Dividing with a negative number, so change order of arguments
  388. # canonical will put the symbol back on the lhs later
  389. r = r.func(-b / m, x)
  390. else:
  391. r = r.func(x, -b / m)
  392. else:
  393. r = r.func(b, S.Zero)
  394. except ValueError:
  395. # maybe not a linear function, try polynomial
  396. from sympy.polys.polyerrors import PolynomialError
  397. from sympy.polys.polytools import gcd, Poly, poly
  398. try:
  399. p = poly(dif, x)
  400. c = p.all_coeffs()
  401. constant = c[-1]
  402. c[-1] = 0
  403. scale = gcd(c)
  404. c = [ctmp / scale for ctmp in c]
  405. r = r.func(Poly.from_list(c, x).as_expr(), -constant / scale)
  406. except PolynomialError:
  407. pass
  408. elif len(free) >= 2:
  409. try:
  410. from sympy.solvers.solveset import linear_coeffs
  411. from sympy.polys.polytools import gcd
  412. free = list(ordered(free))
  413. dif = r.lhs - r.rhs
  414. m = linear_coeffs(dif, *free)
  415. constant = m[-1]
  416. del m[-1]
  417. scale = gcd(m)
  418. m = [mtmp / scale for mtmp in m]
  419. nzm = list(filter(lambda f: f[0] != 0, list(zip(m, free))))
  420. if scale.is_zero is False:
  421. if constant != 0:
  422. # lhs: expression, rhs: constant
  423. newexpr = Add(*[i * j for i, j in nzm])
  424. r = r.func(newexpr, -constant / scale)
  425. else:
  426. # keep first term on lhs
  427. lhsterm = nzm[0][0] * nzm[0][1]
  428. del nzm[0]
  429. newexpr = Add(*[i * j for i, j in nzm])
  430. r = r.func(lhsterm, -newexpr)
  431. else:
  432. r = r.func(constant, S.Zero)
  433. except ValueError:
  434. pass
  435. # Did we get a simplified result?
  436. r = r.canonical
  437. measure = kwargs['measure']
  438. if measure(r) < kwargs['ratio'] * measure(self):
  439. return r
  440. else:
  441. return self
  442. def _eval_trigsimp(self, **opts):
  443. from sympy.simplify.trigsimp import trigsimp
  444. return self.func(trigsimp(self.lhs, **opts), trigsimp(self.rhs, **opts))
  445. def expand(self, **kwargs):
  446. args = (arg.expand(**kwargs) for arg in self.args)
  447. return self.func(*args)
  448. def __bool__(self) -> bool:
  449. raise TypeError(
  450. LazyExceptionMessage(
  451. lambda: f"cannot determine truth value of Relational: {self}"
  452. )
  453. )
  454. def _eval_as_set(self):
  455. # self is univariate and periodicity(self, x) in (0, None)
  456. from sympy.solvers.inequalities import solve_univariate_inequality
  457. from sympy.sets.conditionset import ConditionSet
  458. syms = self.free_symbols
  459. assert len(syms) == 1
  460. x = syms.pop()
  461. try:
  462. xset = solve_univariate_inequality(self, x, relational=False)
  463. except NotImplementedError:
  464. # solve_univariate_inequality raises NotImplementedError for
  465. # unsolvable equations/inequalities.
  466. xset = ConditionSet(x, self, S.Reals)
  467. return xset
  468. @property
  469. def binary_symbols(self):
  470. # override where necessary
  471. return set()
  472. Rel = Relational
  473. class Equality(Relational):
  474. """
  475. An equal relation between two objects.
  476. Explanation
  477. ===========
  478. Represents that two objects are equal. If they can be easily shown
  479. to be definitively equal (or unequal), this will reduce to True (or
  480. False). Otherwise, the relation is maintained as an unevaluated
  481. Equality object. Use the ``simplify`` function on this object for
  482. more nontrivial evaluation of the equality relation.
  483. As usual, the keyword argument ``evaluate=False`` can be used to
  484. prevent any evaluation.
  485. Examples
  486. ========
  487. >>> from sympy import Eq, simplify, exp, cos
  488. >>> from sympy.abc import x, y
  489. >>> Eq(y, x + x**2)
  490. Eq(y, x**2 + x)
  491. >>> Eq(2, 5)
  492. False
  493. >>> Eq(2, 5, evaluate=False)
  494. Eq(2, 5)
  495. >>> _.doit()
  496. False
  497. >>> Eq(exp(x), exp(x).rewrite(cos))
  498. Eq(exp(x), sinh(x) + cosh(x))
  499. >>> simplify(_)
  500. True
  501. See Also
  502. ========
  503. sympy.logic.boolalg.Equivalent : for representing equality between two
  504. boolean expressions
  505. Notes
  506. =====
  507. Python treats 1 and True (and 0 and False) as being equal; SymPy
  508. does not. And integer will always compare as unequal to a Boolean:
  509. >>> Eq(True, 1), True == 1
  510. (False, True)
  511. This class is not the same as the == operator. The == operator tests
  512. for exact structural equality between two expressions; this class
  513. compares expressions mathematically.
  514. If either object defines an ``_eval_Eq`` method, it can be used in place of
  515. the default algorithm. If ``lhs._eval_Eq(rhs)`` or ``rhs._eval_Eq(lhs)``
  516. returns anything other than None, that return value will be substituted for
  517. the Equality. If None is returned by ``_eval_Eq``, an Equality object will
  518. be created as usual.
  519. Since this object is already an expression, it does not respond to
  520. the method ``as_expr`` if one tries to create `x - y` from ``Eq(x, y)``.
  521. If ``eq = Eq(x, y)`` then write `eq.lhs - eq.rhs` to get ``x - y``.
  522. .. deprecated:: 1.5
  523. ``Eq(expr)`` with a single argument is a shorthand for ``Eq(expr, 0)``,
  524. but this behavior is deprecated and will be removed in a future version
  525. of SymPy.
  526. """
  527. rel_op = '=='
  528. __slots__ = ()
  529. is_Equality = True
  530. def __new__(cls, lhs, rhs, **options):
  531. evaluate = options.pop('evaluate', global_parameters.evaluate)
  532. lhs = _sympify(lhs)
  533. rhs = _sympify(rhs)
  534. if evaluate:
  535. val = is_eq(lhs, rhs)
  536. if val is None:
  537. return cls(lhs, rhs, evaluate=False)
  538. else:
  539. return _sympify(val)
  540. return Relational.__new__(cls, lhs, rhs)
  541. @classmethod
  542. def _eval_relation(cls, lhs, rhs):
  543. return _sympify(lhs == rhs)
  544. def _eval_rewrite_as_Add(self, L, R, evaluate=True, **kwargs):
  545. """
  546. return Eq(L, R) as L - R. To control the evaluation of
  547. the result set pass `evaluate=True` to give L - R;
  548. if `evaluate=None` then terms in L and R will not cancel
  549. but they will be listed in canonical order; otherwise
  550. non-canonical args will be returned. If one side is 0, the
  551. non-zero side will be returned.
  552. .. deprecated:: 1.13
  553. The method ``Eq.rewrite(Add)`` is deprecated.
  554. See :ref:`eq-rewrite-Add` for details.
  555. Examples
  556. ========
  557. >>> from sympy import Eq, Add
  558. >>> from sympy.abc import b, x
  559. >>> eq = Eq(x + b, x - b)
  560. >>> eq.rewrite(Add) #doctest: +SKIP
  561. 2*b
  562. >>> eq.rewrite(Add, evaluate=None).args #doctest: +SKIP
  563. (b, b, x, -x)
  564. >>> eq.rewrite(Add, evaluate=False).args #doctest: +SKIP
  565. (b, x, b, -x)
  566. """
  567. sympy_deprecation_warning("""
  568. Eq.rewrite(Add) is deprecated.
  569. For ``eq = Eq(a, b)`` use ``eq.lhs - eq.rhs`` to obtain
  570. ``a - b``.
  571. """,
  572. deprecated_since_version="1.13",
  573. active_deprecations_target="eq-rewrite-Add",
  574. stacklevel=5,
  575. )
  576. from .add import _unevaluated_Add, Add
  577. if L == 0:
  578. return R
  579. if R == 0:
  580. return L
  581. if evaluate:
  582. # allow cancellation of args
  583. return L - R
  584. args = Add.make_args(L) + Add.make_args(-R)
  585. if evaluate is None:
  586. # no cancellation, but canonical
  587. return _unevaluated_Add(*args)
  588. # no cancellation, not canonical
  589. return Add._from_args(args)
  590. @property
  591. def binary_symbols(self):
  592. if S.true in self.args or S.false in self.args:
  593. if self.lhs.is_Symbol:
  594. return {self.lhs}
  595. elif self.rhs.is_Symbol:
  596. return {self.rhs}
  597. return set()
  598. def _eval_simplify(self, **kwargs):
  599. # standard simplify
  600. e = super()._eval_simplify(**kwargs)
  601. if not isinstance(e, Equality):
  602. return e
  603. from .expr import Expr
  604. if not isinstance(e.lhs, Expr) or not isinstance(e.rhs, Expr):
  605. return e
  606. free = self.free_symbols
  607. if len(free) == 1:
  608. try:
  609. from .add import Add
  610. from sympy.solvers.solveset import linear_coeffs
  611. x = free.pop()
  612. m, b = linear_coeffs(
  613. Add(e.lhs, -e.rhs, evaluate=False), x)
  614. if m.is_zero is False:
  615. enew = e.func(x, -b / m)
  616. else:
  617. enew = e.func(m * x, -b)
  618. measure = kwargs['measure']
  619. if measure(enew) <= kwargs['ratio'] * measure(e):
  620. e = enew
  621. except ValueError:
  622. pass
  623. return e.canonical
  624. def integrate(self, *args, **kwargs):
  625. """See the integrate function in sympy.integrals"""
  626. from sympy.integrals.integrals import integrate
  627. return integrate(self, *args, **kwargs)
  628. def as_poly(self, *gens, **kwargs):
  629. '''Returns lhs-rhs as a Poly
  630. Examples
  631. ========
  632. >>> from sympy import Eq
  633. >>> from sympy.abc import x
  634. >>> Eq(x**2, 1).as_poly(x)
  635. Poly(x**2 - 1, x, domain='ZZ')
  636. '''
  637. return (self.lhs - self.rhs).as_poly(*gens, **kwargs)
  638. Eq = Equality
  639. class Unequality(Relational):
  640. """An unequal relation between two objects.
  641. Explanation
  642. ===========
  643. Represents that two objects are not equal. If they can be shown to be
  644. definitively equal, this will reduce to False; if definitively unequal,
  645. this will reduce to True. Otherwise, the relation is maintained as an
  646. Unequality object.
  647. Examples
  648. ========
  649. >>> from sympy import Ne
  650. >>> from sympy.abc import x, y
  651. >>> Ne(y, x+x**2)
  652. Ne(y, x**2 + x)
  653. See Also
  654. ========
  655. Equality
  656. Notes
  657. =====
  658. This class is not the same as the != operator. The != operator tests
  659. for exact structural equality between two expressions; this class
  660. compares expressions mathematically.
  661. This class is effectively the inverse of Equality. As such, it uses the
  662. same algorithms, including any available `_eval_Eq` methods.
  663. """
  664. rel_op = '!='
  665. __slots__ = ()
  666. def __new__(cls, lhs, rhs, **options):
  667. lhs = _sympify(lhs)
  668. rhs = _sympify(rhs)
  669. evaluate = options.pop('evaluate', global_parameters.evaluate)
  670. if evaluate:
  671. val = is_neq(lhs, rhs)
  672. if val is None:
  673. return cls(lhs, rhs, evaluate=False)
  674. else:
  675. return _sympify(val)
  676. return Relational.__new__(cls, lhs, rhs, **options)
  677. @classmethod
  678. def _eval_relation(cls, lhs, rhs):
  679. return _sympify(lhs != rhs)
  680. @property
  681. def binary_symbols(self):
  682. if S.true in self.args or S.false in self.args:
  683. if self.lhs.is_Symbol:
  684. return {self.lhs}
  685. elif self.rhs.is_Symbol:
  686. return {self.rhs}
  687. return set()
  688. def _eval_simplify(self, **kwargs):
  689. # simplify as an equality
  690. eq = Equality(*self.args)._eval_simplify(**kwargs)
  691. if isinstance(eq, Equality):
  692. # send back Ne with the new args
  693. return self.func(*eq.args)
  694. return eq.negated # result of Ne is the negated Eq
  695. Ne = Unequality
  696. class _Inequality(Relational):
  697. """Internal base class for all *Than types.
  698. Each subclass must implement _eval_relation to provide the method for
  699. comparing two real numbers.
  700. """
  701. __slots__ = ()
  702. def __new__(cls, lhs, rhs, **options):
  703. try:
  704. lhs = _sympify(lhs)
  705. rhs = _sympify(rhs)
  706. except SympifyError:
  707. return NotImplemented
  708. evaluate = options.pop('evaluate', global_parameters.evaluate)
  709. if evaluate:
  710. for me in (lhs, rhs):
  711. if me.is_extended_real is False:
  712. raise TypeError("Invalid comparison of non-real %s" % me)
  713. if me is S.NaN:
  714. raise TypeError("Invalid NaN comparison")
  715. # First we invoke the appropriate inequality method of `lhs`
  716. # (e.g., `lhs.__lt__`). That method will try to reduce to
  717. # boolean or raise an exception. It may keep calling
  718. # superclasses until it reaches `Expr` (e.g., `Expr.__lt__`).
  719. # In some cases, `Expr` will just invoke us again (if neither it
  720. # nor a subclass was able to reduce to boolean or raise an
  721. # exception). In that case, it must call us with
  722. # `evaluate=False` to prevent infinite recursion.
  723. return cls._eval_relation(lhs, rhs, **options)
  724. # make a "non-evaluated" Expr for the inequality
  725. return Relational.__new__(cls, lhs, rhs, **options)
  726. @classmethod
  727. def _eval_relation(cls, lhs, rhs, **options):
  728. val = cls._eval_fuzzy_relation(lhs, rhs)
  729. if val is None:
  730. return cls(lhs, rhs, evaluate=False)
  731. else:
  732. return _sympify(val)
  733. class _Greater(_Inequality):
  734. """Not intended for general use
  735. _Greater is only used so that GreaterThan and StrictGreaterThan may
  736. subclass it for the .gts and .lts properties.
  737. """
  738. __slots__ = ()
  739. @property
  740. def gts(self):
  741. return self._args[0]
  742. @property
  743. def lts(self):
  744. return self._args[1]
  745. class _Less(_Inequality):
  746. """Not intended for general use.
  747. _Less is only used so that LessThan and StrictLessThan may subclass it for
  748. the .gts and .lts properties.
  749. """
  750. __slots__ = ()
  751. @property
  752. def gts(self):
  753. return self._args[1]
  754. @property
  755. def lts(self):
  756. return self._args[0]
  757. class GreaterThan(_Greater):
  758. r"""Class representations of inequalities.
  759. Explanation
  760. ===========
  761. The ``*Than`` classes represent inequal relationships, where the left-hand
  762. side is generally bigger or smaller than the right-hand side. For example,
  763. the GreaterThan class represents an inequal relationship where the
  764. left-hand side is at least as big as the right side, if not bigger. In
  765. mathematical notation:
  766. lhs $\ge$ rhs
  767. In total, there are four ``*Than`` classes, to represent the four
  768. inequalities:
  769. +-----------------+--------+
  770. |Class Name | Symbol |
  771. +=================+========+
  772. |GreaterThan | ``>=`` |
  773. +-----------------+--------+
  774. |LessThan | ``<=`` |
  775. +-----------------+--------+
  776. |StrictGreaterThan| ``>`` |
  777. +-----------------+--------+
  778. |StrictLessThan | ``<`` |
  779. +-----------------+--------+
  780. All classes take two arguments, lhs and rhs.
  781. +----------------------------+-----------------+
  782. |Signature Example | Math Equivalent |
  783. +============================+=================+
  784. |GreaterThan(lhs, rhs) | lhs $\ge$ rhs |
  785. +----------------------------+-----------------+
  786. |LessThan(lhs, rhs) | lhs $\le$ rhs |
  787. +----------------------------+-----------------+
  788. |StrictGreaterThan(lhs, rhs) | lhs $>$ rhs |
  789. +----------------------------+-----------------+
  790. |StrictLessThan(lhs, rhs) | lhs $<$ rhs |
  791. +----------------------------+-----------------+
  792. In addition to the normal .lhs and .rhs of Relations, ``*Than`` inequality
  793. objects also have the .lts and .gts properties, which represent the "less
  794. than side" and "greater than side" of the operator. Use of .lts and .gts
  795. in an algorithm rather than .lhs and .rhs as an assumption of inequality
  796. direction will make more explicit the intent of a certain section of code,
  797. and will make it similarly more robust to client code changes:
  798. >>> from sympy import GreaterThan, StrictGreaterThan
  799. >>> from sympy import LessThan, StrictLessThan
  800. >>> from sympy import And, Ge, Gt, Le, Lt, Rel, S
  801. >>> from sympy.abc import x, y, z
  802. >>> from sympy.core.relational import Relational
  803. >>> e = GreaterThan(x, 1)
  804. >>> e
  805. x >= 1
  806. >>> '%s >= %s is the same as %s <= %s' % (e.gts, e.lts, e.lts, e.gts)
  807. 'x >= 1 is the same as 1 <= x'
  808. Examples
  809. ========
  810. One generally does not instantiate these classes directly, but uses various
  811. convenience methods:
  812. >>> for f in [Ge, Gt, Le, Lt]: # convenience wrappers
  813. ... print(f(x, 2))
  814. x >= 2
  815. x > 2
  816. x <= 2
  817. x < 2
  818. Another option is to use the Python inequality operators (``>=``, ``>``,
  819. ``<=``, ``<``) directly. Their main advantage over the ``Ge``, ``Gt``,
  820. ``Le``, and ``Lt`` counterparts, is that one can write a more
  821. "mathematical looking" statement rather than littering the math with
  822. oddball function calls. However there are certain (minor) caveats of
  823. which to be aware (search for 'gotcha', below).
  824. >>> x >= 2
  825. x >= 2
  826. >>> _ == Ge(x, 2)
  827. True
  828. However, it is also perfectly valid to instantiate a ``*Than`` class less
  829. succinctly and less conveniently:
  830. >>> Rel(x, 1, ">")
  831. x > 1
  832. >>> Relational(x, 1, ">")
  833. x > 1
  834. >>> StrictGreaterThan(x, 1)
  835. x > 1
  836. >>> GreaterThan(x, 1)
  837. x >= 1
  838. >>> LessThan(x, 1)
  839. x <= 1
  840. >>> StrictLessThan(x, 1)
  841. x < 1
  842. Notes
  843. =====
  844. There are a couple of "gotchas" to be aware of when using Python's
  845. operators.
  846. The first is that what your write is not always what you get:
  847. >>> 1 < x
  848. x > 1
  849. Due to the order that Python parses a statement, it may
  850. not immediately find two objects comparable. When ``1 < x``
  851. is evaluated, Python recognizes that the number 1 is a native
  852. number and that x is *not*. Because a native Python number does
  853. not know how to compare itself with a SymPy object
  854. Python will try the reflective operation, ``x > 1`` and that is the
  855. form that gets evaluated, hence returned.
  856. If the order of the statement is important (for visual output to
  857. the console, perhaps), one can work around this annoyance in a
  858. couple ways:
  859. (1) "sympify" the literal before comparison
  860. >>> S(1) < x
  861. 1 < x
  862. (2) use one of the wrappers or less succinct methods described
  863. above
  864. >>> Lt(1, x)
  865. 1 < x
  866. >>> Relational(1, x, "<")
  867. 1 < x
  868. The second gotcha involves writing equality tests between relationals
  869. when one or both sides of the test involve a literal relational:
  870. >>> e = x < 1; e
  871. x < 1
  872. >>> e == e # neither side is a literal
  873. True
  874. >>> e == x < 1 # expecting True, too
  875. False
  876. >>> e != x < 1 # expecting False
  877. x < 1
  878. >>> x < 1 != x < 1 # expecting False or the same thing as before
  879. Traceback (most recent call last):
  880. ...
  881. TypeError: cannot determine truth value of Relational
  882. The solution for this case is to wrap literal relationals in
  883. parentheses:
  884. >>> e == (x < 1)
  885. True
  886. >>> e != (x < 1)
  887. False
  888. >>> (x < 1) != (x < 1)
  889. False
  890. The third gotcha involves chained inequalities not involving
  891. ``==`` or ``!=``. Occasionally, one may be tempted to write:
  892. >>> e = x < y < z
  893. Traceback (most recent call last):
  894. ...
  895. TypeError: symbolic boolean expression has no truth value.
  896. Due to an implementation detail or decision of Python [1]_,
  897. there is no way for SymPy to create a chained inequality with
  898. that syntax so one must use And:
  899. >>> e = And(x < y, y < z)
  900. >>> type( e )
  901. And
  902. >>> e
  903. (x < y) & (y < z)
  904. Although this can also be done with the '&' operator, it cannot
  905. be done with the 'and' operarator:
  906. >>> (x < y) & (y < z)
  907. (x < y) & (y < z)
  908. >>> (x < y) and (y < z)
  909. Traceback (most recent call last):
  910. ...
  911. TypeError: cannot determine truth value of Relational
  912. .. [1] This implementation detail is that Python provides no reliable
  913. method to determine that a chained inequality is being built.
  914. Chained comparison operators are evaluated pairwise, using "and"
  915. logic (see
  916. https://docs.python.org/3/reference/expressions.html#not-in). This
  917. is done in an efficient way, so that each object being compared
  918. is only evaluated once and the comparison can short-circuit. For
  919. example, ``1 > 2 > 3`` is evaluated by Python as ``(1 > 2) and (2
  920. > 3)``. The ``and`` operator coerces each side into a bool,
  921. returning the object itself when it short-circuits. The bool of
  922. the --Than operators will raise TypeError on purpose, because
  923. SymPy cannot determine the mathematical ordering of symbolic
  924. expressions. Thus, if we were to compute ``x > y > z``, with
  925. ``x``, ``y``, and ``z`` being Symbols, Python converts the
  926. statement (roughly) into these steps:
  927. (1) x > y > z
  928. (2) (x > y) and (y > z)
  929. (3) (GreaterThanObject) and (y > z)
  930. (4) (GreaterThanObject.__bool__()) and (y > z)
  931. (5) TypeError
  932. Because of the ``and`` added at step 2, the statement gets turned into a
  933. weak ternary statement, and the first object's ``__bool__`` method will
  934. raise TypeError. Thus, creating a chained inequality is not possible.
  935. In Python, there is no way to override the ``and`` operator, or to
  936. control how it short circuits, so it is impossible to make something
  937. like ``x > y > z`` work. There was a PEP to change this,
  938. :pep:`335`, but it was officially closed in March, 2012.
  939. """
  940. __slots__ = ()
  941. rel_op = '>='
  942. @classmethod
  943. def _eval_fuzzy_relation(cls, lhs, rhs):
  944. return is_ge(lhs, rhs)
  945. @property
  946. def strict(self):
  947. return Gt(*self.args)
  948. Ge = GreaterThan
  949. class LessThan(_Less):
  950. __doc__ = GreaterThan.__doc__
  951. __slots__ = ()
  952. rel_op = '<='
  953. @classmethod
  954. def _eval_fuzzy_relation(cls, lhs, rhs):
  955. return is_le(lhs, rhs)
  956. @property
  957. def strict(self):
  958. return Lt(*self.args)
  959. Le = LessThan
  960. class StrictGreaterThan(_Greater):
  961. __doc__ = GreaterThan.__doc__
  962. __slots__ = ()
  963. rel_op = '>'
  964. @classmethod
  965. def _eval_fuzzy_relation(cls, lhs, rhs):
  966. return is_gt(lhs, rhs)
  967. @property
  968. def weak(self):
  969. return Ge(*self.args)
  970. Gt = StrictGreaterThan
  971. class StrictLessThan(_Less):
  972. __doc__ = GreaterThan.__doc__
  973. __slots__ = ()
  974. rel_op = '<'
  975. @classmethod
  976. def _eval_fuzzy_relation(cls, lhs, rhs):
  977. return is_lt(lhs, rhs)
  978. @property
  979. def weak(self):
  980. return Le(*self.args)
  981. Lt = StrictLessThan
  982. # A class-specific (not object-specific) data item used for a minor speedup.
  983. # It is defined here, rather than directly in the class, because the classes
  984. # that it references have not been defined until now (e.g. StrictLessThan).
  985. Relational.ValidRelationOperator = {
  986. None: Equality,
  987. '==': Equality,
  988. 'eq': Equality,
  989. '!=': Unequality,
  990. '<>': Unequality,
  991. 'ne': Unequality,
  992. '>=': GreaterThan,
  993. 'ge': GreaterThan,
  994. '<=': LessThan,
  995. 'le': LessThan,
  996. '>': StrictGreaterThan,
  997. 'gt': StrictGreaterThan,
  998. '<': StrictLessThan,
  999. 'lt': StrictLessThan,
  1000. }
  1001. def _n2(a, b):
  1002. """Return (a - b).evalf(2) if a and b are comparable, else None.
  1003. This should only be used when a and b are already sympified.
  1004. """
  1005. # /!\ it is very important (see issue 8245) not to
  1006. # use a re-evaluated number in the calculation of dif
  1007. if a.is_comparable and b.is_comparable:
  1008. dif = (a - b).evalf(2)
  1009. if dif.is_comparable:
  1010. return dif
  1011. @dispatch(Expr, Expr)
  1012. def _eval_is_ge(lhs, rhs):
  1013. return None
  1014. @dispatch(Basic, Basic)
  1015. def _eval_is_eq(lhs, rhs):
  1016. return None
  1017. @dispatch(Tuple, Expr) # type: ignore
  1018. def _eval_is_eq(lhs, rhs): # noqa:F811
  1019. return False
  1020. @dispatch(Tuple, AppliedUndef) # type: ignore
  1021. def _eval_is_eq(lhs, rhs): # noqa:F811
  1022. return None
  1023. @dispatch(Tuple, Symbol) # type: ignore
  1024. def _eval_is_eq(lhs, rhs): # noqa:F811
  1025. return None
  1026. @dispatch(Tuple, Tuple) # type: ignore
  1027. def _eval_is_eq(lhs, rhs): # noqa:F811
  1028. if len(lhs) != len(rhs):
  1029. return False
  1030. return fuzzy_and(fuzzy_bool(is_eq(s, o)) for s, o in zip(lhs, rhs))
  1031. def is_lt(lhs, rhs, assumptions=None):
  1032. """Fuzzy bool for lhs is strictly less than rhs.
  1033. See the docstring for :func:`~.is_ge` for more.
  1034. """
  1035. return fuzzy_not(is_ge(lhs, rhs, assumptions))
  1036. def is_gt(lhs, rhs, assumptions=None):
  1037. """Fuzzy bool for lhs is strictly greater than rhs.
  1038. See the docstring for :func:`~.is_ge` for more.
  1039. """
  1040. return fuzzy_not(is_le(lhs, rhs, assumptions))
  1041. def is_le(lhs, rhs, assumptions=None):
  1042. """Fuzzy bool for lhs is less than or equal to rhs.
  1043. See the docstring for :func:`~.is_ge` for more.
  1044. """
  1045. return is_ge(rhs, lhs, assumptions)
  1046. def is_ge(lhs, rhs, assumptions=None):
  1047. """
  1048. Fuzzy bool for *lhs* is greater than or equal to *rhs*.
  1049. Parameters
  1050. ==========
  1051. lhs : Expr
  1052. The left-hand side of the expression, must be sympified,
  1053. and an instance of expression. Throws an exception if
  1054. lhs is not an instance of expression.
  1055. rhs : Expr
  1056. The right-hand side of the expression, must be sympified
  1057. and an instance of expression. Throws an exception if
  1058. lhs is not an instance of expression.
  1059. assumptions: Boolean, optional
  1060. Assumptions taken to evaluate the inequality.
  1061. Returns
  1062. =======
  1063. ``True`` if *lhs* is greater than or equal to *rhs*, ``False`` if *lhs*
  1064. is less than *rhs*, and ``None`` if the comparison between *lhs* and
  1065. *rhs* is indeterminate.
  1066. Explanation
  1067. ===========
  1068. This function is intended to give a relatively fast determination and
  1069. deliberately does not attempt slow calculations that might help in
  1070. obtaining a determination of True or False in more difficult cases.
  1071. The four comparison functions ``is_le``, ``is_lt``, ``is_ge``, and ``is_gt`` are
  1072. each implemented in terms of ``is_ge`` in the following way:
  1073. is_ge(x, y) := is_ge(x, y)
  1074. is_le(x, y) := is_ge(y, x)
  1075. is_lt(x, y) := fuzzy_not(is_ge(x, y))
  1076. is_gt(x, y) := fuzzy_not(is_ge(y, x))
  1077. Therefore, supporting new type with this function will ensure behavior for
  1078. other three functions as well.
  1079. To maintain these equivalences in fuzzy logic it is important that in cases where
  1080. either x or y is non-real all comparisons will give None.
  1081. Examples
  1082. ========
  1083. >>> from sympy import S, Q
  1084. >>> from sympy.core.relational import is_ge, is_le, is_gt, is_lt
  1085. >>> from sympy.abc import x
  1086. >>> is_ge(S(2), S(0))
  1087. True
  1088. >>> is_ge(S(0), S(2))
  1089. False
  1090. >>> is_le(S(0), S(2))
  1091. True
  1092. >>> is_gt(S(0), S(2))
  1093. False
  1094. >>> is_lt(S(2), S(0))
  1095. False
  1096. Assumptions can be passed to evaluate the quality which is otherwise
  1097. indeterminate.
  1098. >>> print(is_ge(x, S(0)))
  1099. None
  1100. >>> is_ge(x, S(0), assumptions=Q.positive(x))
  1101. True
  1102. New types can be supported by dispatching to ``_eval_is_ge``.
  1103. >>> from sympy import Expr, sympify
  1104. >>> from sympy.multipledispatch import dispatch
  1105. >>> class MyExpr(Expr):
  1106. ... def __new__(cls, arg):
  1107. ... return super().__new__(cls, sympify(arg))
  1108. ... @property
  1109. ... def value(self):
  1110. ... return self.args[0]
  1111. >>> @dispatch(MyExpr, MyExpr)
  1112. ... def _eval_is_ge(a, b):
  1113. ... return is_ge(a.value, b.value)
  1114. >>> a = MyExpr(1)
  1115. >>> b = MyExpr(2)
  1116. >>> is_ge(b, a)
  1117. True
  1118. >>> is_le(a, b)
  1119. True
  1120. """
  1121. from sympy.assumptions.wrapper import AssumptionsWrapper, is_extended_nonnegative
  1122. if not (isinstance(lhs, Expr) and isinstance(rhs, Expr)):
  1123. raise TypeError("Can only compare inequalities with Expr")
  1124. retval = _eval_is_ge(lhs, rhs)
  1125. if retval is not None:
  1126. return retval
  1127. else:
  1128. n2 = _n2(lhs, rhs)
  1129. if n2 is not None:
  1130. # use float comparison for infinity.
  1131. # otherwise get stuck in infinite recursion
  1132. if n2 in (S.Infinity, S.NegativeInfinity):
  1133. n2 = float(n2)
  1134. return n2 >= 0
  1135. _lhs = AssumptionsWrapper(lhs, assumptions)
  1136. _rhs = AssumptionsWrapper(rhs, assumptions)
  1137. if _lhs.is_extended_real and _rhs.is_extended_real:
  1138. if (_lhs.is_infinite and _lhs.is_extended_positive) or (_rhs.is_infinite and _rhs.is_extended_negative):
  1139. return True
  1140. diff = lhs - rhs
  1141. if diff is not S.NaN:
  1142. rv = is_extended_nonnegative(diff, assumptions)
  1143. if rv is not None:
  1144. return rv
  1145. def is_neq(lhs, rhs, assumptions=None):
  1146. """Fuzzy bool for lhs does not equal rhs.
  1147. See the docstring for :func:`~.is_eq` for more.
  1148. """
  1149. return fuzzy_not(is_eq(lhs, rhs, assumptions))
  1150. def is_eq(lhs, rhs, assumptions=None):
  1151. """
  1152. Fuzzy bool representing mathematical equality between *lhs* and *rhs*.
  1153. Parameters
  1154. ==========
  1155. lhs : Expr
  1156. The left-hand side of the expression, must be sympified.
  1157. rhs : Expr
  1158. The right-hand side of the expression, must be sympified.
  1159. assumptions: Boolean, optional
  1160. Assumptions taken to evaluate the equality.
  1161. Returns
  1162. =======
  1163. ``True`` if *lhs* is equal to *rhs*, ``False`` is *lhs* is not equal to *rhs*,
  1164. and ``None`` if the comparison between *lhs* and *rhs* is indeterminate.
  1165. Explanation
  1166. ===========
  1167. This function is intended to give a relatively fast determination and
  1168. deliberately does not attempt slow calculations that might help in
  1169. obtaining a determination of True or False in more difficult cases.
  1170. :func:`~.is_neq` calls this function to return its value, so supporting
  1171. new type with this function will ensure correct behavior for ``is_neq``
  1172. as well.
  1173. Examples
  1174. ========
  1175. >>> from sympy import Q, S
  1176. >>> from sympy.core.relational import is_eq, is_neq
  1177. >>> from sympy.abc import x
  1178. >>> is_eq(S(0), S(0))
  1179. True
  1180. >>> is_neq(S(0), S(0))
  1181. False
  1182. >>> is_eq(S(0), S(2))
  1183. False
  1184. >>> is_neq(S(0), S(2))
  1185. True
  1186. Assumptions can be passed to evaluate the equality which is otherwise
  1187. indeterminate.
  1188. >>> print(is_eq(x, S(0)))
  1189. None
  1190. >>> is_eq(x, S(0), assumptions=Q.zero(x))
  1191. True
  1192. New types can be supported by dispatching to ``_eval_is_eq``.
  1193. >>> from sympy import Basic, sympify
  1194. >>> from sympy.multipledispatch import dispatch
  1195. >>> class MyBasic(Basic):
  1196. ... def __new__(cls, arg):
  1197. ... return Basic.__new__(cls, sympify(arg))
  1198. ... @property
  1199. ... def value(self):
  1200. ... return self.args[0]
  1201. ...
  1202. >>> @dispatch(MyBasic, MyBasic)
  1203. ... def _eval_is_eq(a, b):
  1204. ... return is_eq(a.value, b.value)
  1205. ...
  1206. >>> a = MyBasic(1)
  1207. >>> b = MyBasic(1)
  1208. >>> is_eq(a, b)
  1209. True
  1210. >>> is_neq(a, b)
  1211. False
  1212. """
  1213. # here, _eval_Eq is only called for backwards compatibility
  1214. # new code should use is_eq with multiple dispatch as
  1215. # outlined in the docstring
  1216. for side1, side2 in (lhs, rhs), (rhs, lhs):
  1217. eval_func = getattr(side1, '_eval_Eq', None)
  1218. if eval_func is not None:
  1219. retval = eval_func(side2)
  1220. if retval is not None:
  1221. return retval
  1222. retval = _eval_is_eq(lhs, rhs)
  1223. if retval is not None:
  1224. return retval
  1225. if dispatch(type(lhs), type(rhs)) != dispatch(type(rhs), type(lhs)):
  1226. retval = _eval_is_eq(rhs, lhs)
  1227. if retval is not None:
  1228. return retval
  1229. # retval is still None, so go through the equality logic
  1230. # If expressions have the same structure, they must be equal.
  1231. if lhs == rhs:
  1232. return True # e.g. True == True
  1233. elif all(isinstance(i, BooleanAtom) for i in (rhs, lhs)):
  1234. return False # True != False
  1235. elif not (lhs.is_Symbol or rhs.is_Symbol) and (
  1236. isinstance(lhs, Boolean) !=
  1237. isinstance(rhs, Boolean)):
  1238. return False # only Booleans can equal Booleans
  1239. from sympy.assumptions.wrapper import (AssumptionsWrapper,
  1240. is_infinite, is_extended_real)
  1241. from .add import Add
  1242. _lhs = AssumptionsWrapper(lhs, assumptions)
  1243. _rhs = AssumptionsWrapper(rhs, assumptions)
  1244. if _lhs.is_infinite or _rhs.is_infinite:
  1245. if fuzzy_xor([_lhs.is_infinite, _rhs.is_infinite]):
  1246. return False
  1247. if fuzzy_xor([_lhs.is_extended_real, _rhs.is_extended_real]):
  1248. return False
  1249. if fuzzy_and([_lhs.is_extended_real, _rhs.is_extended_real]):
  1250. return fuzzy_xor([_lhs.is_extended_positive, fuzzy_not(_rhs.is_extended_positive)])
  1251. # Try to split real/imaginary parts and equate them
  1252. I = S.ImaginaryUnit
  1253. def split_real_imag(expr):
  1254. real_imag = lambda t: (
  1255. 'real' if is_extended_real(t, assumptions) else
  1256. 'imag' if is_extended_real(I*t, assumptions) else None)
  1257. return sift(Add.make_args(expr), real_imag)
  1258. lhs_ri = split_real_imag(lhs)
  1259. if not lhs_ri[None]:
  1260. rhs_ri = split_real_imag(rhs)
  1261. if not rhs_ri[None]:
  1262. eq_real = is_eq(Add(*lhs_ri['real']), Add(*rhs_ri['real']), assumptions)
  1263. eq_imag = is_eq(I * Add(*lhs_ri['imag']), I * Add(*rhs_ri['imag']), assumptions)
  1264. return fuzzy_and(map(fuzzy_bool, [eq_real, eq_imag]))
  1265. from sympy.functions.elementary.complexes import arg
  1266. # Compare e.g. zoo with 1+I*oo by comparing args
  1267. arglhs = arg(lhs)
  1268. argrhs = arg(rhs)
  1269. # Guard against Eq(nan, nan) -> False
  1270. if not (arglhs == S.NaN and argrhs == S.NaN):
  1271. return fuzzy_bool(is_eq(arglhs, argrhs, assumptions))
  1272. if all(isinstance(i, Expr) for i in (lhs, rhs)):
  1273. # see if the difference evaluates
  1274. dif = lhs - rhs
  1275. _dif = AssumptionsWrapper(dif, assumptions)
  1276. z = _dif.is_zero
  1277. if z is not None:
  1278. if z is False and _dif.is_commutative: # issue 10728
  1279. return False
  1280. if z:
  1281. return True
  1282. # is_zero cannot help decide integer/rational with Float
  1283. c, t = dif.as_coeff_Add()
  1284. if c.is_Float:
  1285. if int_valued(c):
  1286. if t.is_integer is False:
  1287. return False
  1288. elif t.is_rational is False:
  1289. return False
  1290. n2 = _n2(lhs, rhs)
  1291. if n2 is not None:
  1292. return _sympify(n2 == 0)
  1293. # see if the ratio evaluates
  1294. n, d = dif.as_numer_denom()
  1295. rv = None
  1296. _n = AssumptionsWrapper(n, assumptions)
  1297. _d = AssumptionsWrapper(d, assumptions)
  1298. if _n.is_zero:
  1299. rv = _d.is_nonzero
  1300. elif _n.is_finite:
  1301. if _d.is_infinite:
  1302. rv = True
  1303. elif _n.is_zero is False:
  1304. rv = _d.is_infinite
  1305. if rv is None:
  1306. # if the condition that makes the denominator
  1307. # infinite does not make the original expression
  1308. # True then False can be returned
  1309. from sympy.simplify.simplify import clear_coefficients
  1310. l, r = clear_coefficients(d, S.Infinity)
  1311. args = [_.subs(l, r) for _ in (lhs, rhs)]
  1312. if args != [lhs, rhs]:
  1313. rv = fuzzy_bool(is_eq(*args, assumptions))
  1314. if rv is True:
  1315. rv = None
  1316. elif any(is_infinite(a, assumptions) for a in Add.make_args(n)):
  1317. # (inf or nan)/x != 0
  1318. rv = False
  1319. if rv is not None:
  1320. return rv