I am done

This commit is contained in:
2024-10-30 22:14:35 +01:00
parent 720dc28c09
commit 40e2a747cf
36901 changed files with 5011519 additions and 0 deletions

View File

@ -0,0 +1,5 @@
"""
Module to implement predicate classes.
Class of every predicate registered to ``Q`` is defined here.
"""

View File

@ -0,0 +1,82 @@
from sympy.assumptions import Predicate
from sympy.multipledispatch import Dispatcher
class FinitePredicate(Predicate):
"""
Finite number predicate.
Explanation
===========
``Q.finite(x)`` is true if ``x`` is a number but neither an infinity
nor a ``NaN``. In other words, ``ask(Q.finite(x))`` is true for all
numerical ``x`` having a bounded absolute value.
Examples
========
>>> from sympy import Q, ask, S, oo, I, zoo
>>> from sympy.abc import x
>>> ask(Q.finite(oo))
False
>>> ask(Q.finite(-oo))
False
>>> ask(Q.finite(zoo))
False
>>> ask(Q.finite(1))
True
>>> ask(Q.finite(2 + 3*I))
True
>>> ask(Q.finite(x), Q.positive(x))
True
>>> print(ask(Q.finite(S.NaN)))
None
References
==========
.. [1] https://en.wikipedia.org/wiki/Finite
"""
name = 'finite'
handler = Dispatcher(
"FiniteHandler",
doc=("Handler for Q.finite. Test that an expression is bounded respect"
" to all its variables.")
)
class InfinitePredicate(Predicate):
"""
Infinite number predicate.
``Q.infinite(x)`` is true iff the absolute value of ``x`` is
infinity.
"""
# TODO: Add examples
name = 'infinite'
handler = Dispatcher(
"InfiniteHandler",
doc="""Handler for Q.infinite key."""
)
class PositiveInfinitePredicate(Predicate):
"""
Positive infinity predicate.
``Q.positive_infinite(x)`` is true iff ``x`` is positive infinity ``oo``.
"""
name = 'positive_infinite'
handler = Dispatcher("PositiveInfiniteHandler")
class NegativeInfinitePredicate(Predicate):
"""
Negative infinity predicate.
``Q.negative_infinite(x)`` is true iff ``x`` is negative infinity ``-oo``.
"""
name = 'negative_infinite'
handler = Dispatcher("NegativeInfiniteHandler")

View File

@ -0,0 +1,81 @@
from sympy.assumptions import Predicate, AppliedPredicate, Q
from sympy.core.relational import Eq, Ne, Gt, Lt, Ge, Le
from sympy.multipledispatch import Dispatcher
class CommutativePredicate(Predicate):
"""
Commutative predicate.
Explanation
===========
``ask(Q.commutative(x))`` is true iff ``x`` commutes with any other
object with respect to multiplication operation.
"""
# TODO: Add examples
name = 'commutative'
handler = Dispatcher("CommutativeHandler", doc="Handler for key 'commutative'.")
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le}
class IsTruePredicate(Predicate):
"""
Generic predicate.
Explanation
===========
``ask(Q.is_true(x))`` is true iff ``x`` is true. This only makes
sense if ``x`` is a boolean object.
Examples
========
>>> from sympy import ask, Q
>>> from sympy.abc import x, y
>>> ask(Q.is_true(True))
True
Wrapping another applied predicate just returns the applied predicate.
>>> Q.is_true(Q.even(x))
Q.even(x)
Wrapping binary relation classes in SymPy core returns applied binary
relational predicates.
>>> from sympy import Eq, Gt
>>> Q.is_true(Eq(x, y))
Q.eq(x, y)
>>> Q.is_true(Gt(x, y))
Q.gt(x, y)
Notes
=====
This class is designed to wrap the boolean objects so that they can
behave as if they are applied predicates. Consequently, wrapping another
applied predicate is unnecessary and thus it just returns the argument.
Also, binary relation classes in SymPy core have binary predicates to
represent themselves and thus wrapping them with ``Q.is_true`` converts them
to these applied predicates.
"""
name = 'is_true'
handler = Dispatcher(
"IsTrueHandler",
doc="Wrapper allowing to query the truth value of a boolean expression."
)
def __call__(self, arg):
# No need to wrap another predicate
if isinstance(arg, AppliedPredicate):
return arg
# Convert relational predicates instead of wrapping them
if getattr(arg, "is_Relational", False):
pred = binrelpreds[type(arg)]
return pred(*arg.args)
return super().__call__(arg)

View File

@ -0,0 +1,511 @@
from sympy.assumptions import Predicate
from sympy.multipledispatch import Dispatcher
class SquarePredicate(Predicate):
"""
Square matrix predicate.
Explanation
===========
``Q.square(x)`` is true iff ``x`` is a square matrix. A square matrix
is a matrix with the same number of rows and columns.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol, ZeroMatrix, Identity
>>> X = MatrixSymbol('X', 2, 2)
>>> Y = MatrixSymbol('X', 2, 3)
>>> ask(Q.square(X))
True
>>> ask(Q.square(Y))
False
>>> ask(Q.square(ZeroMatrix(3, 3)))
True
>>> ask(Q.square(Identity(3)))
True
References
==========
.. [1] https://en.wikipedia.org/wiki/Square_matrix
"""
name = 'square'
handler = Dispatcher("SquareHandler", doc="Handler for Q.square.")
class SymmetricPredicate(Predicate):
"""
Symmetric matrix predicate.
Explanation
===========
``Q.symmetric(x)`` is true iff ``x`` is a square matrix and is equal to
its transpose. Every square diagonal matrix is a symmetric matrix.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol
>>> X = MatrixSymbol('X', 2, 2)
>>> Y = MatrixSymbol('Y', 2, 3)
>>> Z = MatrixSymbol('Z', 2, 2)
>>> ask(Q.symmetric(X*Z), Q.symmetric(X) & Q.symmetric(Z))
True
>>> ask(Q.symmetric(X + Z), Q.symmetric(X) & Q.symmetric(Z))
True
>>> ask(Q.symmetric(Y))
False
References
==========
.. [1] https://en.wikipedia.org/wiki/Symmetric_matrix
"""
# TODO: Add handlers to make these keys work with
# actual matrices and add more examples in the docstring.
name = 'symmetric'
handler = Dispatcher("SymmetricHandler", doc="Handler for Q.symmetric.")
class InvertiblePredicate(Predicate):
"""
Invertible matrix predicate.
Explanation
===========
``Q.invertible(x)`` is true iff ``x`` is an invertible matrix.
A square matrix is called invertible only if its determinant is 0.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol
>>> X = MatrixSymbol('X', 2, 2)
>>> Y = MatrixSymbol('Y', 2, 3)
>>> Z = MatrixSymbol('Z', 2, 2)
>>> ask(Q.invertible(X*Y), Q.invertible(X))
False
>>> ask(Q.invertible(X*Z), Q.invertible(X) & Q.invertible(Z))
True
>>> ask(Q.invertible(X), Q.fullrank(X) & Q.square(X))
True
References
==========
.. [1] https://en.wikipedia.org/wiki/Invertible_matrix
"""
name = 'invertible'
handler = Dispatcher("InvertibleHandler", doc="Handler for Q.invertible.")
class OrthogonalPredicate(Predicate):
"""
Orthogonal matrix predicate.
Explanation
===========
``Q.orthogonal(x)`` is true iff ``x`` is an orthogonal matrix.
A square matrix ``M`` is an orthogonal matrix if it satisfies
``M^TM = MM^T = I`` where ``M^T`` is the transpose matrix of
``M`` and ``I`` is an identity matrix. Note that an orthogonal
matrix is necessarily invertible.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol, Identity
>>> X = MatrixSymbol('X', 2, 2)
>>> Y = MatrixSymbol('Y', 2, 3)
>>> Z = MatrixSymbol('Z', 2, 2)
>>> ask(Q.orthogonal(Y))
False
>>> ask(Q.orthogonal(X*Z*X), Q.orthogonal(X) & Q.orthogonal(Z))
True
>>> ask(Q.orthogonal(Identity(3)))
True
>>> ask(Q.invertible(X), Q.orthogonal(X))
True
References
==========
.. [1] https://en.wikipedia.org/wiki/Orthogonal_matrix
"""
name = 'orthogonal'
handler = Dispatcher("OrthogonalHandler", doc="Handler for key 'orthogonal'.")
class UnitaryPredicate(Predicate):
"""
Unitary matrix predicate.
Explanation
===========
``Q.unitary(x)`` is true iff ``x`` is a unitary matrix.
Unitary matrix is an analogue to orthogonal matrix. A square
matrix ``M`` with complex elements is unitary if :math:``M^TM = MM^T= I``
where :math:``M^T`` is the conjugate transpose matrix of ``M``.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol, Identity
>>> X = MatrixSymbol('X', 2, 2)
>>> Y = MatrixSymbol('Y', 2, 3)
>>> Z = MatrixSymbol('Z', 2, 2)
>>> ask(Q.unitary(Y))
False
>>> ask(Q.unitary(X*Z*X), Q.unitary(X) & Q.unitary(Z))
True
>>> ask(Q.unitary(Identity(3)))
True
References
==========
.. [1] https://en.wikipedia.org/wiki/Unitary_matrix
"""
name = 'unitary'
handler = Dispatcher("UnitaryHandler", doc="Handler for key 'unitary'.")
class FullRankPredicate(Predicate):
"""
Fullrank matrix predicate.
Explanation
===========
``Q.fullrank(x)`` is true iff ``x`` is a full rank matrix.
A matrix is full rank if all rows and columns of the matrix
are linearly independent. A square matrix is full rank iff
its determinant is nonzero.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol, ZeroMatrix, Identity
>>> X = MatrixSymbol('X', 2, 2)
>>> ask(Q.fullrank(X.T), Q.fullrank(X))
True
>>> ask(Q.fullrank(ZeroMatrix(3, 3)))
False
>>> ask(Q.fullrank(Identity(3)))
True
"""
name = 'fullrank'
handler = Dispatcher("FullRankHandler", doc="Handler for key 'fullrank'.")
class PositiveDefinitePredicate(Predicate):
r"""
Positive definite matrix predicate.
Explanation
===========
If $M$ is a :math:`n \times n` symmetric real matrix, it is said
to be positive definite if :math:`Z^TMZ` is positive for
every non-zero column vector $Z$ of $n$ real numbers.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol, Identity
>>> X = MatrixSymbol('X', 2, 2)
>>> Y = MatrixSymbol('Y', 2, 3)
>>> Z = MatrixSymbol('Z', 2, 2)
>>> ask(Q.positive_definite(Y))
False
>>> ask(Q.positive_definite(Identity(3)))
True
>>> ask(Q.positive_definite(X + Z), Q.positive_definite(X) &
... Q.positive_definite(Z))
True
References
==========
.. [1] https://en.wikipedia.org/wiki/Positive-definite_matrix
"""
name = "positive_definite"
handler = Dispatcher("PositiveDefiniteHandler", doc="Handler for key 'positive_definite'.")
class UpperTriangularPredicate(Predicate):
"""
Upper triangular matrix predicate.
Explanation
===========
A matrix $M$ is called upper triangular matrix if :math:`M_{ij}=0`
for :math:`i<j`.
Examples
========
>>> from sympy import Q, ask, ZeroMatrix, Identity
>>> ask(Q.upper_triangular(Identity(3)))
True
>>> ask(Q.upper_triangular(ZeroMatrix(3, 3)))
True
References
==========
.. [1] https://mathworld.wolfram.com/UpperTriangularMatrix.html
"""
name = "upper_triangular"
handler = Dispatcher("UpperTriangularHandler", doc="Handler for key 'upper_triangular'.")
class LowerTriangularPredicate(Predicate):
"""
Lower triangular matrix predicate.
Explanation
===========
A matrix $M$ is called lower triangular matrix if :math:`M_{ij}=0`
for :math:`i>j`.
Examples
========
>>> from sympy import Q, ask, ZeroMatrix, Identity
>>> ask(Q.lower_triangular(Identity(3)))
True
>>> ask(Q.lower_triangular(ZeroMatrix(3, 3)))
True
References
==========
.. [1] https://mathworld.wolfram.com/LowerTriangularMatrix.html
"""
name = "lower_triangular"
handler = Dispatcher("LowerTriangularHandler", doc="Handler for key 'lower_triangular'.")
class DiagonalPredicate(Predicate):
"""
Diagonal matrix predicate.
Explanation
===========
``Q.diagonal(x)`` is true iff ``x`` is a diagonal matrix. A diagonal
matrix is a matrix in which the entries outside the main diagonal
are all zero.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol, ZeroMatrix
>>> X = MatrixSymbol('X', 2, 2)
>>> ask(Q.diagonal(ZeroMatrix(3, 3)))
True
>>> ask(Q.diagonal(X), Q.lower_triangular(X) &
... Q.upper_triangular(X))
True
References
==========
.. [1] https://en.wikipedia.org/wiki/Diagonal_matrix
"""
name = "diagonal"
handler = Dispatcher("DiagonalHandler", doc="Handler for key 'diagonal'.")
class IntegerElementsPredicate(Predicate):
"""
Integer elements matrix predicate.
Explanation
===========
``Q.integer_elements(x)`` is true iff all the elements of ``x``
are integers.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol
>>> X = MatrixSymbol('X', 4, 4)
>>> ask(Q.integer(X[1, 2]), Q.integer_elements(X))
True
"""
name = "integer_elements"
handler = Dispatcher("IntegerElementsHandler", doc="Handler for key 'integer_elements'.")
class RealElementsPredicate(Predicate):
"""
Real elements matrix predicate.
Explanation
===========
``Q.real_elements(x)`` is true iff all the elements of ``x``
are real numbers.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol
>>> X = MatrixSymbol('X', 4, 4)
>>> ask(Q.real(X[1, 2]), Q.real_elements(X))
True
"""
name = "real_elements"
handler = Dispatcher("RealElementsHandler", doc="Handler for key 'real_elements'.")
class ComplexElementsPredicate(Predicate):
"""
Complex elements matrix predicate.
Explanation
===========
``Q.complex_elements(x)`` is true iff all the elements of ``x``
are complex numbers.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol
>>> X = MatrixSymbol('X', 4, 4)
>>> ask(Q.complex(X[1, 2]), Q.complex_elements(X))
True
>>> ask(Q.complex_elements(X), Q.integer_elements(X))
True
"""
name = "complex_elements"
handler = Dispatcher("ComplexElementsHandler", doc="Handler for key 'complex_elements'.")
class SingularPredicate(Predicate):
"""
Singular matrix predicate.
A matrix is singular iff the value of its determinant is 0.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol
>>> X = MatrixSymbol('X', 4, 4)
>>> ask(Q.singular(X), Q.invertible(X))
False
>>> ask(Q.singular(X), ~Q.invertible(X))
True
References
==========
.. [1] https://mathworld.wolfram.com/SingularMatrix.html
"""
name = "singular"
handler = Dispatcher("SingularHandler", doc="Predicate fore key 'singular'.")
class NormalPredicate(Predicate):
"""
Normal matrix predicate.
A matrix is normal if it commutes with its conjugate transpose.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol
>>> X = MatrixSymbol('X', 4, 4)
>>> ask(Q.normal(X), Q.unitary(X))
True
References
==========
.. [1] https://en.wikipedia.org/wiki/Normal_matrix
"""
name = "normal"
handler = Dispatcher("NormalHandler", doc="Predicate fore key 'normal'.")
class TriangularPredicate(Predicate):
"""
Triangular matrix predicate.
Explanation
===========
``Q.triangular(X)`` is true if ``X`` is one that is either lower
triangular or upper triangular.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol
>>> X = MatrixSymbol('X', 4, 4)
>>> ask(Q.triangular(X), Q.upper_triangular(X))
True
>>> ask(Q.triangular(X), Q.lower_triangular(X))
True
References
==========
.. [1] https://en.wikipedia.org/wiki/Triangular_matrix
"""
name = "triangular"
handler = Dispatcher("TriangularHandler", doc="Predicate fore key 'triangular'.")
class UnitTriangularPredicate(Predicate):
"""
Unit triangular matrix predicate.
Explanation
===========
A unit triangular matrix is a triangular matrix with 1s
on the diagonal.
Examples
========
>>> from sympy import Q, ask, MatrixSymbol
>>> X = MatrixSymbol('X', 4, 4)
>>> ask(Q.triangular(X), Q.unit_triangular(X))
True
"""
name = "unit_triangular"
handler = Dispatcher("UnitTriangularHandler", doc="Predicate fore key 'unit_triangular'.")

View File

@ -0,0 +1,126 @@
from sympy.assumptions import Predicate
from sympy.multipledispatch import Dispatcher
class PrimePredicate(Predicate):
"""
Prime number predicate.
Explanation
===========
``ask(Q.prime(x))`` is true iff ``x`` is a natural number greater
than 1 that has no positive divisors other than ``1`` and the
number itself.
Examples
========
>>> from sympy import Q, ask
>>> ask(Q.prime(0))
False
>>> ask(Q.prime(1))
False
>>> ask(Q.prime(2))
True
>>> ask(Q.prime(20))
False
>>> ask(Q.prime(-3))
False
"""
name = 'prime'
handler = Dispatcher(
"PrimeHandler",
doc=("Handler for key 'prime'. Test that an expression represents a prime"
" number. When the expression is an exact number, the result (when True)"
" is subject to the limitations of isprime() which is used to return the "
"result.")
)
class CompositePredicate(Predicate):
"""
Composite number predicate.
Explanation
===========
``ask(Q.composite(x))`` is true iff ``x`` is a positive integer and has
at least one positive divisor other than ``1`` and the number itself.
Examples
========
>>> from sympy import Q, ask
>>> ask(Q.composite(0))
False
>>> ask(Q.composite(1))
False
>>> ask(Q.composite(2))
False
>>> ask(Q.composite(20))
True
"""
name = 'composite'
handler = Dispatcher("CompositeHandler", doc="Handler for key 'composite'.")
class EvenPredicate(Predicate):
"""
Even number predicate.
Explanation
===========
``ask(Q.even(x))`` is true iff ``x`` belongs to the set of even
integers.
Examples
========
>>> from sympy import Q, ask, pi
>>> ask(Q.even(0))
True
>>> ask(Q.even(2))
True
>>> ask(Q.even(3))
False
>>> ask(Q.even(pi))
False
"""
name = 'even'
handler = Dispatcher("EvenHandler", doc="Handler for key 'even'.")
class OddPredicate(Predicate):
"""
Odd number predicate.
Explanation
===========
``ask(Q.odd(x))`` is true iff ``x`` belongs to the set of odd numbers.
Examples
========
>>> from sympy import Q, ask, pi
>>> ask(Q.odd(0))
False
>>> ask(Q.odd(2))
False
>>> ask(Q.odd(3))
True
>>> ask(Q.odd(pi))
False
"""
name = 'odd'
handler = Dispatcher(
"OddHandler",
doc=("Handler for key 'odd'. Test that an expression represents an odd"
" number.")
)

View File

@ -0,0 +1,390 @@
from sympy.assumptions import Predicate
from sympy.multipledispatch import Dispatcher
class NegativePredicate(Predicate):
r"""
Negative number predicate.
Explanation
===========
``Q.negative(x)`` is true iff ``x`` is a real number and :math:`x < 0`, that is,
it is in the interval :math:`(-\infty, 0)`. Note in particular that negative
infinity is not negative.
A few important facts about negative numbers:
- Note that ``Q.nonnegative`` and ``~Q.negative`` are *not* the same
thing. ``~Q.negative(x)`` simply means that ``x`` is not negative,
whereas ``Q.nonnegative(x)`` means that ``x`` is real and not
negative, i.e., ``Q.nonnegative(x)`` is logically equivalent to
``Q.zero(x) | Q.positive(x)``. So for example, ``~Q.negative(I)`` is
true, whereas ``Q.nonnegative(I)`` is false.
- See the documentation of ``Q.real`` for more information about
related facts.
Examples
========
>>> from sympy import Q, ask, symbols, I
>>> x = symbols('x')
>>> ask(Q.negative(x), Q.real(x) & ~Q.positive(x) & ~Q.zero(x))
True
>>> ask(Q.negative(-1))
True
>>> ask(Q.nonnegative(I))
False
>>> ask(~Q.negative(I))
True
"""
name = 'negative'
handler = Dispatcher(
"NegativeHandler",
doc=("Handler for Q.negative. Test that an expression is strictly less"
" than zero.")
)
class NonNegativePredicate(Predicate):
"""
Nonnegative real number predicate.
Explanation
===========
``ask(Q.nonnegative(x))`` is true iff ``x`` belongs to the set of
positive numbers including zero.
- Note that ``Q.nonnegative`` and ``~Q.negative`` are *not* the same
thing. ``~Q.negative(x)`` simply means that ``x`` is not negative,
whereas ``Q.nonnegative(x)`` means that ``x`` is real and not
negative, i.e., ``Q.nonnegative(x)`` is logically equivalent to
``Q.zero(x) | Q.positive(x)``. So for example, ``~Q.negative(I)`` is
true, whereas ``Q.nonnegative(I)`` is false.
Examples
========
>>> from sympy import Q, ask, I
>>> ask(Q.nonnegative(1))
True
>>> ask(Q.nonnegative(0))
True
>>> ask(Q.nonnegative(-1))
False
>>> ask(Q.nonnegative(I))
False
>>> ask(Q.nonnegative(-I))
False
"""
name = 'nonnegative'
handler = Dispatcher(
"NonNegativeHandler",
doc=("Handler for Q.nonnegative.")
)
class NonZeroPredicate(Predicate):
"""
Nonzero real number predicate.
Explanation
===========
``ask(Q.nonzero(x))`` is true iff ``x`` is real and ``x`` is not zero. Note in
particular that ``Q.nonzero(x)`` is false if ``x`` is not real. Use
``~Q.zero(x)`` if you want the negation of being zero without any real
assumptions.
A few important facts about nonzero numbers:
- ``Q.nonzero`` is logically equivalent to ``Q.positive | Q.negative``.
- See the documentation of ``Q.real`` for more information about
related facts.
Examples
========
>>> from sympy import Q, ask, symbols, I, oo
>>> x = symbols('x')
>>> print(ask(Q.nonzero(x), ~Q.zero(x)))
None
>>> ask(Q.nonzero(x), Q.positive(x))
True
>>> ask(Q.nonzero(x), Q.zero(x))
False
>>> ask(Q.nonzero(0))
False
>>> ask(Q.nonzero(I))
False
>>> ask(~Q.zero(I))
True
>>> ask(Q.nonzero(oo))
False
"""
name = 'nonzero'
handler = Dispatcher(
"NonZeroHandler",
doc=("Handler for key 'nonzero'. Test that an expression is not identically"
" zero.")
)
class ZeroPredicate(Predicate):
"""
Zero number predicate.
Explanation
===========
``ask(Q.zero(x))`` is true iff the value of ``x`` is zero.
Examples
========
>>> from sympy import ask, Q, oo, symbols
>>> x, y = symbols('x, y')
>>> ask(Q.zero(0))
True
>>> ask(Q.zero(1/oo))
True
>>> print(ask(Q.zero(0*oo)))
None
>>> ask(Q.zero(1))
False
>>> ask(Q.zero(x*y), Q.zero(x) | Q.zero(y))
True
"""
name = 'zero'
handler = Dispatcher(
"ZeroHandler",
doc="Handler for key 'zero'."
)
class NonPositivePredicate(Predicate):
"""
Nonpositive real number predicate.
Explanation
===========
``ask(Q.nonpositive(x))`` is true iff ``x`` belongs to the set of
negative numbers including zero.
- Note that ``Q.nonpositive`` and ``~Q.positive`` are *not* the same
thing. ``~Q.positive(x)`` simply means that ``x`` is not positive,
whereas ``Q.nonpositive(x)`` means that ``x`` is real and not
positive, i.e., ``Q.nonpositive(x)`` is logically equivalent to
`Q.negative(x) | Q.zero(x)``. So for example, ``~Q.positive(I)`` is
true, whereas ``Q.nonpositive(I)`` is false.
Examples
========
>>> from sympy import Q, ask, I
>>> ask(Q.nonpositive(-1))
True
>>> ask(Q.nonpositive(0))
True
>>> ask(Q.nonpositive(1))
False
>>> ask(Q.nonpositive(I))
False
>>> ask(Q.nonpositive(-I))
False
"""
name = 'nonpositive'
handler = Dispatcher(
"NonPositiveHandler",
doc="Handler for key 'nonpositive'."
)
class PositivePredicate(Predicate):
r"""
Positive real number predicate.
Explanation
===========
``Q.positive(x)`` is true iff ``x`` is real and `x > 0`, that is if ``x``
is in the interval `(0, \infty)`. In particular, infinity is not
positive.
A few important facts about positive numbers:
- Note that ``Q.nonpositive`` and ``~Q.positive`` are *not* the same
thing. ``~Q.positive(x)`` simply means that ``x`` is not positive,
whereas ``Q.nonpositive(x)`` means that ``x`` is real and not
positive, i.e., ``Q.nonpositive(x)`` is logically equivalent to
`Q.negative(x) | Q.zero(x)``. So for example, ``~Q.positive(I)`` is
true, whereas ``Q.nonpositive(I)`` is false.
- See the documentation of ``Q.real`` for more information about
related facts.
Examples
========
>>> from sympy import Q, ask, symbols, I
>>> x = symbols('x')
>>> ask(Q.positive(x), Q.real(x) & ~Q.negative(x) & ~Q.zero(x))
True
>>> ask(Q.positive(1))
True
>>> ask(Q.nonpositive(I))
False
>>> ask(~Q.positive(I))
True
"""
name = 'positive'
handler = Dispatcher(
"PositiveHandler",
doc=("Handler for key 'positive'. Test that an expression is strictly"
" greater than zero.")
)
class ExtendedPositivePredicate(Predicate):
r"""
Positive extended real number predicate.
Explanation
===========
``Q.extended_positive(x)`` is true iff ``x`` is extended real and
`x > 0`, that is if ``x`` is in the interval `(0, \infty]`.
Examples
========
>>> from sympy import ask, I, oo, Q
>>> ask(Q.extended_positive(1))
True
>>> ask(Q.extended_positive(oo))
True
>>> ask(Q.extended_positive(I))
False
"""
name = 'extended_positive'
handler = Dispatcher("ExtendedPositiveHandler")
class ExtendedNegativePredicate(Predicate):
r"""
Negative extended real number predicate.
Explanation
===========
``Q.extended_negative(x)`` is true iff ``x`` is extended real and
`x < 0`, that is if ``x`` is in the interval `[-\infty, 0)`.
Examples
========
>>> from sympy import ask, I, oo, Q
>>> ask(Q.extended_negative(-1))
True
>>> ask(Q.extended_negative(-oo))
True
>>> ask(Q.extended_negative(-I))
False
"""
name = 'extended_negative'
handler = Dispatcher("ExtendedNegativeHandler")
class ExtendedNonZeroPredicate(Predicate):
"""
Nonzero extended real number predicate.
Explanation
===========
``ask(Q.extended_nonzero(x))`` is true iff ``x`` is extended real and
``x`` is not zero.
Examples
========
>>> from sympy import ask, I, oo, Q
>>> ask(Q.extended_nonzero(-1))
True
>>> ask(Q.extended_nonzero(oo))
True
>>> ask(Q.extended_nonzero(I))
False
"""
name = 'extended_nonzero'
handler = Dispatcher("ExtendedNonZeroHandler")
class ExtendedNonPositivePredicate(Predicate):
"""
Nonpositive extended real number predicate.
Explanation
===========
``ask(Q.extended_nonpositive(x))`` is true iff ``x`` is extended real and
``x`` is not positive.
Examples
========
>>> from sympy import ask, I, oo, Q
>>> ask(Q.extended_nonpositive(-1))
True
>>> ask(Q.extended_nonpositive(oo))
False
>>> ask(Q.extended_nonpositive(0))
True
>>> ask(Q.extended_nonpositive(I))
False
"""
name = 'extended_nonpositive'
handler = Dispatcher("ExtendedNonPositiveHandler")
class ExtendedNonNegativePredicate(Predicate):
"""
Nonnegative extended real number predicate.
Explanation
===========
``ask(Q.extended_nonnegative(x))`` is true iff ``x`` is extended real and
``x`` is not negative.
Examples
========
>>> from sympy import ask, I, oo, Q
>>> ask(Q.extended_nonnegative(-1))
False
>>> ask(Q.extended_nonnegative(oo))
True
>>> ask(Q.extended_nonnegative(0))
True
>>> ask(Q.extended_nonnegative(I))
False
"""
name = 'extended_nonnegative'
handler = Dispatcher("ExtendedNonNegativeHandler")

View File

@ -0,0 +1,399 @@
from sympy.assumptions import Predicate
from sympy.multipledispatch import Dispatcher
class IntegerPredicate(Predicate):
"""
Integer predicate.
Explanation
===========
``Q.integer(x)`` is true iff ``x`` belongs to the set of integer
numbers.
Examples
========
>>> from sympy import Q, ask, S
>>> ask(Q.integer(5))
True
>>> ask(Q.integer(S(1)/2))
False
References
==========
.. [1] https://en.wikipedia.org/wiki/Integer
"""
name = 'integer'
handler = Dispatcher(
"IntegerHandler",
doc=("Handler for Q.integer.\n\n"
"Test that an expression belongs to the field of integer numbers.")
)
class NonIntegerPredicate(Predicate):
"""
Non-integer extended real predicate.
"""
name = 'noninteger'
handler = Dispatcher(
"NonIntegerHandler",
doc=("Handler for Q.noninteger.\n\n"
"Test that an expression is a non-integer extended real number.")
)
class RationalPredicate(Predicate):
"""
Rational number predicate.
Explanation
===========
``Q.rational(x)`` is true iff ``x`` belongs to the set of
rational numbers.
Examples
========
>>> from sympy import ask, Q, pi, S
>>> ask(Q.rational(0))
True
>>> ask(Q.rational(S(1)/2))
True
>>> ask(Q.rational(pi))
False
References
==========
.. [1] https://en.wikipedia.org/wiki/Rational_number
"""
name = 'rational'
handler = Dispatcher(
"RationalHandler",
doc=("Handler for Q.rational.\n\n"
"Test that an expression belongs to the field of rational numbers.")
)
class IrrationalPredicate(Predicate):
"""
Irrational number predicate.
Explanation
===========
``Q.irrational(x)`` is true iff ``x`` is any real number that
cannot be expressed as a ratio of integers.
Examples
========
>>> from sympy import ask, Q, pi, S, I
>>> ask(Q.irrational(0))
False
>>> ask(Q.irrational(S(1)/2))
False
>>> ask(Q.irrational(pi))
True
>>> ask(Q.irrational(I))
False
References
==========
.. [1] https://en.wikipedia.org/wiki/Irrational_number
"""
name = 'irrational'
handler = Dispatcher(
"IrrationalHandler",
doc=("Handler for Q.irrational.\n\n"
"Test that an expression is irrational numbers.")
)
class RealPredicate(Predicate):
r"""
Real number predicate.
Explanation
===========
``Q.real(x)`` is true iff ``x`` is a real number, i.e., it is in the
interval `(-\infty, \infty)`. Note that, in particular the
infinities are not real. Use ``Q.extended_real`` if you want to
consider those as well.
A few important facts about reals:
- Every real number is positive, negative, or zero. Furthermore,
because these sets are pairwise disjoint, each real number is
exactly one of those three.
- Every real number is also complex.
- Every real number is finite.
- Every real number is either rational or irrational.
- Every real number is either algebraic or transcendental.
- The facts ``Q.negative``, ``Q.zero``, ``Q.positive``,
``Q.nonnegative``, ``Q.nonpositive``, ``Q.nonzero``,
``Q.integer``, ``Q.rational``, and ``Q.irrational`` all imply
``Q.real``, as do all facts that imply those facts.
- The facts ``Q.algebraic``, and ``Q.transcendental`` do not imply
``Q.real``; they imply ``Q.complex``. An algebraic or
transcendental number may or may not be real.
- The "non" facts (i.e., ``Q.nonnegative``, ``Q.nonzero``,
``Q.nonpositive`` and ``Q.noninteger``) are not equivalent to
not the fact, but rather, not the fact *and* ``Q.real``.
For example, ``Q.nonnegative`` means ``~Q.negative & Q.real``.
So for example, ``I`` is not nonnegative, nonzero, or
nonpositive.
Examples
========
>>> from sympy import Q, ask, symbols
>>> x = symbols('x')
>>> ask(Q.real(x), Q.positive(x))
True
>>> ask(Q.real(0))
True
References
==========
.. [1] https://en.wikipedia.org/wiki/Real_number
"""
name = 'real'
handler = Dispatcher(
"RealHandler",
doc=("Handler for Q.real.\n\n"
"Test that an expression belongs to the field of real numbers.")
)
class ExtendedRealPredicate(Predicate):
r"""
Extended real predicate.
Explanation
===========
``Q.extended_real(x)`` is true iff ``x`` is a real number or
`\{-\infty, \infty\}`.
See documentation of ``Q.real`` for more information about related
facts.
Examples
========
>>> from sympy import ask, Q, oo, I
>>> ask(Q.extended_real(1))
True
>>> ask(Q.extended_real(I))
False
>>> ask(Q.extended_real(oo))
True
"""
name = 'extended_real'
handler = Dispatcher(
"ExtendedRealHandler",
doc=("Handler for Q.extended_real.\n\n"
"Test that an expression belongs to the field of extended real\n"
"numbers, that is real numbers union {Infinity, -Infinity}.")
)
class HermitianPredicate(Predicate):
"""
Hermitian predicate.
Explanation
===========
``ask(Q.hermitian(x))`` is true iff ``x`` belongs to the set of
Hermitian operators.
References
==========
.. [1] https://mathworld.wolfram.com/HermitianOperator.html
"""
# TODO: Add examples
name = 'hermitian'
handler = Dispatcher(
"HermitianHandler",
doc=("Handler for Q.hermitian.\n\n"
"Test that an expression belongs to the field of Hermitian operators.")
)
class ComplexPredicate(Predicate):
"""
Complex number predicate.
Explanation
===========
``Q.complex(x)`` is true iff ``x`` belongs to the set of complex
numbers. Note that every complex number is finite.
Examples
========
>>> from sympy import Q, Symbol, ask, I, oo
>>> x = Symbol('x')
>>> ask(Q.complex(0))
True
>>> ask(Q.complex(2 + 3*I))
True
>>> ask(Q.complex(oo))
False
References
==========
.. [1] https://en.wikipedia.org/wiki/Complex_number
"""
name = 'complex'
handler = Dispatcher(
"ComplexHandler",
doc=("Handler for Q.complex.\n\n"
"Test that an expression belongs to the field of complex numbers.")
)
class ImaginaryPredicate(Predicate):
"""
Imaginary number predicate.
Explanation
===========
``Q.imaginary(x)`` is true iff ``x`` can be written as a real
number multiplied by the imaginary unit ``I``. Please note that ``0``
is not considered to be an imaginary number.
Examples
========
>>> from sympy import Q, ask, I
>>> ask(Q.imaginary(3*I))
True
>>> ask(Q.imaginary(2 + 3*I))
False
>>> ask(Q.imaginary(0))
False
References
==========
.. [1] https://en.wikipedia.org/wiki/Imaginary_number
"""
name = 'imaginary'
handler = Dispatcher(
"ImaginaryHandler",
doc=("Handler for Q.imaginary.\n\n"
"Test that an expression belongs to the field of imaginary numbers,\n"
"that is, numbers in the form x*I, where x is real.")
)
class AntihermitianPredicate(Predicate):
"""
Antihermitian predicate.
Explanation
===========
``Q.antihermitian(x)`` is true iff ``x`` belongs to the field of
antihermitian operators, i.e., operators in the form ``x*I``, where
``x`` is Hermitian.
References
==========
.. [1] https://mathworld.wolfram.com/HermitianOperator.html
"""
# TODO: Add examples
name = 'antihermitian'
handler = Dispatcher(
"AntiHermitianHandler",
doc=("Handler for Q.antihermitian.\n\n"
"Test that an expression belongs to the field of anti-Hermitian\n"
"operators, that is, operators in the form x*I, where x is Hermitian.")
)
class AlgebraicPredicate(Predicate):
r"""
Algebraic number predicate.
Explanation
===========
``Q.algebraic(x)`` is true iff ``x`` belongs to the set of
algebraic numbers. ``x`` is algebraic if there is some polynomial
in ``p(x)\in \mathbb\{Q\}[x]`` such that ``p(x) = 0``.
Examples
========
>>> from sympy import ask, Q, sqrt, I, pi
>>> ask(Q.algebraic(sqrt(2)))
True
>>> ask(Q.algebraic(I))
True
>>> ask(Q.algebraic(pi))
False
References
==========
.. [1] https://en.wikipedia.org/wiki/Algebraic_number
"""
name = 'algebraic'
AlgebraicHandler = Dispatcher(
"AlgebraicHandler",
doc="""Handler for Q.algebraic key."""
)
class TranscendentalPredicate(Predicate):
"""
Transcedental number predicate.
Explanation
===========
``Q.transcendental(x)`` is true iff ``x`` belongs to the set of
transcendental numbers. A transcendental number is a real
or complex number that is not algebraic.
"""
# TODO: Add examples
name = 'transcendental'
handler = Dispatcher(
"Transcendental",
doc="""Handler for Q.transcendental key."""
)