2017-07-16 5 views
0

sympyでブール型変数を含む関数の派生を取ろうとしています。ブーリアン付きsympy派生

マイ期待される結果:

真または偽であるブール値に応じて、2つの異なる誘導体(すなわち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)) 

分-機能BOはTrueまたはFalseであることのためのxの閾値が4.29 ...、これ正と実際のだろう私を示しています。

出力:

TypeError: cannot determine truth value of Relation 

私は、真理値がシンボルであるX、に依存していることを理解しています。したがって、xを知らなくても、boを決定することはできない。

しかし、ボーが象徴的なところで私の期待した結果を得るにはどうすればよいでしょうか?

答えて

1

まず、上に貼り付けた方法でコード内で何が起こっているのかを慎重に検討することをお勧めします。最初にいくつかのsympy関数を定義します。

fct1 = sy.Function("fct1") 

だからこの後、fct1は未定義sympy.Functionある - それはその引数は、関数がどのように見えるかあり、またどのようなどちらも指定されていないという意味で未定義。

しかし、その後、あなたはこの時点で、fct1sympy.Function、またはそのことについては、sympy対象でなくなっていること、しかし

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

ノートのように、明示的に同じ名前の関数を定義する:あなたは上書き古い定義であり、今はちょうど普通のPython関数です!

これはまた、あなたがエラーを取得する理由です:あなたはbo(x)を呼び出すときに、Pythonは

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

を評価し、bo()のあなたの定義に従って値を返そうとします。しかし、Pythonは上記が真であるかどうか(またはその比較を行う方法)を知らないので、それは不平を言う。コードのように、あなたは、単に、例えばsympy表現を、使用することができ、代わりにPython関数の

  1. 私は2つの変更を示唆しています

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

    はあなたの条件の真理値を取得するには、私は肯定的に負の引数に0と評価さHeaviside function (wiki)、とに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) 

2つのコメント

bo = sy.Heaviside(y - fct1) 

(1)現在の実装では、デフォルトでsympy.Heaviside(0)を評価しません。これは周囲に異なる定義があるからです(あるものは1、それ以外のものは1/2)。あなたはOPの(弱い)不平等に従うことを1にしたいと思うでしょう。これはsympyの古いバージョンではサポートされていません

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

:1.1 sympyでは、これはあなたがHeaviside(0)のに評価したいものは何でも、すなわち、Heavisideに追加の引数を渡すことによって達成することができます。

(2)あなたのFOC2には、Heavisideという用語も含まれています。私がこれについて気に入っているのは、この表現で作業を続けることができるということです。二次微分などをしたいとしたらどうでしょうか。読みやすさのために、断片的な表現を好む場合は問題ありません。次の行をそのまま使用してください。

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

これは自動的に区分機能に変換されます。

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

残念ながら、私は私で1.1作業sympyを持っていない。(2)一緒に(1)を使用するのが最善と - ((0)= 0.5より古いバージョンで、これは自動的に暗黙的にヘビサイドを使用することに注意してください今手とだけ古いコードをテストすることができ

つ以上noteconcerningのsympyの区分関数:初期のコードで

sy.init_printing() 

を挿入することにより、sympyのラテックス印刷を使用した場合、彼らははるかに読みやすいです

(免責事項:私は決してsympyの専門家ではなく、そこに他の、好ましい解決策があるかもしれません。ただ提案しようとしています!)

+0

この提案と私のコードへのコメントありがとう。あなたのアイデアは、私が提起した質問に対してうまくいきます。 FOCsを取った後wrt。いくつかの象徴的な変数、私はこれらの象徴的な変数のためのFOCのシステムを解決しようとしています。私はHeavisideでそれをすることができないように見えますか? sy.solve_triangulatedを使用すると、Heaviside式にジェネレータの要素が含まれていることを示すPolynomialErrorが返されます。何かご意見は? –