2017-07-16 65 views
0

我正在嘗試將帶有sympy的布爾變量的函數派生出來。帶布爾值的sympy衍生物

我的預期的結果:

兩種不同的衍生物,這取決於布爾型用True或False(即1或0)。

例子:

import sympy as sy 
c, x = sy.symbols("c x", positive=True, real=True) 
bo = sy.Function("bo") 
fct1 = sy.Function("fct1") 
fct2 = sy.Function("fct2") 
FOC2 = sy.Function("FOC2") 
y = 5 
a = 2 
b = 4 


def fct1(x): 
    return -0.004*x**2 + 0.25*x + 4 
# the following gives the smaller positive intercept with the x-axis) 
# this intercept is the threshold value for the boolean function, bo 
min(sy.solve(fct1(x)-y, x)) 


def bo(x): 
    if fct1(x) <= y: 
     return 1 
    else: 
     return 0 


def fct2(c, x): 
    return a + b*c + bo(x)*c 


def FOC2(c, x): 
    return sy.diff(fct2(c, x), c) 
print(FOC2(c, x)) 

的最小功能的意見後,顯示我的x爲博是真或假是4.29 ... ...,從而積極和現實的門檻。

輸出:

TypeError: cannot determine truth value of Relation 

我明白,真值取決於X,這是一個象徵。因此,在不知道x的情況下,無法確定博。

但是,如何得到我的預期結果,其中博是象徵性的?

回答

1

首先,我建議您仔細考慮代碼上面粘貼的方式。你首先定義一些sympy函數,例如

fct1 = sy.Function("fct1") 

所以在此之後,fct1是一個未定義的sympy.Function - 在這個意義上,它既不指定什麼它的參數是,也不是功能樣子不確定的。

但是,那麼你明確地定義相同名稱的功能,如

def fct1(x): 
    return -0.004*x**2 + 0.25*x + 4 

不過請注意,在這一點,fct1不再是sympy.Function,或任何與此有關sympy對象:您覆蓋舊的定義,現在它只是一個普通的Python函數!

這也是你的錯誤的原因:當你打電話bo(x),蟒蛇試圖評估

-0.004*x**2 + 0.25*x + 4 <= 5 

,並返回根據您的bo()定義的值。但python不知道以上是否屬實(或如何進行比較),所以它抱怨。

我建議2點的變化:

  1. ,而不是蟒蛇功能,如代碼,你可以簡單地使用sympy表達式,如

    fct1 = -0.004*x**2 + 0.25*x + 4

  2. 爲了讓您的病情的真值,我會建議使用Heaviside function (wiki),其計算結果爲0負的參數,併爲1陽性。它在sympy中的實現是sympy.Heaviside。 你的代碼,那麼可以看看如下:上線

import sympy as sy 
c, x = sy.symbols("c x", positive=True, real=True) 
y = 5 
a = 2 
b = 4 


fct1 = -0.004*x**2 + 0.25*x + 4 
bo = sy.Heaviside(y - fct1) 
fct2 = a + b*c + bo * c 

FOC2 = sy.diff(fct2, c) 

print(FOC2) 

兩點意見

bo = sy.Heaviside(y - fct1) 

(1)當前的實現並不默認評估sympy.Heaviside(0);這是因爲周圍有不同的定義(有些定義爲1,其他1/2)。你希望它是1,以符合OP中的(弱)不平等。

bo = sy.Heaviside(y - fct1, 1) 

這不是在舊版本sympy的支持:在sympy 1.1,這可以通過傳遞一個額外的參數來Heaviside,即無論你想Heaviside(0)評估來實現。 (2)您將得到您的FOC2,再次涉及Heaviside條款。我喜歡這一點,就是你可以繼續使用這個表達方式,比如說如果你想獲得第二個導數等等。如果出於可讀性的原因,您更喜歡分段表達式 - 沒有問題。只需更換相應的行

bo = sy.Heaviside(y - fct1)._eval_rewrite_as_Piecewise(y-fct1) 

這將自動轉換爲分段函數。 (請注意,在舊版本中,這個自動隱式使用亥(0)= 0.5 - 最好用(1)和(2)一起:

bo = sy.Heaviside(y - fct1, 1)._eval_rewrite_as_Piecewise(y-fct1) 

不幸的是,我沒有工作sympy 1.1在我手,現在只能測試舊代碼

一個更noteconcerning sympy的分段函數:他們更具可讀性,如果使用sympy的膠乳印染,通過插入

sy.init_printing() 

代碼早

(免責聲明:我絕不是sympy的專家,可能還有其他更好的解決方案。只是想提出建議!)

+0

感謝您的建議和對我的代碼的評論。你的想法對我提出的問題很有效。在採取FOCs之後。一些符號變量,我試圖解決這些符號變量的FOCs系統。看起來我無法用海維思來做到這一點?使用sy.solve_triangulated會給我一個PolynomialError,說明Heaviside表達式包含發生器集的一個元素。有什麼想法嗎? –