2017-02-03 69 views
1

我正在使用Python和Sympy。在Python中评估Sympy布尔表达式

我有以下几点:

x,y,z = Symbols('x,y,z') 
doc = {x : False, y : True, z: True} 
rule = Or(x, And(y,z)) 

我要寻找一个在Sympy一个函数,将在rule.eval(doc)返回True

编辑: 目前我正在使用rule.subsrule.xreplace两个缓慢地执行,每次调用约0.0003秒。这使得它不切实际。

+0

我想知道你为什么不能做'rule.subs(doc)'? –

+0

嗨,你是对的,我没有提到它。这就是我所使用的'rule.subs'和'rule.xreplace',它们都按预期工作,但具有可怕的性能。我已经分析了我的代码,发现每次执行大约需要0.0003秒。我使用这些功能很多。我正在寻找更有效的方法 –

+0

而且您必须使用sympy?如果没有,那么你可以这样做:'将操作符导入为op; rule = lambda x,y,z:op.or_(x,op.and_(y,z));规则(假,真,真)'。不提供字典,因为它是但更快。 –

回答

1

一种方式来获得用最少的代码更好的性能是使用lambdify

X = tuple(doc.iterkeys()) 
f = lambdify(X, rule) 

在此之后IPython都递给我:

V = tuple(doc.itervalues()) 
%timeit f(*V) 
The slowest run took 7.56 times longer than the fastest. This could mean that an intermediate result is being cached. 
1000000 loops, best of 3: 209 ns per loop 

我不知道该警告可能有多大影响的结论,但有明显的改善。在与原始代码相同的计算机上:

%timeit rule.xreplace(doc) 
10000 loops, best of 3: 126 µs per loop 

而且subs更慢。

0

而不是使用潜艇你可以使用直接评估?

>>> F = Lambda((x, y, z), Or(x, And(y, z))) 
>>> F(0, 1, 1) 
True 

如果不是,你可以创建一个玩具类,允许通过lambda表单的subs?这不是一个类,但它给人的想法:

>>> def sub(f, d): 
...  F = Lambda(d.keys(), f) 
...  return F(*[d[k] for k in d.keys()]) 
>>> sub(Or(x,And(y,z)),{x:0,y:1,z:1}) 

类将创建拉姆达形式,并有潜艇方法,该方法将返回评估LAMBDA形式。