You can also pull from my repo, branch master:
git pull http://fseoane.net/git/sympy.git master
I also squashed together two test cases that had the same name
(and thus probably only one was getting run)
---
sympy/core/basic.py | 8 +++++---
sympy/core/tests/test_basic.py | 23 +++++++++++------------
2 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/sympy/core/basic.py b/sympy/core/basic.py
index b20ed06..35d39c4 100644
--- a/sympy/core/basic.py
+++ b/sympy/core/basic.py
@@ -822,11 +822,13 @@ def is_number(self):
True
"""
+ result = False
for obj in self.iter_basic_args():
- if not obj.is_number:
+ if obj.is_number:
+ result = True
+ else:
return False
- else:
- return True
+ return result
@property
def func(self):
diff --git a/sympy/core/tests/test_basic.py b/sympy/core/tests/test_basic.py
index 7c51702..238f144 100644
--- a/sympy/core/tests/test_basic.py
+++ b/sympy/core/tests/test_basic.py
@@ -325,13 +325,6 @@ def test_doit():
assert (2*Integral(x, x)).doit() == x**2
-def test_is_number():
- assert Rational(8).is_number
- assert not x.is_number
- assert (8+log(2)).is_number
- assert not (8+log(2)+x).is_number
- assert (1+x**2/x-x).is_number
-
def test_attribute_error():
raises(AttributeError, "x.cos()")
raises(AttributeError, "x.sin()")
@@ -525,19 +518,25 @@ def test_is_number():
assert Real(3.14).is_number == True
assert Integer(737).is_number == True
assert Rational(3, 2).is_number == True
-
+ assert Rational(8).is_number == True
assert x.is_number == False
assert (2*x).is_number == False
-
assert (x + y).is_number == False
-
assert log(2).is_number == True
assert log(x).is_number == False
-
assert (2 + log(2)).is_number == True
+ assert (8+log(2)).is_number == True
assert (2 + log(x)).is_number == False
-
+ assert (8+log(2)+x).is_number == False
assert (2*g).is_number == False
+ assert (1+x**2/x-x).is_number == True
+
+ # test extensibility of .is_number
+ # on subinstances of Basic
+ class A(Basic):
+ pass
+ a = A()
+ assert a.is_number == False
# TODO write more tests for as_coeff_factors
--
1.6.2.2
diff --git a/sympy/__init__.py b/sympy/__init__.py
index 3be16a4..c813490 100644
--- a/sympy/__init__.py
+++ b/sympy/__init__.py
@@ -21,7 +21,7 @@ def __sympy_debug():
import symbol as stdlib_symbol
from sympy.core import *
-
+from assumptions import *
from polys import *
from series import *
from functions import *
diff --git a/sympy/assumptions/__init__.py b/sympy/assumptions/__init__.py
new file mode 100644
index 0000000..bdd47c2
--- /dev/null
+++ b/sympy/assumptions/__init__.py
@@ -0,0 +1,2 @@
+from assume import Assume, register_global_assumptions, list_global_assumptions, \
+ remove_global_assumptions, clean_global_assumptions
diff --git a/sympy/assumptions/assume.py b/sympy/assumptions/assume.py
new file mode 100644
index 0000000..4069ee9
--- /dev/null
+++ b/sympy/assumptions/assume.py
@@ -0,0 +1,97 @@
+# doctests are disabled because of issue #1521
+from sympy.core import Basic, Symbol
+from sympy.core.relational import Relational
+
+__global_assumptions = []
+
+def register_global_assumptions(*assump):
+ """Register an assumption as global
+
+ Examples:
+# >>> from sympy import *
+# >>> list_global()
+# []
+# >>> x = Symbol('x')
+# >>> register_global(Assume(x, real=True))
+# True
+# >>> list_global()
+# [Assume(x, real=True)]
+
+ You can undo this calling remove_global
+ """
+ __global_assumptions.extend(assump)
+
+def list_global_assumptions():
+ """List all global assumptions"""
+ return __global_assumptions[:] # make a copy
+
+def remove_global_assumptions(*assump):
+ """Remove a global assumption. If argument is not
+ a global assumption, it will raise ValueError
+ """
+ for assumption in assump:
+ __global_assumptions.remove(assumption)
+
+def clean_global_assumptions():
+ """Remove all global assumptions"""
+ global __global_assumptions
+ __global_assumptions = []
+
+class Assume(Basic):
+ """New-style assumptions
+
+# >>> from sympy import Symbol, Assume
+# >>> x = Symbol('x')
+# >>> Assume(x, integer=True)
+# Assume( x, integer = True )
+# >>> Assume(x, integer=False)
+# Assume( x, integer = False )
+# >>> Assume( x > 1 )
+# Assume( x > 1, relational = True)
+ """
+
+ def __init__(self, expr, *args, **kwargs):
+ if isinstance(expr, Symbol):
+ key, value = kwargs.popitem()
+ elif isinstance(expr, Relational):
+ key, value = 'relational', True
+ if kwargs:
+ raise ValueError('Wrong set of arguments')
+ self._args = (expr, key, value)
+
+ is_Atom = True # do not attempt to decompose this
+
+ @property
+ def expr(self):
+ return self._args[0]
+
+ @property
+ def key(self):
+ return self._args[1]
+
+ @property
+ def value(self):
+ return self._args[2]
+
+ def __eq__(self, other):
+ if type(other) == Assume:
+ return self._args == other._args
+ return False
+
+def eliminate_assume(expr, symbol=None):
+ """
+ Will convert an expression with assumptions to an equivalent with all assumptions
+ replaced by symbols
+ Assume(x, integer=True) --> integer
+ Assume(x, integer=False) --> ~integer
+ """
+ if type(expr) == Assume:
+ if symbol is not None:
+ if not expr.expr.has(symbol): return
+ if expr.value: return Symbol(expr.key)
+ return ~Symbol(expr.key)
+ args = []
+ for a in expr.args:
+ args.append(eliminate_assume(a))
+ return type(expr)(*args)
+
diff --git a/sympy/assumptions/tests/test_assumptions_2.py b/sympy/assumptions/tests/test_assumptions_2.py
new file mode 100644
index 0000000..d95162f
--- /dev/null
+++ b/sympy/assumptions/tests/test_assumptions_2.py
@@ -0,0 +1,58 @@
+"""rename this to test_assumptions.py when the old assumptions system is deleted"""
+from sympy.core import symbols
+from sympy.assumptions import Assume, register_global_assumptions, \
+ list_global_assumptions, remove_global_assumptions, clean_global_assumptions
+from sympy.assumptions.assume import eliminate_assume
+from sympy.printing import pretty
+
+def test_assume():
+ x = symbols('x')
+ assump = Assume(x, integer=True)
+ assert assump.expr == x
+ assert assump.key == 'integer'
+ assert assump.value == True
+
+def test_False():
+ """Test Assume object with False keys"""
+ x = symbols('x')
+ assump = Assume(x, integer=False)
+ assert assump.expr == x
+ assert assump.key == 'integer'
+ assert assump.value == False
+
+def test_equal():
+ """Test for equality"""
+ x = symbols('x')
+ assert Assume(x, positive=True) == Assume(x, positive=True)
+ assert Assume(x, positive=True) != Assume(x, positive=False)
+ assert Assume(x, positive=False) == Assume(x, positive=False)
+
+def test_pretty():
+ x = symbols('x')
+ assert pretty(Assume(x, positive=True)) == 'Assume(x, positive=True)'
+
+def test_eliminate_assumptions():
+ a, b, x, y = symbols('abxy')
+ assert eliminate_assume(Assume(x, a=True)) == a
+ assert eliminate_assume(Assume(x, a=True), symbol=x) == a
+ assert eliminate_assume(Assume(x, a=True), symbol=y) == None
+ assert eliminate_assume(Assume(x, a=False)) == ~a
+ assert eliminate_assume(Assume(x, a=False), symbol=y) == None
+ assert eliminate_assume(Assume(x, a=True) | Assume(x, b=True)) == a | b
+ assert eliminate_assume(Assume(x, a=True) | Assume(x, b=False)) == a | ~b
+
+def test_global():
+ """Test for global assumptions"""
+ x, y = symbols('x y')
+ register_global_assumptions(Assume(x>0))
+ assert Assume(x>0) in list_global_assumptions()
+ remove_global_assumptions(Assume(x>0))
+ assert (Assume(x>0) in list_global_assumptions()) == False
+
+ # same with multiple of assumptions
+ register_global_assumptions(Assume(x>0), Assume(y>0))
+ assert Assume(x>0) in list_global_assumptions()
+ assert Assume(y>0) in list_global_assumptions()
+ clean_global_assumptions()
+ assert (Assume(x>0) in list_global_assumptions()) == False
+ assert (Assume(y>0) in list_global_assumptions()) == False
diff --git a/sympy/printing/pretty/pretty.py b/sympy/printing/pretty/pretty.py
index 19ffff2..6d7f4da 100644
--- a/sympy/printing/pretty/pretty.py
+++ b/sympy/printing/pretty/pretty.py
@@ -56,6 +56,9 @@ def _print_Atom(self, e):
except KeyError:
return self.emptyPrinter(e)
+ def _print_Assume(self, e):
+ return prettyForm("Assume(%s, %s=%s)" % (e.expr, e.key, e.value))
+
# Infinity inherits from Rational, so we have to override _print_XXX order
_print_Infinity = _print_Atom
_print_NegativeInfinity = _print_Atom
--
1.6.2.2
1. Can't assume relations. It is not possible to specify relations between different
objects. For example, you can assume that x>0 and y>0, but you can't
assume x>y. You also can't assume facts on expressions, only on symbols.
2. Verbose code splitted across multiple classes. Each class must override
query methods (.is_*).
3. Extensibility. To add new assumptions you have to add code to
the core
The assumption system implemented in this series of patches relies on these
principles:
1. Assumptions are separate from objects. Assumptions are instances of Assume, which is
a class that holds a reference to the expression and to the 'key' (what it assumes)
2. Queries out of the core. No more .is_* methods. Specific queries are implemented
as subclasses of QueryHandler, and the query function calls the appropriate
subclass of QueryHandler
query -> QueryHandler -> QueryNegativeHandler
-> QueryIntegerHandler
-> QueryBoundedHandler
...
That way, creating new queries is a matter of subclassing QueryHandler and override
the apropriate methods.
3. Extensibility. This system can be extended with new keys and new types. See last tests
for examples on this.
---
sympy/__init__.py | 1 +
sympy/queries/__init__.py | 162 ++++++
sympy/queries/handlers/__init__.py | 40 ++
sympy/queries/handlers/calculus.py | 145 ++++++
sympy/queries/handlers/ntheory.py | 207 ++++++++
sympy/queries/handlers/order.py | 173 +++++++
sympy/queries/handlers/sets.py | 433 ++++++++++++++++
sympy/queries/tests/test_query.py | 979 ++++++++++++++++++++++++++++++++++++
8 files changed, 2140 insertions(+), 0 deletions(-)
create mode 100644 sympy/queries/__init__.py
create mode 100644 sympy/queries/handlers/__init__.py
create mode 100644 sympy/queries/handlers/calculus.py
create mode 100644 sympy/queries/handlers/ntheory.py
create mode 100644 sympy/queries/handlers/order.py
create mode 100644 sympy/queries/handlers/sets.py
create mode 100644 sympy/queries/tests/test_query.py
diff --git a/sympy/__init__.py b/sympy/__init__.py
index c813490..fbec483 100644
--- a/sympy/__init__.py
+++ b/sympy/__init__.py
@@ -40,6 +40,7 @@ def __sympy_debug():
pprint_try_use_unicode, print_gtk, print_tree
from printing import ccode, latex, preview, view, pngview, pdfview, dviview
from printing import python, print_python, srepr, sstr, sstrrepr
+from queries import query
evalf._create_evalf_table()
diff --git a/sympy/queries/__init__.py b/sympy/queries/__init__.py
new file mode 100644
index 0000000..49ee205
--- /dev/null
+++ b/sympy/queries/__init__.py
@@ -0,0 +1,162 @@
+import inspect
+from sympy.core import Symbol, sympify
+from sympy.utilities.source import get_class
+from sympy.assumptions import list_global_assumptions
+from sympy.assumptions.assume import eliminate_assume
+from sympy.logic.boolalg import to_cnf, conjuncts, \
+ compile_rule, Equivalent, And
+from sympy.logic.algorithms.dpll import dpll_satisfiable
+
+def query(expr, *args, **kwargs):
+ """
+ Method for inferring properties about objects.
+
+ Syntax
+
+ * query(expression, key=boolean)
+
+ * query(expression, key=boolean, assumptions=assumptions)
+
+ where expression is any SymPy expression, and boolean is any
+ boolean value (True/False). key can have any value listed in
+ handlers_dict.keys()
+
+ It accepts an optional keyword assumptions, a boolean expression
+ containing assumptions satisfied by expr.
+
+ Examples
+ >>> from sympy import *
+ >>> x, y = symbols('x y')
+ >>> query(pi, rational=True)
+ False
+ >>> query(x*y, even=True, assumptions=Assume(x, even=True) & Assume(y, integer=True))
+ True
+ >>> query(x*y, prime=True, assumptions=Assume(x, integer=True) & Assume(y, integer=True))
+ False
+
+ Remarks
+ Relations in assumptions are not implemented (yet), so the following
+ will not give a meaningful result.
+ #>>> query(x, positive=True, Assume(x>0))
+ It is however a work in progress and should be available before
+ the official release
+ """
+ assumptions = kwargs.pop('assumptions', [])
+ if assumptions and not hasattr(assumptions, '__iter__'):
+ assumptions = conjuncts(to_cnf(assumptions))
+ # Warning: global assumptions are expected to be in CNF
+ assumptions.extend(list_global_assumptions())
+
+ key, value = kwargs.popitem()
+ expr = sympify(expr)
+ if kwargs:
+ # split multiple queries
+ k = {key: value}
+ return query(expr, assumptions=assumptions, **k) and \
+ query(expr, assumptions=assumptions, **kwargs)
+ if not value: # only True queries from now on (e.g. prime=True)
+ k = {key: True}
+ result = query(expr, assumptions=assumptions, **k)
+ if result is not None:
+ return not result
+ return
+
+ # direct resolution method, no logic
+ resolutors = []
+ for handler in handlers_dict[key]:
+ resolutors.append( get_class(handler) )
+ res, _res = None, None
+ mro = inspect.getmro(type(expr))
+ for handler in resolutors:
+ for subclass in mro:
+ if hasattr(handler, subclass.__name__):
+ res = getattr(handler, subclass.__name__)(expr, assumptions)
+ if _res is None: _res = res
+ elif _res != res: raise ValueError, 'incompatible resolutors'
+ break
+ if res is not None:
+ return res
+
+ # use logic inference
+ if not expr.is_Atom: return
+ clauses = []
+ for k, values in known_facts_dict.iteritems():
+ for v in values:
+ clauses.append(Equivalent(compile_rule(k), compile_rule(v)))
+ result = None
+
+ # add assumptions to the knowledge base
+ for assump in assumptions:
+ clauses.append(eliminate_assume(assump, symbol=expr))
+
+ clauses.append(Symbol(key))
+ # TODO: call dpll and avoid creating this object
+ if not dpll_satisfiable(And(*clauses)):
+ return False
+ clauses[-1] = ~clauses[-1]
+ if not dpll_satisfiable(And(*clauses)):
+ # if the negation is satisfiable, it is entailed
+ return True
+ clauses.pop(-1)
+
+
+def register_handler(key, handler):
+ """Register a handler in the query system. key must be a string and handler a
+ class inheriting from QueryHandler.
+
+ >>> from sympy.queries.handlers import QueryHandler
+ >>> class MersenneHandler(QueryHandler):
+ ... # Mersenne numbers are in the form 2**n + 1, n integer
+ ... @staticmethod
+ ... def Integer(expr, assumptions):
+ ... import math
+ ... return query(math.log(expr + 1, 2), integer=True)
+ >>> register_handler('mersenne', MersenneHandler)
+ >>> query(7, mersenne=True)
+ True
+ """
+ if key in handlers_dict:
+ handlers_dict[key].append(handler)
+ else:
+ handlers_dict.update({key: [handler]})
+
+def remove_handler(key, handler):
+ """Removes a handler from the query system. Same syntax as register_handler"""
+ handlers_dict[key].remove(handler)
+
+# query_dict tells us what query handler we should use
+# for a particular key
+handlers_dict = {
+ 'bounded' : ['sympy.queries.handlers.calculus.QueryBoundedHandler'],
+ 'commutative' : ['sympy.queries.handlers.QueryCommutativeHandler'],
+ 'complex' : ['sympy.queries.handlers.sets.QueryComplexHandler'],
+ 'composite' : ['sympy.queries.handlers.ntheory.QueryCompositeHandler'],
+ 'even' : ['sympy.queries.handlers.ntheory.QueryEvenHandler'],
+ 'extended_real' : ['sympy.queries.handlers.sets.QueryExtendedRealHandler'],
+ 'imaginary' : ['sympy.queries.handlers.sets.QueryImaginaryHandler'],
+ 'infinitesimal' : ['sympy.queries.handlers.calculus.QueryInfinitesimalHandler'],
+ 'integer' : ['sympy.queries.handlers.sets.QueryIntegerHandler'],
+ 'irrational' : ['sympy.queries.handlers.sets.QueryIrrationalHandler'],
+ 'rational' : ['sympy.queries.handlers.sets.QueryRationalHandler'],
+ 'negative' : ['sympy.queries.handlers.order.QueryNegativeHandler'],
+ 'positive' : ['sympy.queries.handlers.order.QueryPositiveHandler'],
+ 'prime' : ['sympy.queries.handlers.ntheory.QueryPrimeHandler'],
+ 'real' : ['sympy.queries.handlers.sets.QueryRealHandler'],
+ 'odd' : ['sympy.queries.handlers.ntheory.QueryOddHandler'],
+ 'zero' : ['sympy.queries.handlers.order.QueryZeroHandler']
+}
+
+known_facts_dict = {
+ 'complex' : ['real | complex_number_re_0'],
+ 'even' : ['integer & ~odd'],
+ 'extended_real' : ['real | infinity'],
+ 'odd' : ['integer & ~even'],
+ 'prime' : ['integer & positive & ~composite'],
+ 'integer' : ['rational & denominator_one'],
+ 'imaginary' : ['complex & ~real'],
+ 'negative' : ['real & ~positive & ~zero'],
+ 'positive' : ['real & ~negative & ~zero'],
+ 'rational' : ['real & ~irrational'],
+ 'real' : ['rational | irrational' ],
+ 'zero' : ['real & ~positive & ~negative']
+}
diff --git a/sympy/queries/handlers/__init__.py b/sympy/queries/handlers/__init__.py
new file mode 100644
index 0000000..ba9bb89
--- /dev/null
+++ b/sympy/queries/handlers/__init__.py
@@ -0,0 +1,40 @@
+from sympy.queries import query
+
+class QueryHandler(object):
+ """Base class that all Query Handlers must inherit"""
+ pass
+
+class CommonHandler(QueryHandler):
+ """Defines some useful methods common to most Handlers """
+
+ @staticmethod
+ def NaN(expr, assumptions):
+ return False
+
+class QueryCommutativeHandler(CommonHandler):
+ """
+ Handler for key 'commutative'
+ """
+
+ @staticmethod
+ def Symbol(expr, assumptions):
+ """Objects are expected to be commutative unless otherwise stated"""
+ for assump in assumptions:
+ if assump.expr == expr and assump.key == 'commutative':
+ return assump.value
+ return True
+
+ @staticmethod
+ def Basic(expr, assumptions):
+ for arg in expr.args:
+ if not query(arg, commutative=True, assumptions=assumptions):
+ return False
+ return True
+
+ @staticmethod
+ def Number(expr, assumptions):
+ return True
+
+ @staticmethod
+ def NaN(expr, assumptions):
+ return True
diff --git a/sympy/queries/handlers/calculus.py b/sympy/queries/handlers/calculus.py
new file mode 100644
index 0000000..4885aee
--- /dev/null
+++ b/sympy/queries/handlers/calculus.py
@@ -0,0 +1,145 @@
+"""
+This module contains query handlers resposible for calculus queries:
+infinitesimal, bounded, etc.
+"""
+from sympy.queries import query
+from sympy.queries.handlers import CommonHandler
+
+class QueryInfinitesimalHandler(CommonHandler):
+ """
+ Handler for key 'infinitesimal'
+ Test that a given expression is equivalent to an infinitesimal
+ number
+ """
+
+ @staticmethod
+ def _number(expr, assumptions):
+ # helper method
+ return expr.evalf() == 0
+
+ @staticmethod
+ def Basic(expr, assumptions):
+ if expr.is_number:
+ return QueryInfinitesimalHandler._number(expr, assumptions)
+
+ @staticmethod
+ def Mul(expr, assumptions):
+ """
+ Infinitesimal*Bounded -> Infinitesimal
+ """
+ if expr.is_number:
+ return QueryInfinitesimalHandler._number(expr, assumptions)
+ result = False
+ for arg in expr.args:
+ if query(arg, infinitesimal=True, assumptions=assumptions):
+ result = True
+ elif query(arg, bounded=True, assumptions=assumptions):
+ continue
+ else: break
+ else:
+ return result
+
+ Add, Pow = Mul, Mul
+
+ @staticmethod
+ def Number(expr, assumptions):
+ return expr == 0
+
+ NumberSymbol = Number
+
+ @staticmethod
+ def ImaginaryUnit(expr, assumptions):
+ return False
+
+
+class QueryBoundedHandler(CommonHandler):
+ """
+ Handler for key 'bounded'
+ Test that an expression is bounded respect to all its variables
+ """
+
+ @staticmethod
+ def Add(expr, assumptions):
+ """
+ Bounded + Bounded -> Bounded
+ Unbounded + Bounded -> Unbounded
+ Unbounded + Unbounded -> ?
+ """
+ result = True
+ for arg in expr.args:
+ _bounded = query(arg, bounded=True, assumptions=assumptions)
+ if _bounded: continue
+ elif _bounded is None: return
+ elif _bounded is False:
+ if result: result = False
+ else: return
+ return result
+
+ Mul = Add
+
+ @staticmethod
+ def Pow(expr, assumptions):
+ """
+ Unbounded ** Whatever -> Unbounded
+ Bounded ** Unbounded -> Unbounded if base > 1
+ Bounded ** Unbounded -> Unbounded if base < 1
+ """
+ base_bounded = query(expr.base, bounded=True, assumptions=assumptions)
+ if not base_bounded: return base_bounded
+ if query(expr.exp, bounded=True, assumptions=assumptions) \
+ and base_bounded: return True
+ if base_bounded and expr.base.is_number:
+ # We need to implement relations for this
+ if abs(expr.base) > 1:
+ return False
+ return True
+
+ @staticmethod
+ def Symbol(expr, assumptions):
+ if query(expr, zero=True, assumptions=assumptions):
+ return True
+ for assump in assumptions:
+ if assump.key == 'bounded' and assump.expr == expr:
+ return assump.value
+ return False
+
+ @staticmethod
+ def log(expr, assumptions):
+ return query(expr.args[0], bounded=True, assumptions=assumptions)
+
+ exp = log
+
+ @staticmethod
+ def sin(expr, assumptions):
+ return True
+
+ cos = sin
+
+ @staticmethod
+ def Number(expr, assumptions):
+ return True
+
+ @staticmethod
+ def Infinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def NegativeInfinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def Pi(expr, assumptions):
+ return True
+
+ @staticmethod
+ def Exp1(expr, assumptions):
+ return True
+
+ @staticmethod
+ def ImaginaryUnit(expr, assumptions):
+ return True
+
+ @staticmethod
+ def sign(expr, assumptions):
+ return True
+
diff --git a/sympy/queries/handlers/ntheory.py b/sympy/queries/handlers/ntheory.py
new file mode 100644
index 0000000..196f2aa
--- /dev/null
+++ b/sympy/queries/handlers/ntheory.py
@@ -0,0 +1,207 @@
+"""
+Handlers for keys related to number theory: prime, even, odd, etc.
+"""
+from sympy.queries import query
+from sympy.queries.handlers import CommonHandler
+from sympy.ntheory import isprime
+
+class QueryPrimeHandler(CommonHandler):
+ """
+ Handler for key 'prime'
+ Test that an expression represents a prime number
+ """
+
+ @staticmethod
+ def _number(expr, assumptions):
+ # helper method
+ if (expr.as_real_imag()[1] == 0) and int(expr.evalf()) == expr:
+ return isprime(expr.evalf(1))
+ return False
+
+ @staticmethod
+ def Basic(expr, assumptions):
+ # Just use int(expr) once
+ # http://code.google.com/p/sympy/issues/detail?id=1462
+ # is solved
+ if expr.is_number:
+ return QueryPrimeHandler._number(expr, assumptions)
+
+ @staticmethod
+ def Mul(expr, assumptions):
+ if expr.is_number:
+ return QueryPrimeHandler._number(expr, assumptions)
+ for arg in expr.args:
+ if query(arg, integer=True, assumptions=assumptions):
+ pass
+ else: break
+ else:
+ # a product of integers can't be a prime
+ return False
+
+ @staticmethod
+ def Pow(expr, assumptions):
+ """
+ Integer**Integer -> !Prime
+ """
+ if expr.is_number:
+ return QueryPrimeHandler._number(expr, assumptions)
+ if query(expr.exp, integer=True, assumptions=assumptions) and \
+ query(expr.base, integer=True, assumptions=assumptions):
+ return False
+
+ @staticmethod
+ def Integer(expr, assumptions):
+ return isprime(expr)
+
+ @staticmethod
+ def Rational(expr, assumptions):
+ return False
+
+ @staticmethod
+ def Real(expr, assumptions):
+ return QueryPrimeHandler._number(expr, assumptions)
+
+ @staticmethod
+ def Infinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def NegativeInfinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def ImaginaryUnit(expr, assumptions):
+ return False
+
+ @staticmethod
+ def NumberSymbol(expr, assumptions):
+ return QueryPrimeHandler._number(expr, assumptions)
+
+class QueryCompositeHandler(CommonHandler):
+
+ @staticmethod
+ def Basic(expr, assumptions):
+ return query(expr, positive=True, integer=True, prime=False, \
+ assumptions=assumptions)
+
+class QueryEvenHandler(CommonHandler):
+
+ @staticmethod
+ def _number(expr, assumptions):
+ # helper method
+ if (expr.as_real_imag()[1] == 0) and expr.evalf(1) == expr:
+ return float(expr.evalf()) % 2 == 0
+ else: return False
+
+ @staticmethod
+ def Basic(expr, assumptions):
+ if expr.is_number:
+ return QueryEvenHandler._number(expr, assumptions)
+
+ @staticmethod
+ def Mul(expr, assumptions):
+ """
+ Even * Integer -> Even
+ Even * Odd -> Even
+ Integer * Odd -> ?
+ Odd * Odd -> Odd
+ """
+ if expr.is_number:
+ return QueryEvenHandler._number(expr, assumptions)
+ even, odd, irrational = False, 0, False
+ for arg in expr.args:
+ # check for all integers and at least one even
+ if query(arg, integer=True, assumptions=assumptions):
+ if query(arg, even=True, assumptions=assumptions):
+ even = True
+ elif query(arg, odd=True, assumptions=assumptions):
+ odd += 1
+ elif query(arg, irrational=True, assumptions=assumptions):
+ # one irrational makes the result False
+ # two makes it undefined
+ if irrational:
+ break
+ irrational = True
+ else: break
+ else:
+ if irrational: return False
+ if even: return True
+ if odd == len(expr.args): return False
+
+ @staticmethod
+ def Add(expr, assumptions):
+ """
+ Even + Odd -> Odd
+ Even + Even -> Even
+ Odd + Odd -> Even
+
+ TODO: remove float() when issue
+ http://code.google.com/p/sympy/issues/detail?id=1473
+ is solved
+ """
+ if expr.is_number:
+ return QueryEvenHandler._number(expr, assumptions)
+ _result = True
+ for arg in expr.args:
+ if query(arg, even=True, assumptions=assumptions):
+ pass
+ elif query(arg, odd=True, assumptions=assumptions):
+ _result = not _result
+ else: break
+ else:
+ return _result
+
+ @staticmethod
+ def Integer(expr, assumptions):
+ return expr % 2 == 0
+
+ @staticmethod
+ def Rational(expr, assumptions):
+ return False
+
+ @staticmethod
+ def Real(expr, assumptions):
+ return expr % 2 == 0
+
+ @staticmethod
+ def Infinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def NegativeInfinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def NumberSymbol(expr, assumptions):
+ return QueryEvenHandler._number(expr, assumptions)
+
+ @staticmethod
+ def ImaginaryUnit(expr, assumptions):
+ return False
+
+ @staticmethod
+ def abs(expr, assumptions):
+ if query(expr.args[0], real=True, assumptions=assumptions):
+ return query(expr.args[0], even=True, assumptions=assumptions)
+
+ @staticmethod
+ def re(expr, assumptions):
+ if query(expr.args[0], real=True, assumptions=assumptions):
+ return query(expr.args[0], even=True, assumptions=assumptions)
+
+ @staticmethod
+ def im(expr, assumptions):
+ if query(expr.args[0], real=True, assumptions=assumptions):
+ return True
+
+class QueryOddHandler(CommonHandler):
+ """
+ Handler for key 'odd'
+ Test that an expression represents an odd number
+ """
+
+ @staticmethod
+ def Basic(expr, assumptions):
+ return query(expr, integer=True, even=False, \
+ assumptions=assumptions)
+
diff --git a/sympy/queries/handlers/order.py b/sympy/queries/handlers/order.py
new file mode 100644
index 0000000..42d63d5
--- /dev/null
+++ b/sympy/queries/handlers/order.py
@@ -0,0 +1,173 @@
+"""
+QueryHandlers related to order relations: positive, negative, etc.
+"""
+from sympy.queries import query
+from sympy.queries.handlers import CommonHandler
+
+
+class QueryNegativeHandler(CommonHandler):
+ """
+ Handler for key 'negative'
+ Test that an expression is less (strict) than zero
+ """
+
+ @staticmethod
+ def _number(expr, assumptions):
+ if not expr.as_real_imag()[1]:
+ return expr.evalf() < 0
+ else: return False
+
+ @staticmethod
+ def Basic(expr, assumptions):
+ if expr.is_number:
+ return QueryNegativeHandler._number(expr, assumptions)
+
+ @staticmethod
+ def Add(expr, assumptions):
+ """
+ Positive + Positive -> Positive,
+ Negative + Negative -> Negative
+ """
+ if expr.is_number:
+ return QueryNegativeHandler._number(expr, assumptions)
+ for arg in expr.args:
+ if not query(arg, negative=True, assumptions=assumptions):
+ break
+ else:
+ # if all argument's are negative
+ return True
+
+ @staticmethod
+ def Mul(expr, assumptions):
+ if expr.is_number:
+ return QueryNegativeHandler._number(expr, assumptions)
+ result = False
+ for arg in expr.args:
+ _negative = query(arg, real=True, negative=True, assumptions=assumptions)
+ if _negative is None: return
+ result = result ^ _negative
+ return result
+
+ @staticmethod
+ def Pow(expr, assumptions):
+ if expr.is_number:
+ return QueryNegativeHandler._number(expr, assumptions)
+ if query(expr.base, negative=True, assumptions=assumptions):
+ if query(expr.exp, odd=True, assumptions=assumptions):
+ return True
+ if query(expr.exp, even=True, assumptions=assumptions):
+ return False
+ elif query(expr.base, positive=True, assumptions=assumptions):
+ if query(expr.exp, real=True, assumptions=assumptions):
+ return False
+
+ @staticmethod
+ def ImaginaryUnit(expr, assumptions):
+ return False
+
+ @staticmethod
+ def abs(expr, assumptions):
+ return False
+
+class QueryZeroHandler(CommonHandler):
+ """
+ Handler for key 'zero'
+ Test that an expression is not identically zero
+ """
+
+ @staticmethod
+ def Basic(expr, assumptions):
+ if expr.is_number:
+ # if there are no symbols just evalf
+ return expr.evalf() == 0
+
+ @staticmethod
+ def Add(expr, assumptions):
+ if all([query(x, positive=True, assumptions=assumptions) for x in expr.args]) \
+ or all([query(x, negative=True, assumptions=assumptions) for x in expr.args]):
+ return False
+
+ @staticmethod
+ def Mul(expr, assumptions):
+ for arg in expr.args:
+ result = query(arg, zero=True, assumptions=assumptions)
+ if result == True:
+ # one zero is enough
+ return True
+ elif result is None:
+ return None
+ else:
+ return False
+
+ @staticmethod
+ def Pow(expr, assumptions):
+ if query(expr.exp, zero=True, assumptions=assumptions) == False:
+ return query(expr.base, zero=True, assumptions=assumptions)
+
+ @staticmethod
+ def abs(expr, assumptions):
+ return query(expr.args[0], zero=True, assumptions=assumptions)
+
+class QueryPositiveHandler(CommonHandler):
+ """
+ Handler for key 'positive'
+ Test that an expression is greater (strict) than zero
+ """
+
+ @staticmethod
+ def _number(expr, assumptions):
+ if not expr.as_real_imag()[1]:
+ return expr.evalf() > 0
+ else: return False
+
+ @staticmethod
+ def Basic(expr, assumptions):
+ if expr.is_number:
+ return QueryPositiveHandler._number(expr, assumptions)
+
+ @staticmethod
+ def Mul(expr, assumptions):
+ if expr.is_number:
+ return QueryPositiveHandler._number(expr, assumptions)
+ result = True
+ for arg in expr.args:
+ if query(arg, positive=True, assumptions=assumptions): continue
+ elif query(arg, negative=True, assumptions=assumptions):
+ result = result ^ True
+ else: return
+ return result
+
+ @staticmethod
+ def Add(expr, assumptions):
+ if expr.is_number:
+ return QueryPositiveHandler._number(expr, assumptions)
+ for arg in expr.args:
+ if query(arg, positive=True, assumptions=assumptions) is not True:
+ break
+ else:
+ # if all argument's are positive
+ return True
+
+ @staticmethod
+ def Pow(expr, assumptions):
+ if expr.is_number: return expr.evalf() > 0
+ if query(expr.base, positive=True, assumptions=assumptions):
+ return True
+ if query(expr.base, negative=True, assumptions=assumptions):
+ if query(expr.exp, even=True, assumptions=assumptions):
+ return True
+ if query(expr.exp, even=True, assumptions=assumptions):
+ return False
+
+ @staticmethod
+ def exp(expr, assumptions):
+ if query(expr.args[0], real=True, assumptions=assumptions):
+ return True
+
+ @staticmethod
+ def ImaginaryUnit(expr, assumptions):
+ return False
+
+ @staticmethod
+ def abs(expr, assumptions):
+ return query(expr, zero=False, assumptions=assumptions)
diff --git a/sympy/queries/handlers/sets.py b/sympy/queries/handlers/sets.py
new file mode 100644
index 0000000..61971ce
--- /dev/null
+++ b/sympy/queries/handlers/sets.py
@@ -0,0 +1,433 @@
+"""
+Handlers for keys related to set membership: integer, rational, etc.
+"""
+from sympy.queries import query
+from sympy.queries.handlers import CommonHandler
+
+class QueryIntegerHandler(CommonHandler):
+ """
+ Handler for key 'integer'
+ Test that an expression belongs to the field of integer numbers
+ """
+
+ @staticmethod
+ def _number(expr, assumptions):
+ # helper method
+ if expr.as_real_imag()[1] == 0:
+ return expr.evalf(1) == expr
+ return False
+
+ @staticmethod
+ def Add(expr, assumptions):
+ """
+ Integer + Integer -> Integer
+ Integer + !Integer -> !Integer
+ !Integer + !Integer -> ?
+ """
+ if expr.is_number:
+ return QueryIntegerHandler._number(expr, assumptions)
+ return test_closed_group(expr, assumptions, 'integer')
+
+ @staticmethod
+ def Mul(expr, assumptions):
+ """
+ Integer*Integer -> Integer
+ Integer*Irrational -> !Integer
+ Odd/Even -> !Integer
+ Integer*Rational -> ?
+ """
+ if expr.is_number:
+ return QueryIntegerHandler._number(expr, assumptions)
+ _output = True
+ for arg in expr.args:
+ if not query(arg, integer=True, assumptions=assumptions):
+ if arg.is_Rational:
+ if arg.q == 2:
+ return query(2*expr, even=True, assumptions=assumptions)
+ if arg.q % 2 == 1:
+ if query(arg.q*expr, even=True, assumptions=assumptions):
+ # even / odd -> !integer
+ return False
+ else: break
+ elif query(arg, irrational=True, assumptions=assumptions):
+ if _output:
+ _output = False
+ else:
+ return
+ else:
+ return
+ else:
+ return _output
+
+ Pow = Add
+
+ @staticmethod
+ def int(expr, assumptions):
+ return True
+
+ @staticmethod
+ def Integer(expr, assumptions):
+ return True
+
+ @staticmethod
+ def Rational(expr, assumptions):
+ # rationals with denominator one get
+ # evaluated to Integers
+ return False
+
+ @staticmethod
+ def Real(expr, assumptions):
+ return int(expr) == expr
+
+ @staticmethod
+ def Pi(expr, assumptions):
+ return False
+
+ @staticmethod
+ def Exp1(expr, assumptions):
+ return False
+
+ @staticmethod
+ def Infinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def NegativeInfinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def ImaginaryUnit(expr, assumptions):
+ return False
+
+ @staticmethod
+ def abs(expr, assumptions):
+ return query(expr.args[0], integer=True, assumptions=assumptions)
+
+class QueryRationalHandler(CommonHandler):
+ """
+ Handler for key 'rational'
+ Test that an expression belongs to the field of rational numbers
+ """
+
+ @staticmethod
+ def Symbol(expr, assumptions):
+ if query(expr, zero=True, assumptions=assumptions):
+ # zero is a rational number
+ return True
+
+ @staticmethod
+ def Add(expr, assumptions):
+ """
+ Rational + Rational -> Rational
+ Rational + !Rational -> !Rational
+ !Rational + !Rational -> ?
+ """
+ if expr.is_number:
+ if expr.as_real_imag()[1]:
+ return False
+ return test_closed_group(expr, assumptions, 'rational')
+
+ Mul = Add
+
+ @staticmethod
+ def Pow(expr, assumptions):
+ """
+ Rational ** Integer -> Rational
+ Irrational ** Rational -> Irrational
+ Rational ** Irrational -> ?
+ """
+ if query(expr.exp, integer=True, assumptions=assumptions):
+ return query(expr.base, rational=True, assumptions=assumptions)
+ elif query(expr.exp, rational=True, assumptions=assumptions):
+ if query(expr.base, prime=True, assumptions=assumptions):
+ return False
+
+ @staticmethod
+ def Rational(expr, assumptions):
+ return True
+
+ @staticmethod
+ def Real(expr, assumptions):
+ # it's finite-precission
+ return True
+
+ @staticmethod
+ def ImaginaryUnit(expr, assumptions):
+ return False
+
+ @staticmethod
+ def Infinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def NegativeInfinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def Pi(expr, assumptions):
+ return False
+
+ @staticmethod
+ def Exp1(expr, assumptions):
+ return False
+
+class QueryIrrationalHandler(CommonHandler):
+
+ @staticmethod
+ def Basic(expr, assumptions):
+ return query(expr, real=True, rational=False, \
+ assumptions=assumptions)
+
+class QueryRealHandler(CommonHandler):
+ """
+ Handler for key 'real'
+ Test that an expression belongs to the field of real numbers
+ """
+
+ @staticmethod
+ def _number(expr, assumptions):
+ return not expr.as_real_imag()[1]
+
+ @staticmethod
+ def Add(expr, assumptions):
+ """
+ Real + Real -> Real
+ Real + (Complex & !Real) -> !Real
+ """
+ if expr.is_number:
+ return QueryRealHandler._number(expr, assumptions)
+ return test_closed_group(expr, assumptions, 'real')
+
+ @staticmethod
+ def Mul(expr, assumptions):
+ """
+ Real*Real -> Real
+ Real*Imaginary -> !Real
+ Imaginary*Imaginary -> Real
+ """
+ if expr.is_number:
+ return QueryRealHandler._number(expr, assumptions)
+ result = True
+ for arg in expr.args:
+ if query(arg, real=True, assumptions=assumptions):
+ pass
+ elif query(arg, imaginary=True, assumptions=assumptions):
+ result = result ^ True
+ else:
+ break
+ else:
+ return result
+
+ @staticmethod
+ def Pow(expr, assumptions):
+ """
+ Real**Integer -> Real
+ Positive**Real -> Real
+ Real**(Integer/Even) -> Real if base is nonnegative
+ Real**(Integer/Odd) -> Real
+ """
+ if expr.is_number:
+ return QueryRealHandler._number(expr, assumptions)
+ if query(expr.base, real=True, assumptions=assumptions):
+ if query(expr.exp, integer=True, assumptions=assumptions):
+ return True
+ elif expr.exp.is_Rational:
+ if (expr.exp.q % 2 == 0):
+ return query(expr.base, real=True, negative=False, \
+ assumptions=assumptions)
+ else: return True
+ elif query(expr.exp, real=True, assumptions=assumptions):
+ if query(expr.base, positive=True, assumptions=assumptions):
+ return True
+
+ @staticmethod
+ def Rational(expr, assumptions):
+ return True
+
+ @staticmethod
+ def Real(expr, assumptions):
+ return True
+
+ @staticmethod
+ def Pi(expr, assumptions):
+ return True
+
+ @staticmethod
+ def Exp1(expr, assumptions):
+ return True
+
+ @staticmethod
+ def abs(expr, assumptions):
+ return True
+
+ @staticmethod
+ def re(expr, assumptions):
+ return True
+
+ im = re
+
+ @staticmethod
+ def ImaginaryUnit(expr, assumptions):
+ return False
+
+ @staticmethod
+ def Infinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def NegativeInfinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def sin(expr, assumptions):
+ if query(expr.args[0], real=True, assumptions=assumptions):
+ return True
+
+ cos, exp = sin, sin
+
+class QueryExtendedRealHandler(QueryRealHandler):
+ """
+ Handler for key 'extended_real'
+ Test that an expression belongs to the field of extended real numbers,
+ that is real numbers union {Infinity, -Infinity}
+ """
+
+ @staticmethod
+ def Add(expr, assumptions):
+ return test_closed_group(expr, assumptions, 'extended_real')
+
+ Mul, Pow = Add, Add
+
+ @staticmethod
+ def Infinity(expr, assumptions):
+ return True
+
+ @staticmethod
+ def NegativeInfinity(expr, assumptions):
+ return True
+
+class QueryComplexHandler(CommonHandler):
+ """
+ Handler for key 'complex'
+ Test that an expression belongs to the field of complex numbers
+ """
+
+ @staticmethod
+ def Add(expr, assumptions):
+ return test_closed_group(expr, assumptions, 'complex')
+
+ Mul, Pow = Add, Add
+
+ @staticmethod
+ def Number(expr, assumptions):
+ return True
+
+ @staticmethod
+ def NumberSymbol(expr, assumptions):
+ return True
+
+ @staticmethod
+ def abs(expr, assumptions):
+ return True
+
+ @staticmethod
+ def ImaginaryUnit(expr, assumptions):
+ return True
+
+ @staticmethod
+ def Infinity(expr, assumptions):
+ return False
+
+ @staticmethod
+ def NegativeInfinity(expr, assumptions):
+ return False
+
+ sin, cos, exp, re, im = [abs]*5 # they are all complex functions
+
+class QueryImaginaryHandler(CommonHandler):
+ """
+ Handler for key 'imaginary'
+ Test that an expression belongs to the field of imaginary numbers,
+ that is, numbers in the form x*I, where x is real
+ """
+
+ @staticmethod
+ def _number(expr, assumptions):
+ # helper method
+ return not expr.as_real_imag()[0]
+
+ @staticmethod
+ def Add(expr, assumptions):
+ """
+ Imaginary + Imaginary -> Imaginary
+ Imaginary + Complex -> ?
+ Imaginary + Real -> !Imaginary
+ """
+ if expr.is_number:
+ return QueryImaginaryHandler._number(expr, assumptions)
+ reals = 0
+ for arg in expr.args:
+ if query(arg, imaginary=True, assumptions=assumptions):
+ pass
+ elif query(arg, real=True, assumptions=assumptions):
+ reals += 1
+ else:
+ break
+ else:
+ if reals == 0:
+ return True
+ if reals == 1 or (len(expr.args) == reals):
+ # two reals could sum 0 thus giving an imaginary
+ return False
+
+ @staticmethod
+ def Mul(expr, assumptions):
+ """
+ Real*Imaginary -> Imaginary
+ Imaginary*Imaginary -> Real
+ """
+ if expr.is_number:
+ return QueryImaginaryHandler._number(expr, assumptions)
+ result = False
+ reals = 0
+ for arg in expr.args:
+ if query(arg, imaginary=True, assumptions=assumptions):
+ result = result ^ True
+ elif not query(arg, real=True, assumptions=assumptions):
+ break
+ else:
+ if reals == len(expr.args):
+ return False
+ return result
+
+ Pow = Add
+
+ @staticmethod
+ def Number(expr, assumptions):
+ return not (expr.as_real_imag()[1] == 0)
+
+ NumberSymbol = Number
+
+ @staticmethod
+ def ImaginaryUnit(expr, assumptions):
+ return True
+
+
+#### Helper methods
+
+def test_closed_group(expr, assumptions, key):
+ """
+ Test for membership in a group with respect
+ to the current operation
+ """
+ kwargs = {'assumptions': assumptions, key: True}
+ result = True
+ for arg in expr.args:
+ _out = query(arg, **kwargs)
+ if _out is None: break
+ elif _out is False:
+ if result: result = False
+ else: break
+ else:
+ return result
+
diff --git a/sympy/queries/tests/test_query.py b/sympy/queries/tests/test_query.py
new file mode 100644
index 0000000..34a41b6
--- /dev/null
+++ b/sympy/queries/tests/test_query.py
@@ -0,0 +1,979 @@
+from sympy.core import Symbol, symbols, S, Rational, Integer
+from sympy.functions import exp, log, sin, cos, sign, re, im, sqrt
+from sympy.assumptions import Assume, register_global_assumptions, \
+ clean_global_assumptions
+from sympy.queries import query, register_handler, remove_handler
+from sympy.queries.handlers import QueryHandler
+from sympy.utilities.pytest import raises, XFAIL
+
+def test_int_1():
+ z = 1
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == True
+ assert query(z, rational=True) == True
+ assert query(z, real=True) == True
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == False
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == True
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == True
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == True
+
+def test_float_1():
+ z = 1.0
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == True
+ assert query(z, rational=True) == True
+ assert query(z, real=True) == True
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == False
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == True
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == True
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == True
+
+ z = 7.2123
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == False
+ assert query(z, rational=True) == True
+ assert query(z, real=True) == True
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == False
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == True
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == False
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+def test_zero_0():
+ z = Integer(0)
+ assert query(z, zero=True) == True
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == True
+ assert query(z, rational=True) == True
+ assert query(z, real=True) == True
+ assert query(z, complex=True) == True
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == False
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == True
+ assert query(z, odd=True) == False
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == True
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+def test_negativeone():
+ z = Integer(-1)
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == True
+ assert query(z, rational=True) == True
+ assert query(z, real=True) == True
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == False
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == False
+ assert query(z, negative=True) == True
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == True
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+def test_infinity():
+ oo = S.Infinity
+ assert query(oo, commutative=True) == True
+ assert query(oo, integer=True) == False
+ assert query(oo, rational=True) == False
+ assert query(oo, real=True) == False
+ assert query(oo, extended_real=True) == True
+ assert query(oo, complex=True) == False
+ assert query(oo, irrational=True) == False
+ assert query(oo, imaginary=True) == False
+ assert query(oo, positive=True) == True
+ assert query(oo, negative=True) == False
+ assert query(oo, even=True) == False
+ assert query(oo, odd=True) == False
+ assert query(oo, bounded=True) == False
+ assert query(oo, infinitesimal=True) == False
+ assert query(oo, prime=True) == False
+ assert query(oo, composite=True) == False
+
+def test_neg_infinity():
+ mm = S.NegativeInfinity
+ assert query(mm, commutative=True) == True
+ assert query(mm, integer=True) == False
+ assert query(mm, rational=True) == False
+ assert query(mm, real=True) == False
+ assert query(mm, extended_real=True) == True
+ assert query(mm, complex=True) == False
+ assert query(mm, irrational=True) == False
+ assert query(mm, imaginary=True) == False
+ assert query(mm, positive=True) == False
+ assert query(mm, negative=True) == True
+ assert query(mm, even=True) == False
+ assert query(mm, odd=True) == False
+ assert query(mm, bounded=True) == False
+ assert query(mm, infinitesimal=True) == False
+ assert query(mm, prime=True) == False
+ assert query(mm, composite=True) == False
+
+def test_nan():
+ nan = S.NaN
+ assert query(nan, commutative=True) == True
+ assert query(nan, integer=True) == False
+ assert query(nan, rational=True) == False
+ assert query(nan, real=True) == False
+ assert query(nan, extended_real=True) == False
+ assert query(nan, complex=True) == False
+ assert query(nan, irrational=True) == False
+ assert query(nan, imaginary=True) == False
+ assert query(nan, positive=True) == False
+ assert query(nan, zero=True) == False
+ assert query(nan, even=True) == False
+ assert query(nan, odd=True) == False
+ assert query(nan, bounded=True) == False
+ assert query(nan, infinitesimal=True) == False
+ assert query(nan, prime=True) == False
+ assert query(nan, composite=True) == False
+
+def test_Rational_number():
+ r = Rational(3,4)
+ assert query(r, commutative=True) == True
+ assert query(r, integer=True) == False
+ assert query(r, rational=True) == True
+ assert query(r, real=True) == True
+ assert query(r, complex=True) == True
+ assert query(r, irrational=True) == False
+ assert query(r, imaginary=True) == False
+ assert query(r, positive=True) == True
+ assert query(r, negative=True) == False
+ assert query(r, even=True) == False
+ assert query(r, odd=True) == False
+ assert query(r, bounded=True) == True
+ assert query(r, infinitesimal=True) == False
+ assert query(r, prime=True) == False
+ assert query(r, composite=True) == False
+
+ r = Rational(1,4)
+ assert query(r, positive=True) == True
+ assert query(r, negative=True) == False
+
+ r = Rational(5,4)
+ assert query(r, negative=True) == False
+ assert query(r, positive=True) == True
+
+ r = Rational(5,3)
+ assert query(r, positive=True) == True
+ assert query(r, negative=True) == False
+
+ r = Rational(-3,4)
+ assert query(r, positive=True) == False
+ assert query(r, negative=True) == True
+
+ r = Rational(-1,4)
+ assert query(r, positive=True) == False
+ assert query(r, negative=True) == True
+
+ r = Rational(-5,4)
+ assert query(r, negative=True) == True
+ assert query(r, positive=True) == False
+
+ r = Rational(-5,3)
+ assert query(r, positive=True) == False
+ assert query(r, negative=True) == True
+
+def test_sqrt_2():
+ z = sqrt(2)
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == False
+ assert query(z, rational=True) == False
+ assert query(z, real=True) == True
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == True
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == True
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == False
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+def test_pi():
+ z = S.Pi
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == False
+ assert query(z, rational=True) == False
+ assert query(z, real=True) == True
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == True
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == True
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == False
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+ z = S.Pi + 1
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == False
+ assert query(z, rational=True) == False
+ assert query(z, real=True) == True
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == True
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == True
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == False
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+ z = 2*S.Pi
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == False
+ assert query(z, rational=True) == False
+ assert query(z, real=True) == True
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == True
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == True
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == False
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+ z = S.Pi ** 2
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == False
+ assert query(z, rational=True) == False
+ assert query(z, real=True) == True
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == True
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == True
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == False
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+ z = (1+S.Pi) ** 2
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == False
+ assert query(z, rational=True) == False
+ assert query(z, real=True) == True
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == True
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == True
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == False
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+def test_E():
+ z = S.Exp1
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == False
+ assert query(z, rational=True) == False
+ assert query(z, real=True) == True
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == True
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == True
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == False
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+def test_I():
+ I = S.ImaginaryUnit
+ z = I
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == False
+ assert query(z, rational=True) == False
+ assert query(z, real=True) == False
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == False
+ assert query(z, imaginary=True) == True
+ assert query(z, positive=True) == False
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == False
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+ z = 1 + I
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == False
+ assert query(z, rational=True) == False
+ assert query(z, real=True) == False
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == False
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == False
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == False
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+ z = I*(1+I)
+ assert query(z, commutative=True) == True
+ assert query(z, integer=True) == False
+ assert query(z, rational=True) == False
+ assert query(z, real=True) == False
+ assert query(z, complex=True) == True
+ assert query(z, irrational=True) == False
+ assert query(z, imaginary=True) == False
+ assert query(z, positive=True) == False
+ assert query(z, negative=True) == False
+ assert query(z, even=True) == False
+ assert query(z, odd=True) == False
+ assert query(z, bounded=True) == True
+ assert query(z, infinitesimal=True) == False
+ assert query(z, prime=True) == False
+ assert query(z, composite=True) == False
+
+def test_bounded():
+ x, y = symbols('xy')
+ assert query(x, bounded=True) == False
+ assert query(x, bounded=False) == True
+ assert query(x, bounded=True, assumptions=Assume(x, bounded=True)) == True
+ assert query(x, bounded=True, assumptions=Assume(y, bounded=True)) == False
+ assert query(x, bounded=True, assumptions=Assume(x, complex=True)) == False
+ assert query(x, bounded=True, assumptions=Assume(x, zero=True)) == True
+ assert query(x+ 1, bounded=True) == False
+ assert query(x+ 1, bounded=True, assumptions=Assume(x, bounded=True)) == True
+ assert query(x+y, bounded=True) == None
+ assert query(x+y, bounded=True, assumptions=Assume(x, bounded=True)) == False
+ assert query(x+1, bounded=True, assumptions=[Assume(x, bounded=True), \
+ Assume(y, bounded=True)]) == True
+ assert query(2*x, bounded=True) == False
+ assert query(2*x, bounded=True, assumptions=Assume(x, bounded=True)) == True
+ assert query(x*y, bounded=True) == None
+ assert query(x*y, bounded=True, assumptions=Assume(x, bounded=True)) == False
+ assert query(x*y, bounded=True, assumptions=Assume(x, bounded=True) & \
+ Assume(y, bounded=True)) == True
+
+ assert query(x**2, bounded=True) == False
+ assert query(2**x, bounded=True) == False
+ assert query(2**x, bounded=True, assumptions=Assume(x, bounded=True)) == True
+ assert query(x**x, bounded=True) == False
+ assert query(Rational(1,2) ** x, bounded=True) == True
+ assert query(x ** Rational(1,2), bounded=True) == False
+
+ # sign function
+ assert query(sign(x), bounded=True) == True
+ assert query(sign(x), bounded=True, assumptions=Assume(x, bounded=False)) == True
+
+ # exponential functions
+ assert query(log(x), bounded=True) == False
+ assert query(log(x), bounded=True, assumptions=Assume(x, bounded=True)) == True
+ assert query(exp(x), bounded=True) == False
+ assert query(exp(x), bounded=True, assumptions=Assume(x, bounded=True)) == True
+ assert query(exp(2), bounded=True) == True
+
+ # trigonometric functions
+ assert query(sin(x), bounded=True) == True
+ assert query(sin(x), bounded=True, assumptions=Assume(x, bounded=False)) == True
+ assert query(cos(x), bounded=True) == True
+ assert query(cos(x), bounded=True, assumptions=Assume(x, bounded=False)) == True
+ assert query(2*sin(x), bounded=True) == True
+ assert query(sin(x)**2, bounded=True) == True
+ assert query(cos(x)**2, bounded=True) == True
+ assert query(cos(x) + sin(x), bounded=True) == True
+
+@XFAIL
+def test_bounded_xfail():
+ """We need to support relations in query for this to work"""
+ x = Symbol('x')
+ assert query(sin(x)**x, bounded=True) == True
+ assert query(cos(x)**x, bounded=True) == True
+ assert query(sin(x) ** x, bounded=True) == True
+
+def test_commutative():
+ """By default objects are commutative that is why it returns True
+ for both key=True and key=False"""
+ x, y = symbols('xy')
+ assert query(x, commutative=True) == True
+ assert query(x, commutative=False) == False
+ assert query(x, commutative=True, assumptions=Assume(x, commutative=False)) == False
+ assert query(x, commutative=True, assumptions=Assume(x, complex=True)) == True
+ assert query(x, commutative=True, assumptions=Assume(x, imaginary=True)) == True
+ assert query(x, commutative=True, assumptions=Assume(x, real=True)) == True
+ assert query(x, commutative=True, assumptions=Assume(x, positive=True)) == True
+ assert query(x, commutative=True, assumptions=Assume(y, commutative=False)) == True
+
+ assert query(2*x, commutative=True ) == True
+ assert query(2*x, commutative=True, assumptions=Assume(x, commutative=False)) == False
+
+ assert query(x + 1, commutative=True ) == True
+ assert query(x + 1, commutative=True, assumptions=Assume(x, commutative=False)) == False
+
+ assert query(x**2, commutative=True) == True
+ assert query(x**2, commutative=True, assumptions=Assume(x, commutative=False)) == False
+
+ assert query(log(x), commutative=True) == True
+
+def test_complex():
+ x, y = symbols('xy')
+ assert query(x, complex=True) == None
+ assert query(x, complex=False) == None
+ assert query(x, complex=True, assumptions=Assume(x, complex=True)) == True
+ assert query(x, complex=True, assumptions=Assume(y, complex=True)) == None
+ assert query(x, complex=True, assumptions=Assume(x, complex=False)) == False
+ assert query(x, complex=True, assumptions=Assume(x, real=True)) == True
+ assert query(x, complex=True, assumptions=Assume(x, real=False)) == None
+ assert query(x, complex=True, assumptions=Assume(x, rational=True)) == True
+ assert query(x, complex=True, assumptions=Assume(x, irrational=True)) == True
+ assert query(x, complex=True, assumptions=Assume(x, zero=True)) == True
+ assert query(x, complex=True, assumptions=Assume(x, zero=False)) == None
+ assert query(x, complex=True, assumptions=Assume(x, positive=True)) == True
+ assert query(x, complex=True, assumptions=Assume(x, imaginary=True)) == True
+
+ # a+b
+ assert query(x+1, complex=True, assumptions=Assume(x, complex=True)) == True
+ assert query(x+1, complex=True, assumptions=Assume(x, real=True)) == True
+ assert query(x+1, complex=True, assumptions=Assume(x, rational=True)) == True
+ assert query(x+1, complex=True, assumptions=Assume(x, irrational=True)) == True
+ assert query(x+1, complex=True, assumptions=Assume(x, imaginary=True)) == True
+ assert query(x+1, complex=True, assumptions=Assume(x, integer=True)) == True
+ assert query(x+1, complex=True, assumptions=Assume(x, even=True)) == True
+ assert query(x+1, complex=True, assumptions=Assume(x, odd=True)) == True
+ assert query(x+y, complex=True, assumptions=Assume(x, complex=True) & \
+ Assume(y, complex=True)) == True
+ assert query(x+y, complex=True, assumptions=Assume(x, real=True) & \
+ Assume(y, imaginary=True)) == True
+
+ # a*x +b
+ assert query(2*x+1, complex=True, assumptions=Assume(x, complex=True)) == True
+ assert query(2*x+1, complex=True, assumptions=Assume(x, real=True)) == True
+ assert query(2*x+1, complex=True, assumptions=Assume(x, positive=True)) == True
+ assert query(2*x+1, complex=True, assumptions=Assume(x, rational=True)) == True
+ assert query(2*x+1, complex=True, assumptions=Assume(x, irrational=True)) == True
+ assert query(2*x+1, complex=True, assumptions=Assume(x, imaginary=True)) == True
+ assert query(2*x+1, complex=True, assumptions=Assume(x, integer=True)) == True
+ assert query(2*x+1, complex=True, assumptions=Assume(x, even=True)) == True
+ assert query(2*x+1, complex=True, assumptions=Assume(x, odd=True)) == True
+
+ # x**2
+ assert query(x**2, complex=True, assumptions=Assume(x, complex=True)) == True
+ assert query(x**2, complex=True, assumptions=Assume(x, real=True)) == True
+ assert query(x**2, complex=True, assumptions=Assume(x, positive=True)) == True
+ assert query(x**2, complex=True, assumptions=Assume(x, rational=True)) == True
+ assert query(x**2, complex=True, assumptions=Assume(x, irrational=True)) == True
+ assert query(x**2, complex=True, assumptions=Assume(x, imaginary=True)) == True
+ assert query(x**2, complex=True, assumptions=Assume(x, integer=True)) == True
+ assert query(x**2, complex=True, assumptions=Assume(x, even=True)) == True
+ assert query(x**2, complex=True, assumptions=Assume(x, odd=True)) == True
+
+ # 2**x
+ assert query(2**x, complex=True, assumptions=Assume(x, complex=True)) == True
+ assert query(2**x, complex=True, assumptions=Assume(x, real=True)) == True
+ assert query(2**x, complex=True, assumptions=Assume(x, positive=True)) == True
+ assert query(2**x, complex=True, assumptions=Assume(x, rational=True)) == True
+ assert query(2**x, complex=True, assumptions=Assume(x, irrational=True)) == True
+ assert query(2**x, complex=True, assumptions=Assume(x, imaginary=True)) == True
+ assert query(2**x, complex=True, assumptions=Assume(x, integer=True)) == True
+ assert query(2**x, complex=True, assumptions=Assume(x, even=True)) == True
+ assert query(2**x, complex=True, assumptions=Assume(x, odd=True)) == True
+ assert query(x**y, complex=True, assumptions=Assume(x, complex=True) & \
+ Assume(y, complex=True)) == True
+
+ # trigonometric expressions
+ assert query(sin(x), complex=True) == True
+ assert query(sin(2*x + 1), complex=True) == True
+ assert query(cos(x), complex=True) == True
+ assert query(cos(2*x+1), complex=True) == True
+
+ # exponential
+ assert query(exp(x), complex=True) == True
+ assert query(exp(x), complex=True) == True
+
+ # complexes
+ assert query(abs(x), complex=True) == True
+ assert query(re(x), complex=True) == True
+ assert query(im(x), complex=True) == True
+
+def test_even():
+ x, y, z, t = symbols('x y z t')
+ assert query(x, even=True) == None
+ assert query(x, even=True, assumptions=Assume(x, integer=True)) == None
+ assert query(x, even=True, assumptions=Assume(x, integer=False)) == False
+ assert query(x, even=True, assumptions=Assume(x, rational=True)) == None
+ assert query(x, even=True, assumptions=Assume(x, positive=True)) == None
+
+ assert query(2*x, even=True) == None
+ assert query(2*x, even=True, assumptions=Assume(x, integer=True)) == True
+ assert query(2*x, even=True, assumptions=Assume(x, even=True)) == True
+ assert query(2*x, even=True, assumptions=Assume(x, irrational=True)) == False
+ assert query(2*x, even=True, assumptions=Assume(x, odd=True)) == True
+ assert query(2*x, even=True, assumptions=Assume(x, integer=False)) == None
+ assert query(3*x, even=True, assumptions=Assume(x, integer=True)) == None
+ assert query(3*x, even=True, assumptions=Assume(x, even=True)) == True
+ assert query(3*x, even=True, assumptions=Assume(x, odd=True)) == False
+
+ assert query(x+1, even=True, assumptions=Assume(x, odd=True)) == True
+ assert query(x+1, even=True, assumptions=Assume(x, even=True)) == False
+ assert query(x+2, even=True, assumptions=Assume(x, odd=True)) == False
+ assert query(x+2, even=True, assumptions=Assume(x, even=True)) == True
+ assert query(7-x, even=True, assumptions=Assume(x, odd=True)) == True
+ assert query(7+x, even=True, assumptions=Assume(x, odd=True)) == True
+ assert query(x+y, even=True, assumptions=Assume(x, odd=True) & Assume(y, odd=True)) == True
+ assert query(x+y, even=True, assumptions=Assume(x, odd=True) & Assume(y, even=True)) == False
+ assert query(x+y, even=True, assumptions=Assume(x, even=True) & Assume(y, even=True)) == True
+
+ assert query(2*x + 1, even=True, assumptions=Assume(x, integer=True)) == False
+ assert query(2*x*y, even=True, assumptions=Assume(x, rational=True) & Assume(x, rational=True)) == None
+ assert query(2*x*y, even=True, assumptions=Assume(x, irrational=True) & Assume(x, irrational=True)) == None
+
+ assert query(x+y+z, even=True, assumptions=Assume(x, odd=True) & Assume(y, odd=True) & \
+ Assume(z, even=True)) == True
+ assert query(x+y+z+t, even=True, assumptions=Assume(x, odd=True) & Assume(y, odd=True) & \
+ Assume(z, even=True) & Assume(t, integer=True)) == None
+
+ assert query(abs(x), even=True, assumptions=Assume(x, even=True)) == True
+ assert query(abs(x), even=True, assumptions=Assume(x, even=False)) == None
+ assert query(re(x), even=True, assumptions=Assume(x, even=True)) == True
+ assert query(re(x), even=True, assumptions=Assume(x, even=False)) == None
+ assert query(im(x), even=True, assumptions=Assume(x, even=True)) == True
+ assert query(im(x), even=True, assumptions=Assume(x, real=True)) == True
+
+def test_extended_real():
+ x = symbols('x')
+ assert query(x, extended_real=True, assumptions=Assume(x, positive=True)) == True
+ assert query(-x, extended_real=True, assumptions=Assume(x, positive=True)) == True
+ assert query(-x, extended_real=True, assumptions=Assume(x, negative=True)) == True
+
+ assert query(x+S.Infinity, extended_real=True, assumptions=Assume(x, real=True)) == True
+
+def test_rational():
+ x, y = symbols('xy')
+ assert query(x, rational=True, assumptions=Assume(x, zero=True)) == True
+ assert query(x, rational=True, assumptions=Assume(x, integer=True)) == True
+ assert query(x, rational=True, assumptions=Assume(x, irrational=True)) == False
+ assert query(x, rational=True, assumptions=Assume(x, real=True)) == None
+ assert query(x, rational=True, assumptions=Assume(x, positive=True)) == None
+ assert query(x, rational=True, assumptions=Assume(x, negative=True)) == None
+ assert query(x, rational=True, assumptions=Assume(x, nonzero=True)) == None
+
+ assert query(2*x, rational=True, assumptions=Assume(x, rational=True)) == True
+ assert query(2*x, rational=True, assumptions=Assume(x, integer=True)) == True
+ assert query(2*x, rational=True, assumptions=Assume(x, even=True)) == True
+ assert query(2*x, rational=True, assumptions=Assume(x, odd=True)) == True
+ assert query(2*x, rational=True, assumptions=Assume(x, irrational=True)) == False
+
+ assert query(x/2, rational=True, assumptions=Assume(x, rational=True)) == True
+ assert query(x/2, rational=True, assumptions=Assume(x, integer=True)) == True
+ assert query(x/2, rational=True, assumptions=Assume(x, even=True)) == True
+ assert query(x/2, rational=True, assumptions=Assume(x, odd=True)) == True
+ assert query(x/2, rational=True, assumptions=Assume(x, irrational=True)) == False
+
+ assert query(1/x, rational=True, assumptions=Assume(x, rational=True)) == True
+ assert query(1/x, rational=True, assumptions=Assume(x, integer=True)) == True
+ assert query(1/x, rational=True, assumptions=Assume(x, even=True)) == True
+ assert query(1/x, rational=True, assumptions=Assume(x, odd=True)) == True
+ assert query(1/x, rational=True, assumptions=Assume(x, irrational=True)) == False
+
+ assert query(2/x, rational=True, assumptions=Assume(x, rational=True)) == True
+ assert query(2/x, rational=True, assumptions=Assume(x, integer=True)) == True
+ assert query(2/x, rational=True, assumptions=Assume(x, even=True)) == True
+ assert query(2/x, rational=True, assumptions=Assume(x, odd=True)) == True
+ assert query(2/x, rational=True, assumptions=Assume(x, irrational=True)) == False
+
+ # with multiple symbols
+ assert query(x*y, rational=True, assumptions=[Assume(x, irrational=True), \
+ Assume(y, irrational=True)]) == None
+ assert query(y/x, rational=True, assumptions=[Assume(x, rational=True), \
+ Assume(y, rational=True)]) == True
+ assert query(y/x, rational=True, assumptions=[Assume(x, integer=True), \
+ Assume(y, rational=True)]) == True
+ assert query(y/x, rational=True, assumptions=[Assume(x, even=True), \
+ Assume(y, rational=True)]) == True
+ assert query(y/x, rational=True, assumptions=[Assume(x, odd=True), \
+ Assume(y, rational=True)]) == True
+ assert query(y/x, rational=True, assumptions=[Assume(x, irrational=True), \
+ Assume(y, rational=True)]) == False
+
+def test_imaginary():
+ x, y, z = symbols('x y z')
+ I = S.ImaginaryUnit
+ assert query(x, imaginary=True) == None
+ assert query(x, imaginary=True, assumptions=Assume(x, real=True)) == False
+ assert query(x, imaginary=True, assumptions=Assume(x, prime=True)) == False
+
+ assert query(x+1, imaginary=True, assumptions=Assume(x, real=True)) == False
+ assert query(x+1, imaginary=True, assumptions=Assume(x, imaginary=True)) == False
+ assert query(x+I, imaginary=True, assumptions=Assume(x, real=True)) == False
+ assert query(x+I, imaginary=True, assumptions=Assume(x, imaginary=True)) == True
+ assert query(x+y, imaginary=True, assumptions=Assume(x, imaginary=True) & \
+ Assume(y, imaginary=True)) == True
+ assert query(x+y, imaginary=True, assumptions=Assume(x, real=True) & \
+ Assume(y, real=True)) == False
+ assert query(x+y, imaginary=True, assumptions=Assume(x, imaginary=True) & \
+ Assume(y, real=True)) == False
+ assert query(x+y, imaginary=True, assumptions=Assume(x, complex=True) & \
+ Assume(y, real=True)) == None
+
+ assert query(I*x, imaginary=True, assumptions=Assume(x, real=True)) == True
+ assert query(I*x, imaginary=True, assumptions=Assume(x, imaginary=True)) == False
+ assert query(I*x, imaginary=True, assumptions=Assume(x, complex=True)) == None
+ assert query(x*y, imaginary=True, assumptions=Assume(x, imaginary=True) & \
+ Assume(y, real=True)) == True
+
+ assert query(x+y+z, imaginary=True, assumptions=Assume(x, real=True) & \
+ Assume(y, real=True) & Assume(z, real=True)) == False
+ assert query(x+y+z, imaginary=True, assumptions=Assume(x, real=True) & \
+ Assume(y, real=True) & Assume(z, imaginary=True)) == None
+ assert query(x+y+z, imaginary=True, assumptions=Assume(x, real=True) & \
+ Assume(y, imaginary=True) & Assume(z, imaginary=True)) == False
+
+def test_infinitesimal():
+ x, y = symbols('x y')
+ assert query(x, infinitesimal=True) == None
+ assert query(x, infinitesimal=True, assumptions=Assume(x, infinitesimal=True)) == True
+
+ assert query(2*x, infinitesimal=True, assumptions=Assume(x, infinitesimal=True)) == True
+ assert query(x*y, infinitesimal=True, assumptions=Assume(x, infinitesimal=True)) == None
+ assert query(x*y, infinitesimal=True, assumptions=Assume(x, infinitesimal=True) & \
+ Assume(y, infinitesimal=True)) == True
+ assert query(x*y, infinitesimal=True, assumptions=Assume(x, infinitesimal=True) & \
+ Assume(y, bounded=True)) == True
+
+ assert query(x**2, infinitesimal=True, assumptions=Assume(x, infinitesimal=True)) == True
+
+def test_integer():
+ x = symbols('x')
+ assert query(x, integer=True) == None
+ assert query(x, integer=True, assumptions=Assume(x, integer=True)) == True
+ assert query(x, integer=True, assumptions=Assume(x, integer=False)) == False
+ assert query(x, integer=True, assumptions=Assume(x, real=False)) == False
+ assert query(x, integer=True, assumptions=Assume(x, positive=False)) == None
+
+ assert query(2*x, integer=True, assumptions=Assume(x, integer=True)) == True
+ assert query(2*x, integer=True, assumptions=Assume(x, even=True)) == True
+ assert query(2*x, integer=True, assumptions=Assume(x, prime=True)) == True
+ assert query(2*x, integer=True, assumptions=Assume(x, rational=True)) == None
+ assert query(2*x, integer=True, assumptions=Assume(x, real=True)) == None
+
+ assert query(x/2, integer=True, assumptions=Assume(x, odd=True)) == False
+ assert query(x/2, integer=True, assumptions=Assume(x, even=True)) == True
+ assert query(x/3, integer=True, assumptions=Assume(x, odd=True)) == None
+ assert query(x/3, integer=True, assumptions=Assume(x, even=True)) == False
+
+def test_negative():
+ x, y = symbols('xy')
+ assert query(x, negative=True, assumptions=Assume(x, negative=True)) == True
+ assert query(x, negative=True, assumptions=Assume(x, positive=True)) == False
+ assert query(x, negative=True, assumptions=Assume(x, real=False)) == False
+ assert query(x, negative=True, assumptions=Assume(x, prime=True)) == False
+ assert query(x, negative=True, assumptions=Assume(x, prime=False)) == None
+
+ assert query(-x, negative=True, assumptions=Assume(x, positive=True)) == True
+ assert query(-x, negative=True, assumptions=Assume(x, positive=False)) == None
+ assert query(-x, negative=True, assumptions=Assume(x, negative=True)) == False
+ assert query(-x, negative=True, assumptions=Assume(x, positive=True)) == True
+
+ assert query(x-1, negative=True, assumptions=Assume(x, negative=True)) == True
+ assert query(x+y, negative=True) == None
+ assert query(x+y, negative=True, assumptions=Assume(x, negative=True)) == None
+ assert query(x+y, negative=True, assumptions=Assume(x, negative=True) &\
+ Assume(y, negative=True)) == True
+
+ assert query(x*y, negative=True) == None
+ assert query(x*y, negative=True, assumptions=Assume(x, positive=True) & \
+ Assume(y, positive=True)) == False
+ assert query(x*y, negative=True, assumptions=Assume(x, positive=True) & \
+ Assume(y, negative=True)) == True
+ assert query(x*y, negative=True, assumptions=Assume(x, complex=True) & \
+ Assume(y, complex=True)) == None
+
+ assert query(x**y, negative=True) == None
+ assert query(x**y, negative=True, assumptions=Assume(x, negative=True) & \
+ Assume(y, even=True)) == False
+ assert query(x**y, negative=True, assumptions=Assume(x, negative=True) & \
+ Assume(y, odd=True)) == True
+ assert query(x**y, negative=True, assumptions=Assume(x, positive=True) & \
+ Assume(y, integer=True)) == False
+
+ assert query(abs(x), negative=True) == False
+
+def test_nonzero():
+ x = Symbol('x')
+ def nonzero(expr, assumptions=[]):
+ return query(expr, real=True, assumptions=assumptions) and \
+ query(expr, zero=False, assumptions=assumptions)
+ assert nonzero(x) == None
+ assert nonzero(x, assumptions=Assume(x, real=True) & Assume(x, zero=False))== True
+ assert nonzero(x, assumptions=Assume(x, zero=True)) == False
+ assert nonzero( x, assumptions=Assume(x, positive=True)) == True
+ assert nonzero(2*x, assumptions=Assume(x, positive=True)) == True
+
+def test_odd():
+ x, y, z, t = symbols('x y z t')
+ assert query(x, odd=True) == None
+ assert query(x, odd=True, assumptions=Assume(x, odd=True)) == True
+ assert query(x, odd=True, assumptions=Assume(x, integer=True)) == None
+ assert query(x, odd=True, assumptions=Assume(x, integer=False)) == False
+ assert query(x, odd=True, assumptions=Assume(x, rational=True)) == None
+ assert query(x, odd=True, assumptions=Assume(x, positive=True)) == None
+
+ assert query(-x, odd=True, assumptions=Assume(x, odd=True)) == True
+
+ assert query(2*x, odd=True) == None
+ assert query(2*x, odd=True, assumptions=Assume(x, integer=True)) == False
+ assert query(2*x, odd=True, assumptions=Assume(x, odd=True)) == False
+ assert query(2*x, odd=True, assumptions=Assume(x, irrational=True)) == False
+ assert query(2*x, odd=True, assumptions=Assume(x, integer=False)) == None
+ assert query(3*x, odd=True, assumptions=Assume(x, integer=True)) == None
+
+ assert query(x/3, odd=True, assumptions=Assume(x, odd=True)) == None
+ assert query(x/3, odd=True, assumptions=Assume(x, even=True)) == None
+
+ assert query(x+1, odd=True, assumptions=Assume(x, even=True)) == True
+ assert query(x+2, odd=True, assumptions=Assume(x, even=True)) == False
+ assert query(x+2, odd=True, assumptions=Assume(x, odd=True)) == True
+ assert query(3-x, odd=True, assumptions=Assume(x, odd=True)) == False
+ assert query(3-x, odd=True, assumptions=Assume(x, even=True)) == True
+ assert query(3+x, odd=True, assumptions=Assume(x, odd=True)) == False
+ assert query(3+x, odd=True, assumptions=Assume(x, even=True)) == True
+ assert query(x+y, odd=True, assumptions=Assume(x, odd=True) & Assume(y, odd=True)) == False
+ assert query(x+y, odd=True, assumptions=Assume(x, odd=True) & Assume(y, even=True)) == True
+ assert query(x-y, odd=True, assumptions=Assume(x, even=True) & Assume(y, odd=True)) == True
+ assert query(x-y, odd=True, assumptions=Assume(x, odd=True) & Assume(y, odd=True)) == False
+
+ assert query(x+y+z, odd=True, assumptions=Assume(x, odd=True) & Assume(y, odd=True) & \
+ Assume(z, even=True)) == False
+ assert query(x+y+z+t, odd=True, assumptions=Assume(x, odd=True) & Assume(y, odd=True) & \
+ Assume(z, even=True) & Assume(t, integer=True)) == None
+
+ assert query(2*x + 1, odd=True, assumptions=Assume(x, integer=True)) == True
+ assert query(2*x + y, odd=True, assumptions=Assume(x, integer=True) & Assume(y, odd=True)) == True
+ assert query(2*x + y, odd=True, assumptions=Assume(x, integer=True) & Assume(y, even=True)) == False
+ assert query(2*x + y, odd=True, assumptions=Assume(x, integer=True) & Assume(y, integer=True)) == None
+ assert query(x*y, odd=True, assumptions=Assume(x, odd=True) & Assume(y, even=True)) == False
+ assert query(x*y, odd=True, assumptions=Assume(x, odd=True) & Assume(y, odd=True)) == True
+ assert query(2*x*y, odd=True, assumptions=Assume(x, rational=True) & Assume(x, rational=True)) == None
+ assert query(2*x*y, odd=True, assumptions=Assume(x, irrational=True) & Assume(x, irrational=True)) == None
+
+ assert query(abs(x), odd=True, assumptions=Assume(x, odd=True)) == True
+
+def test_prime():
+ x, y = symbols('x y')
+ assert query(x, prime=True, assumptions=Assume(x, prime=True)) == True
+ assert query(x, prime=True, assumptions=Assume(x, prime=False)) == False
+ assert query(x, prime=True, assumptions=Assume(x, integer=True)) == None
+ assert query(x, prime=True, assumptions=Assume(x, integer=False)) == False
+
+ assert query(2*x, prime=True, assumptions=Assume(x, integer=True)) == False
+ assert query(x*y, prime=True) == None
+ assert query(x*y, prime=True, assumptions=Assume(x, prime=True)) == None
+ assert query(x*y, prime=True, assumptions=Assume(x, integer=True) & \
+ Assume(y, integer=True)) == False
+
+ assert query(x**2, prime=True, assumptions=Assume(x, integer=True)) == False
+ assert query(x**2, prime=True, assumptions=Assume(x, prime=True)) == False
+ assert query(x**y, prime=True, assumptions=Assume(x, integer=True) & \
+ Assume(y, integer=True)) == False
+
+def test_positive():
+ x, y, z, w = symbols('xyzw')
+ assert query(x, positive=True, assumptions=Assume(x, positive=True)) == True
+ assert query(x, positive=True, assumptions=Assume(x, negative=True)) == False
+ assert query(x, positive=True, assumptions=Assume(x, zero=True)) == False
+ assert query(x, positive=True, assumptions=Assume(x, nonnegative=True)) == None
+ assert query(x, positive=True, assumptions=Assume(x, nonnegative=False)) == None
+
+ assert query(-x, positive=True, assumptions=Assume(x, positive=True)) == False
+ assert query(-x, positive=True, assumptions=Assume(x, negative=True)) == True
+
+ assert query(x+y, positive=True, assumptions=Assume(x, positive=True) & \
+ Assume(y, positive=True)) == True
+ assert query(x+y, positive=True, assumptions=Assume(x, positive=True) & \
+ Assume(y, negative=True)) == None
+
+ assert query(2*x, positive=True, assumptions=Assume(x, positive=True)) == True
+ assumptions = Assume(x, positive=True) & Assume(y, negative=True) & \
+ Assume(z, negative=True) & Assume(w, positive=True)
+ assert query(x*y*z, positive=True) == None
+ assert query(x*y*z, positive=True, assumptions=assumptions) == True
+ assert query(-x*y*z, positive=True, assumptions=assumptions) == False
+
+ assert query(x**2, positive=True, assumptions=Assume(x, positive=True)) == True
+ assert query(x**2, positive=True, assumptions=Assume(x, negative=True)) == True
+ assert query(x**2, positive=True, assumptions=Assume(x, nonnegative=True)) == None # could be 0
+
+ #exponential
+ assert query(exp(x), positive=True, assumptions=Assume(x, real=True)) == True
+ assert query(x + exp(x), positive=True, assumptions=Assume(x, real=True)) == None
+
+ #absolute value
+ assert query(abs(x), positive=True) == None # abs(0) = 0
+ assert query(abs(x), positive=True, assumptions=Assume(x, positive=True)) == True
+
+@XFAIL
+def test_positive_xfail():
+ assert query(1/(1 + x**2), positive=True, assumptions=Assume(x, real=True)) == True
+
+def test_real():
+ x, y = symbols('x y')
+ assert query(x, real=True) == None
+ assert query(x, real=True, assumptions=Assume(x, real=True)) == True
+ assert query(x, real=True, assumptions=Assume(x, zero=True)) == True
+ assert query(x, real=True, assumptions=Assume(x, zero=False) & Assume(x, real=True)) == True
+ assert query(x, real=True, assumptions=Assume(x, positive=True)) == True
+ assert query(x, real=True, assumptions=Assume(x, negative=True)) == True
+ assert query(x, real=True, assumptions=Assume(x, negative=True) | Assume(x, zero=True)) == True
+ assert query(x, real=True, assumptions=Assume(x, positive=True) | Assume(x, zero=True)) == True
+ assert query(x, real=True, assumptions=Assume(x, integer=True)) == True
+ assert query(x, real=True, assumptions=Assume(x, even=True)) == True
+ assert query(x, real=True, assumptions=Assume(x, prime=True)) == True
+
+ assert query(x/sqrt(2), real=True, assumptions=Assume(x, real=True)) == True
+ assert query(x/sqrt(-2), real=True, assumptions=Assume(x, real=True)) == False
+
+ I = S.ImaginaryUnit
+ assert query(x+1, real=True, assumptions=Assume(x, real=True)) == True
+ assert query(x+I, real=True, assumptions=Assume(x, real=True)) == False
+ assert query(x+I, real=True, assumptions=Assume(x, complex=True)) == None
+
+ assert query(2*x, real=True, assumptions=Assume(x, real=True)) == True
+ assert query(I*x, real=True, assumptions=Assume(x, real=True)) == False
+ assert query(I*x, real=True, assumptions=Assume(x, imaginary=True)) == True
+ assert query(I*x, real=True, assumptions=Assume(x, complex=True)) == None
+
+ assert query(x**2, real=True, assumptions=Assume(x, real=True)) == True
+ assert query(sqrt(x), real=True, assumptions=Assume(x, negative=True)) == False
+ assert query(x**y, real=True, assumptions=Assume(x, real=True) & \
+ Assume(y, integer=True)) == True
+ assert query(x**y, real=True, assumptions=Assume(x, real=True) & \
+ Assume(y, real=True)) == None
+ assert query(x**y, real=True, assumptions=Assume(x, positive=True) &\
+ Assume(y, real=True)) == True
+
+ # trigonometric functions
+ assert query(sin(x), real=True) == None
+ assert query(cos(x), real=True) == None
+ assert query(sin(x), real=True, assumptions=Assume(x, real=True)) == True
+ assert query(cos(x), real=True, assumptions=Assume(x, real=True)) == True
+
+ # exponential function
+ assert query(exp(x), real=True) == None
+ assert query(exp(x), real=True, assumptions=Assume(x, real=True)) == True
+ assert query(x + exp(x), real=True, assumptions=Assume(x, real=True)) == True
+
+ # complexes
+ assert query(re(x), real=True) == True
+ assert query(im(x), real=True) == True
+
+def test_zero():
+ x, y = symbols('xy')
+ assert query(x, zero=True) == None
+ assert query(x, zero=True, assumptions=Assume(x, positive=True)) == False
+ assert query(x, zero=True, assumptions=Assume(x, negative=True)) == False
+
+ assert query(x+y, zero=True) == None
+ assert query(x+y, zero=True, assumptions=Assume(x, positive=True) & Assume(y, positive=True)) == False
+ assert query(x+y, zero=True, assumptions=Assume(x, positive=True) & Assume(y, negative=True)) == None
+ assert query(x+y, zero=True, assumptions=Assume(x, negative=True) & Assume(y, negative=True)) == False
+
+ assert query(2*x, zero=True) == None
+ assert query(2*x, zero=True, assumptions=Assume(x, positive=True)) == False
+ assert query(2*x, zero=True, assumptions=Assume(x, negative=True)) == False
+ assert query(x*y, zero=True, assumptions=Assume(x, zero=False)) == None
+ assert query(x*y, zero=True, assumptions=Assume(x, zero=False) & Assume(y, zero=False)) == False
+
+ assert query(abs(x), zero=True) == None
+ assert query(abs(x), zero=True, assumptions=Assume(x, zero=False)) == False
+
+def test_global():
+ """Test query with global assumptions"""
+ x = symbols('x')
+ assert query(x, integer=True) == None
+ register_global_assumptions(Assume(x, integer=True))
+ assert query(x, integer=True) == True
+ clean_global_assumptions()
+ assert query(x, integer=True) == None
+
+def test_incompatible_resolutors():
+ x = symbols('x')
+ class Prime2QueryHandler(QueryHandler):
+ @staticmethod
+ def Number(expr, assumptions):
+ return True
+ register_handler('prime', Prime2QueryHandler)
+ raises(ValueError, 'query(4, prime=True)')
+
+def test_key_extensibility():
+ """test that you can add keys to the query system at runtime"""
+ x = Symbol('x')
+ # make sure thie key is not defined
+ raises(KeyError, "query(x, my_key=True)")
+ class MyQueryHandler(QueryHandler):
+ @staticmethod
+ def Symbol(expr, assumptions):
+ return True
+ register_handler('my_key', MyQueryHandler)
+ assert query(x, my_key=True) == True
+ assert query(x+1, my_key=True) == None
+ remove_handler('my_key', MyQueryHandler)
+
+def test_type_extensibility():
+ """test that new types can be added to the query system at runtime
+ We create a custom type MyType, and override query prime=True with handler
+ MyQueryHandler for this type
+
+ TODO: test incompatible resolutors
+ """
+ from sympy.core import Basic
+
+ class MyType(Basic):
+ pass
+
+ class MyQueryHandler(QueryHandler):
+ @staticmethod
+ def MyType(expr, assumptions):
+ return True
+
+ a = MyType()
+ register_handler('prime', MyQueryHandler)
+ assert query(a, prime=True) == True
--
1.6.2.2
diff --git a/doc/src/modules.txt b/doc/src/modules.txt
index 0816df0..ae5bbdb 100644
--- a/doc/src/modules.txt
+++ b/doc/src/modules.txt
@@ -17,6 +17,7 @@ access any SymPy module, or use this contens:
:maxdepth: 2
modules/core.txt
+ modules/concrete.txt
modules/evalf.txt
modules/functions.txt
modules/geometry.txt
@@ -26,14 +27,14 @@ access any SymPy module, or use this contens:
modules/logic.txt
modules/matrices.txt
modules/mpmath/index.txt
- modules/rewriting.txt
modules/polynomials.txt
modules/printing.txt
modules/plotting.txt
+ modules/queries.txt
+ modules/rewriting.txt
modules/series.txt
modules/simplify.txt
modules/statistics.txt
- modules/concrete.txt
modules/solvers.txt
modules/utilities/index.txt
diff --git a/doc/src/modules/queries.txt b/doc/src/modules/queries.txt
new file mode 100644
index 0000000..0d665cb
--- /dev/null
+++ b/doc/src/modules/queries.txt
@@ -0,0 +1,375 @@
+Query module
+============
+
+.. module:: sympy.queries
+
+Queries are used to ask information about expression. Main method in this
+module is function query:
+
+.. automethod:: sympy.queries.query
+
+Assumptions
+===========
+
+query has a keyword argument assumptions. It's value should be a boolean
+expression involving assumptions about objects in expr. Valid values include:
+
+ * Assume(x, integer=True)
+ * Assume(x, integer=False)
+ * Assume(x, integer=True) & Assume(x, positive=True)
+ * etc.
+
+See documentation for the logic module for a complete list of valid boolean
+expressions.
+
+
+Supported queries
+=================
+
+bounded
+-------
+
+Test that a function is bounded with respect to it's variables. For example,
+sin(x) is a bounded functions, but exp(x) is not.
+
+Examples::
+
+ >>> from sympy import *
+ >>> x = Symbol('x')
+ >>> query(exp(x), bounded=True)
+ False
+ >>> query(exp(x), bounded=True , assumptions=Assume(x, bounded=True))
+ True
+ >>> query(sin(x), bounded=True)
+ True
+
+
+commutative
+-----------
+
+Test that objects are commutative. By default, symbols in SymPy are considered
+commutative except otherwise stated
+
+Examples::
+
+ >>> from sympy import *
+ >>> x, y = symbols('x y')
+ >>> query(x, commutative=True)
+ True
+ >>> query(x, commutative=True, assumptions=Assume(x, commutative=False))
+ False
+ >>> query(x*y, commutative=True, assumptions=Assume(x, commutative=False))
+ False
+
+
+complex
+-------
+
+Test that expression belongs to the field of complex numbers.
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(2, complex=True)
+ True
+ >>> query(I, complex=True)
+ True
+ >>> x, y = symbols('x y')
+ >>> query(x+I*y, complex=True, assumptions=Assume(x, real=True) & Assume(y, real=True))
+ True
+
+
+even
+----
+
+Test that expression represents an even number, that is, an number that
+can be written in the form 2*n, n integer.
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(2, even=True)
+ True
+ >>> n = Symbol('n')
+ >>> query(2*n, even=True, assumptions=Assume(n, integer=True))
+ True
+
+
+extended_real
+-------------
+
+Test that an expression belongs to the field of extended real numbers, that is, real
+numbers union {Infinity, -Infinity}
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(oo, extended_real=True)
+ True
+ >>> query(2, extended_real=True)
+ True
+ >>> query(x, extended_real=True, assumptions=Assume(x, real=True))
+ True
+
+
+imaginary
+---------
+
+Test that an expression belongs to the field of imaginary numbers, that is,
+ it can be written as x*I, where x is real and I is the imaginary unit.
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(2*I, imaginary=True)
+ True
+ >>> x = Symbol('x')
+ >>> query(x*I, imaginary=True, assumptions=Assume(x, real=True))
+ True
+
+
+infinitesimal
+-------------
+
+Test that an expression is equivalent to an infinitesimal number.
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(1/oo, infinitesimal=True)
+ True
+ >>> x, y = symbols('x y')
+ >>> query(2*x, infinitesimal=True, assumptions=Assume(x, infinitesimal=True))
+ True
+ >>> query(x*y, infinitesimal=True, assumptions=Assume(x, infinitesimal=True) & Assume(y, bounded=True))
+ True
+
+
+integer
+-------
+
+Test that an expression belongs to the field of integer numbers
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(2, integer=True)
+ True
+ >>> query(sqrt(2), integer=True)
+ False
+ >>> x = Symbol('x')
+ >>> query(x/2, integer=True, assumptions=Assume(x, even=True))
+ True
+
+
+irrational
+----------
+
+Test that an expression represents an irrational number.
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(pi, irrational=True)
+ True
+ >>> query(sqrt(2), irrational=True)
+ True
+ >>> query(x*sqrt(2), irrational=True, assumptions=Assume(x, rational=True))
+ True
+
+
+rational
+--------
+
+Test that an expression represents a rational number.
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(Rational(3, 4), rational=True)
+ True
+ >>> x, y = symbols('x y')
+ >>> query(x/2, rational=True, assumptions=Assume(x, integer=True))
+ True
+ >>> query(x/y, rational=True, assumptions=Assume(x, integer=True) & Assume(y, integer=True))
+ True
+
+
+negative
+--------
+
+Test that an expression is less (strict) than zero.
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(0.3, negative=True)
+ False
+ >>> x = Symbol('x')
+ >>> query(-x, negative=True, assumptions=Assume(x, positive=True))
+ True
+
+Remarks
+^^^^^^^
+negative numbers are defined as real numbers that are not zero nor positive, so
+complex numbers (with nontrivial imaginary coefficients) will return False
+in this query. The same applies to query positive.
+
+
+positive
+--------
+
+Test that a given expression is greater (strict) than zero.
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(0.3, positive=True)
+ True
+ >>> x = Symbol('x')
+ >>> query(-x, positive=True, assumptions=Assume(x, negative=True))
+ True
+
+Remarks
+^^^^^^^
+see Remarks for negative
+
+
+prime
+-----
+
+Test that an expression represents a prime number.
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(13, prime=True)
+ True
+
+Remarks: Use sympy.ntheory.isprime for efficiently test numeric values
+
+
+real
+----
+
+Test that an expression belongs to the field of real numbers.
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(sqrt(2), real=True)
+ True
+ >>> x, y = symbols('x y')
+ >>> query(x*y, real=True, assumptions=Assume(x, real=True) & Assume(y, real=True))
+ True
+
+
+odd
+---
+
+Test that an expression represents an odd number.
+
+Examples::
+
+ >>> from sympy import *
+ >>> query(3, odd=True)
+ True
+ >>> n = Symbol('n')
+ >>> query(2*n + 1, odd=True, assumptions=Assume(n, integer=True))
+ True
+
+
+zero
+----
+
+Test that an expression is zero. This is mostly used for assumptions.
+
+Examples::
+
+ >>> from sympy import *
+ >>> x = Symbol('x')
+ >>> query(x, negative=True, assumptions=Assume(x, real=True) & Assume(x, positive=False) & Assume(x, zero=False))
+ True
+
+Note: To solve equations, use solve() instead
+
+
+Design
+======
+
+Each time query is called, the appropriate Handler for the current key is called. This is
+always a subclass of sympy.queries.QueryHandler. It's classmethods have the name's of the classes
+it supports. For example, a (simplified) QueryHandler for the query 'positive' would
+look like this::
+
+ class QueryPositiveHandler(CommonHandler):
+
+ def Mul(self):
+ # return True if all argument's in self.expr.args are positive
+ ...
+
+ def Add(self):
+ for arg in self.expr.args:
+ if not query(arg, positive=True, self.assumptions):
+ break
+ else:
+ # if all argument's are positive
+ return True
+ ...
+
+The .Mul() method is called when self.expr is an instance of Mul, the Add method
+would be called when self.expr is an instance of Add and so on.
+
+
+Extensibility
+=============
+
+You can define new queries or support new types by subclassing sympy.queries.QueryHandler
+ and registering that handler for a particular key by calling register_handler:
+
+.. automethod:: sympy.queries.register_handler
+
+You can undo this operation by calling remove_handler.
+
+.. automethod:: sympy.queries.remove_handler
+
+You can support new types [1]_ by adding a handler to an existing key. In the
+following example, we will create a new type MyType and extend the key 'prime'
+to accept this type (and return True)
+
+.. parsed-literal::
+
+ >>> from sympy.core import Basic
+ >>> from sympy.queries import register_handler
+ >>> from sympy.queries.handlers import QueryHandler
+ >>> class MyType(Basic):
+ ... pass
+ >>> class MyQueryHandler(QueryHandler):
+ ... @staticmethod
+ ... def MyType(expr, assumptions):
+ ... return True
+ >>> a = MyType()
+ >>> register_handler('prime', MyQueryHandler)
+ None
+ >>> query(a, prime=True)
+ True
+
+
+Performance improvements
+========================
+
+On queries that involve symbolic coefficients, logical inference is used. Work on
+improving satisfiable function (sympy.logic.inference.satisfiable) should result
+in notable speed improvements.
+
+Logic inference used in one query could be used to speed up further queries, and
+current system does not take advantage of this. For example, a truth maintenance
+system (http://en.wikipedia.org/wiki/Truth_maintenance_system) could be implemented.
+
+Misc
+====
+
+You can find more examples in the in the form of test under directory sympy/query/tests/
+
+.. [1] New type must inherit from Basic, otherwise an exception will be raised.
+ This is a bug and should be fixed.
--
1.6.2.2
Vinzent
> Yes, I also considered this approach, but for that I would need an
> object GlobalAssumptions with methods .Add(), .Remove(), .Clean(). Plus,
> this object should be a singleton of provide some way of preserving
> data. I just felt that it was too complicated, while current approach is
> much simpler (but I am willing to change it if there is a good reason to
> do so).
I think an object would be much cleaner, because it does not pollute
the namespace. In my opinion it's not more complicated, I'd implement
it if you don't want to. ;)
Something along the lines
class GlobalAssumptions(set):
def clear():
...
Vinzent
2009/7/21 Fabian Pedregosa <fab...@fseoane.net>:
2 colons?
> +
> +.. automethod:: sympy.queries.query
> +
> +Assumptions
> +===========
> +
> +query has a keyword argument assumptions. It's value should be a boolean
> +expression involving assumptions about objects in expr. Valid values include:
> +
> + Â Â * Assume(x, integer=True)
> + Â Â * Assume(x, integer=False)
> + Â Â * Assume(x, integer=True) & Assume(x, positive=True)
> + Â Â * etc.
> +
> +See documentation for the logic module for a complete list of valid boolean
> +expressions.
> +
What about lowercase 'assume'? For the use there is no difference
between ask() and assume(), and integrate() (at some point also
solve()) could also return a class, so this is maybe more consistent.
Dot?
Dot?
Dot?
So positive=True and negative=True is equivalent to nonzero=True?
> +
> +prime
> +-----
> +
> +Test that an expression represents a prime number.
> +
> +Examples::
> +
> + Â Â >>> from sympy import *
> + Â Â >>> query(13, prime=True)
> + Â Â True
> +
> +Remarks: Use sympy.ntheory.isprime for efficiently test numeric values
> +
Dot?
I think contradictory arguments should also be covered. (Things like
Assume(integer=False, odd=True).)
Are 2 colons necessary? I'm not sure...
> +
> +.. automethod:: sympy.queries.register_handler
> +
> +You can undo this operation by calling remove_handler.
> +
> +.. automethod:: sympy.queries.remove_handler
> +
> +You can support new types [1]_ by adding a handler to an existing key. In the
> +following example, we will create a new type MyType and extend the key 'prime'
> +to accept this type (and return True)
A dot?
Thank you.
Vinzent
I meant the documentation. What do you think, should
>>> Assume(x, integer=True, positive=True)
raise an exception or should it return
Assume(x, integer=True) & Assume(x, positive=True)?
Vinzent
Those 4 patches are +1.
Ondrej
I see what you mean:
>>> Assume(x, integer=True, positive=True)Traceback (most recent call
last):
File "<console>", line 1, in <module>
File "./sympy/assumptions/__init__.py", line 55, in __init__
raise ValueError('Wrong set of arguments')
ValueError: Wrong set of arguments
I think we should assume the and operator for multiple keyword
arguments. At any rate, I think "Wrong set of arguments" does not
explain clearly enough what the error was.
I had been working under the assumption that multiple arguments worked
like they do in the current assumptions system with my above example.
Trying Assume(x, integer=False) & Assume(x, odd=True) just returns
And(Assume(x, integer=False), Assume(x, odd=True)).
and Assume(x, integer=True, odd=True) just raises the same exception
as the example you give.
Is there supposed to be a function or method to reduce something like
And(Assume(x, integer=False), Assume(x, odd=True)) to an inconsistency
or something like And(Assume(x, integer=True), Assume(x, odd=False))
to Assume(x, even=True)? I couldn't find one.
Aaron Meurer
This is a nice concept, we can later implement helper methods that are
more conveniant to use.
Vinzent
It would be a handy shortcut though.
Vinzent
Definitely. Let's get this in, we need to start getting rid of old
assumptions now.
Ondrej
Yes, please do so. Let's merge now. If you could get things running
(=done:) till this Friday, it'd be awesome. Luke and Aaron will come,
so we can hack on this together.
Ondrej
Yeah, let's get it merged. In the long run I would like such syntax:
Assume(x > 0)
Assume(x in RR) == Assume(x, rational=True)
Do you think the "in" syntax could replace the keyword argument
syntax? The latter one does not make much sense for relational
assumptions, e.g.:
Assume(x > y, positive=True)
But we can implement this before the interface gets stable (i.e.
before a release).
Vinzent
It is possible to overwrite __contains__ but sadly Python seems to
force booleans as a returned type.
Vinzent
I agree. But let's get it in now.
Ondrej
2009/8/5 Ondrej Certik <ond...@certik.cz>:
>
> Looks good in general, but before we push this in, please improve the
> doctest coverage to 100%:
>
> $ bin/coverage_doctest.py sympy/assumptions/assume.py
> ----------------------------------------------------------------------
> sympy/assumptions/assume.py
>
> Missing documentation:
> Â Â Â Â * expr(self)
> Â Â Â Â * key(self)
> Â Â Â Â * value(self)
>
>
> Missing doctests:
> Â Â Â Â * list_global_assumptions()
> Â Â Â Â * remove_global_assumptions(*assump)
> Â Â Â Â * clean_global_assumptions()
> Â Â Â Â * eliminate_assume(expr, symbol=None)
>
>
> Indirect doctest (function name doesn't occur in doctests):
> Â Â Â Â * register_global_assumptions(*assump)
>
> Use "# indirect doctest" in the docstring to surpress this warning
> SCORE sympy/assumptions/assume.py: 12% (1 of 8)
> ----------------------------------------------------------------------
>
>
>
> The same about the handlers/, do you think there should be no example
> doctests? I think there should, at least in the classes, but I think
> it should be in all methods. I have no idea how to use it without the
> doctests.
I'd like to remove all the global assumptions functions and replace it
with an ordinary Python set of assumptions, for simplicity's sake. (It
already has add(), remove(), clear(), copy() and other stuff which
could be nice when working with different "contexts" of assumptions.)
If you agree, I'll go for it. :)
Vinzent
Do you mean the old assumptions, or something else?
Ondrej
I meant these methods in the new assumptions branch:
* list_global_assumptions()
* remove_global_assumptions(*assump)
* clean_global_assumptions()
Vinzent
Yes, then I am definitely +1. But let's wait for Fabian.
Ondrej
Cool, looking forward.
Ondrej
#assume.py#
file?
let's put all the docstrings into the classes and just use sphinx
ability to include those docstrings. This is really important, so that
people can just read docstrings and understand what things are doing.
I don't want to hold it anymore, so if you are all ok to push it in,
let's do it now. After you explain the purpose of #assume.py#.
Ondrej
Thanks!
Ondrej