relational.py 49 KB

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