2017-02-03 58 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形式。