common.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. from sympy.assumptions import Predicate, AppliedPredicate, Q
  2. from sympy.core.relational import Eq, Ne, Gt, Lt, Ge, Le
  3. from sympy.multipledispatch import Dispatcher
  4. class CommutativePredicate(Predicate):
  5. """
  6. Commutative predicate.
  7. Explanation
  8. ===========
  9. ``ask(Q.commutative(x))`` is true iff ``x`` commutes with any other
  10. object with respect to multiplication operation.
  11. """
  12. # TODO: Add examples
  13. name = 'commutative'
  14. handler = Dispatcher("CommutativeHandler", doc="Handler for key 'commutative'.")
  15. binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le}
  16. class IsTruePredicate(Predicate):
  17. """
  18. Generic predicate.
  19. Explanation
  20. ===========
  21. ``ask(Q.is_true(x))`` is true iff ``x`` is true. This only makes
  22. sense if ``x`` is a boolean object.
  23. Examples
  24. ========
  25. >>> from sympy import ask, Q
  26. >>> from sympy.abc import x, y
  27. >>> ask(Q.is_true(True))
  28. True
  29. Wrapping another applied predicate just returns the applied predicate.
  30. >>> Q.is_true(Q.even(x))
  31. Q.even(x)
  32. Wrapping binary relation classes in SymPy core returns applied binary
  33. relational predicates.
  34. >>> from sympy import Eq, Gt
  35. >>> Q.is_true(Eq(x, y))
  36. Q.eq(x, y)
  37. >>> Q.is_true(Gt(x, y))
  38. Q.gt(x, y)
  39. Notes
  40. =====
  41. This class is designed to wrap the boolean objects so that they can
  42. behave as if they are applied predicates. Consequently, wrapping another
  43. applied predicate is unnecessary and thus it just returns the argument.
  44. Also, binary relation classes in SymPy core have binary predicates to
  45. represent themselves and thus wrapping them with ``Q.is_true`` converts them
  46. to these applied predicates.
  47. """
  48. name = 'is_true'
  49. handler = Dispatcher(
  50. "IsTrueHandler",
  51. doc="Wrapper allowing to query the truth value of a boolean expression."
  52. )
  53. def __call__(self, arg):
  54. # No need to wrap another predicate
  55. if isinstance(arg, AppliedPredicate):
  56. return arg
  57. # Convert relational predicates instead of wrapping them
  58. if getattr(arg, "is_Relational", False):
  59. pred = binrelpreds[type(arg)]
  60. return pred(*arg.args)
  61. return super().__call__(arg)