m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1599 lines
50 KiB

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