Assumptions#
A module to implement logical predicates and assumption system.
Predicate#
- class sympy.assumptions.assume.Predicate(*args, **kwargs)[source]
Base class for mathematical predicates. It also serves as a constructor for undefined predicate objects.
Explanation
Predicate is a function that returns a boolean value [1].
Predicate function is object, and it is instance of predicate class. When a predicate is applied to arguments,
AppliedPredicate
instance is returned. This merely wraps the argument and remain unevaluated. To obtain the truth value of applied predicate, use the functionask
.Evaluation of predicate is done by multiple dispatching. You can register new handler to the predicate to support new types.
Every predicate in SymPy can be accessed via the property of
Q
. For example,Q.even
returns the predicate which checks if the argument is even number.To define a predicate which can be evaluated, you must subclass this class, make an instance of it, and register it to
Q
. After then, dispatch the handler by argument types.If you directly construct predicate using this class, you will get
UndefinedPredicate
which cannot be dispatched. This is useful when you are building boolean expressions which do not need to be evaluated.Examples
Applying and evaluating to boolean value:
>>> from sympy import Q, ask >>> ask(Q.prime(7)) True
You can define a new predicate by subclassing and dispatching. Here, we define a predicate for sexy primes [2] as an example.
>>> from sympy import Predicate, Integer >>> class SexyPrimePredicate(Predicate): ... name = "sexyprime" >>> Q.sexyprime = SexyPrimePredicate() >>> @Q.sexyprime.register(Integer, Integer) ... def _(int1, int2, assumptions): ... args = sorted([int1, int2]) ... if not all(ask(Q.prime(a), assumptions) for a in args): ... return False ... return args[1] - args[0] == 6 >>> ask(Q.sexyprime(5, 11)) True
Direct constructing returns
UndefinedPredicate
, which can be applied but cannot be dispatched.>>> from sympy import Predicate, Integer >>> Q.P = Predicate("P") >>> type(Q.P) <class 'sympy.assumptions.assume.UndefinedPredicate'> >>> Q.P(1) Q.P(1) >>> Q.P.register(Integer)(lambda expr, assump: True) Traceback (most recent call last): ... TypeError: <class 'sympy.assumptions.assume.UndefinedPredicate'> cannot be dispatched.
References
- eval(args, assumptions=True)[source]
Evaluate
self(*args)
under the given assumptions.This uses only direct resolution methods, not logical inference.
- handler = <dispatched AskPredicateHandler>
- classmethod register(*types, **kwargs)[source]
Register the signature to the handler.
- classmethod register_many(*types, **kwargs)[source]
Register multiple signatures to same handler.
- class sympy.assumptions.assume.AppliedPredicate(predicate, *args)[source]
The class of expressions resulting from applying
Predicate
to the arguments.AppliedPredicate
merely wraps its argument and remain unevaluated. To evaluate it, use theask()
function.Examples
>>> from sympy import Q, ask >>> Q.integer(1) Q.integer(1)
The
function
attribute returns the predicate, and thearguments
attribute returns the tuple of arguments.>>> type(Q.integer(1)) <class 'sympy.assumptions.assume.AppliedPredicate'> >>> Q.integer(1).function Q.integer >>> Q.integer(1).arguments (1,)
Applied predicates can be evaluated to a boolean value with
ask
:>>> ask(Q.integer(1)) True
- property arg
Return the expression used by this assumption.
Examples
>>> from sympy import Q, Symbol >>> x = Symbol('x') >>> a = Q.integer(x + 1) >>> a.arg x + 1
- property arguments
Return the arguments which are applied to the predicate.
- property function
Return the predicate.
Querying#
Queries are used to ask information about expressions. Main method for this
is ask()
:
- sympy.assumptions.ask.ask(proposition, assumptions=True, context={})[source]
Function to evaluate the proposition with assumptions.
- Parameters
proposition : Any boolean expression.
Proposition which will be evaluated to boolean value. If this is not
AppliedPredicate
, it will be wrapped byQ.is_true
.assumptions : Any boolean expression, optional.
Local assumptions to evaluate the proposition.
context : AssumptionsContext, optional.
Default assumptions to evaluate the proposition. By default, this is
sympy.assumptions.global_assumptions
variable.- Returns
True
,False
, orNone
- Raises
TypeError : proposition or assumptions is not valid logical expression.
ValueError : assumptions are inconsistent.
Explanation
This function evaluates the proposition to
True
orFalse
if the truth value can be determined. If not, it returnsNone
.It should be discerned from
refine()
which, when applied to a proposition, simplifies the argument to symbolicBoolean
instead of Python built-inTrue
,False
orNone
.Syntax
- ask(proposition)
Evaluate the proposition in global assumption context.
- ask(proposition, assumptions)
Evaluate the proposition with respect to assumptions in global assumption context.
Examples
>>> from sympy import ask, Q, pi >>> from sympy.abc import x, y >>> ask(Q.rational(pi)) False >>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) True >>> ask(Q.prime(4*x), Q.integer(x)) False
If the truth value cannot be determined,
None
will be returned.>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x None
ValueError
is raised if assumptions are inconsistent.>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) Traceback (most recent call last): ... ValueError: inconsistent assumptions Q.even(x) & Q.odd(x)
Notes
Relations in assumptions are not implemented (yet), so the following will not give a meaningful result.
>>> ask(Q.positive(x), x > 0)
It is however a work in progress.
See also
sympy.assumptions.refine.refine
Simplification using assumptions. Proposition is not reduced to
None
if the truth value cannot be determined.
ask
’s optional second argument should be a boolean expression involving
assumptions about objects in expr. Valid values include:
Q.integer(x)
Q.positive(x)
Q.integer(x) & Q.positive(x)
etc.
Q
is an object holding known predicates.
See documentation for the logic module for a complete list of valid boolean expressions.
You can also define a context so you don’t have to pass that argument
each time to function ask()
. This is done by using the assuming context manager
from module sympy.assumptions.
>>> from sympy import *
>>> x = Symbol('x')
>>> y = Symbol('y')
>>> facts = Q.positive(x), Q.positive(y)
>>> with assuming(*facts):
... print(ask(Q.positive(2*x + y)))
True
Contents#
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 ask could be used to speed up further queries, and current system does not take advantage of this. For example, a truth maintenance system (https://en.wikipedia.org/wiki/Truth_maintenance_system) could be implemented.
Misc#
You can find more examples in the form of tests in the directory
sympy/assumptions/tests/