Skip to content

Commit

Permalink
implement local assumptions
Browse files Browse the repository at this point in the history
The basic idea is to define a "hiddden" variable in the local scope to store
the local assumptions. Many thanks to Felix Kaiser who helped me a lot
implementing this!
  • Loading branch information
vks committed Apr 4, 2010
1 parent 9210ba6 commit bfc837b
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 3 deletions.
3 changes: 2 additions & 1 deletion sympy/assumptions/__init__.py
@@ -1,3 +1,4 @@
from assume import Assume, global_assumptions
from assume import (Assume, global_assumptions, set_local_assumptions,
get_local_assumptions)
from ask import Q, ask, register_handler, remove_handler
from refine import refine
34 changes: 33 additions & 1 deletion sympy/assumptions/assume.py
@@ -1,5 +1,6 @@
# doctests are disabled because of issue #1521
from sympy.core import Basic, Symbol
import inspect

class AssumptionsContext(set):
"""Set representing assumptions.
Expand All @@ -26,11 +27,42 @@ class to create your own local assumptions contexts. It is basically a thin
def add(self, *assumptions):
"""Add an assumption."""
for a in assumptions:
assert isinstance(a, Assume), 'can only store instances of Assume'
assert type(a) is Assume, 'can only store instances of Assume'
super(AssumptionsContext, self).add(a)

# TODO: get rid of this
global_assumptions = AssumptionsContext()

LOCALCONTEXT = '__sympy_local_assumptions'

def set_local_assumptions():
"""Set a local assumption context and return it.
By default, this is done in the current local scope, this can be changed
using the `scope` argument.
This will overwrite any previous (local) assumptions."""
f = inspect.currentframe().f_back
c = AssumptionsContext()
f.f_locals[LOCALCONTEXT] = c
return c

def get_local_assumptions():
"""Return the current local assumption context.
This can be in an outer scope if `set_local_assumptions()` has not been yet
called in the current scope.
If there is no defined assumption context in any scope, None is returned.
"""
f = inspect.currentframe()
while f.f_back is not None:
f = f.f_back
result = f.f_locals.get(LOCALCONTEXT)
if result is not None:
return result
return None

class Assume(Basic):
"""New-style assumptions.
Expand Down
19 changes: 18 additions & 1 deletion sympy/assumptions/tests/test_assumptions_2.py
@@ -1,6 +1,7 @@
"""rename this to test_assumptions.py when the old assumptions system is deleted"""
from sympy.core import symbols
from sympy.assumptions import Assume, global_assumptions
from sympy.assumptions import (Assume, global_assumptions, get_local_assumptions,
set_local_assumptions, ask, Q)
from sympy.assumptions.assume import eliminate_assume
from sympy.printing import pretty

Expand Down Expand Up @@ -54,3 +55,19 @@ def test_global():
global_assumptions.clear()
assert not Assume(x>0) in global_assumptions
assert not Assume(y>0) in global_assumptions

def test_local():
x, y = symbols('x y')
set_local_assumptions()
a = get_local_assumptions()
a.add(Assume(x, Q.positive))
def localfunc():
assert Assume(x, Q.positive) in get_local_assumptions()
assert ask(x, Q.positive) == True
b = set_local_assumptions()
assert not b is a
b.add(Assume(x, Q.negative))
assert ask(x, Q.positive) == False
localfunc()
assert a
assert ask(x, Q.positive) == True

0 comments on commit bfc837b

Please sign in to comment.