2009-07-23 1 views
1

私は、テキストを解く方程式に変換するための一般的なPythonの方法を探しています。例えばソルバの方程式を再整理する

これは5を離れる

e1,e2=0.58,0.62 
ma1,ma2=0.85,1.15 
mw=0.8 
Cpa,Cpw=1.023,4.193 
dba,dbr=0.0,25.0 

を初期化するためにいくつかの定数および(ソルバではなく、読みやすくするためにここに書かれた)の方程式の組

Q=e1*ma1*Cpa*(tw1-dba) 
Q=ma1*Cpa*(dbs-dba) 
Q=mw*Cpw*(tw1-tw2) 
Q=e2*ma2*Cpa*(dbr-tw2) 
Q=ma2*Cpa*(dbr-dbo) 

があってもよいですおそらくシステムを解決することができます。

Q, dbo, dbr, tw1, tw2 

実際のシステムは非線形であり、はるかに複雑です。

私はすでにscipy、Delphi、Sage ...でこの簡単な例を解決していますので、解決部分は探していません。

方程式はテキストエディタに直接入力されています。私はPythonプログラムに私に未知数の配列とエラー関数の配列を与えたいと思います。

y = mysolver.fsolve(f, x) 

ので、上記の例

x=[Q,dbo,dbr,tw1,tw2] 

f=[Q-e1*ma1*Cpa*(tw1-dba), Q-ma1*Cpa*(dbs-dba), Q-mw*Cpw*(tw1-tw2), 
    Q-e2*ma2*Cpa*(dbr-tw2), Q-ma2*Cpa*(dbr-dbo)] 

のために、私はただの未知数を抽出する方法を知っていると誤差関数を作成しないでください。

私はcompile.parse()関数を試しましたが、構造化された内訳を与えるようです。

誰もが最良のアプローチについていくつかのアイデアを提供できますか?

+0

"リスト"の構文を許可する必要がありますか? (a、b = 1,2)そうでなければアプローチする方が簡単かもしれません... – Stobor

+0

いいえ、私は定数割り当てをよりコンパクトにするためにしました。 個別に値を割り当てるのはどのように役立ちますか? –

+0

長い間、この問題を解決するユーレカというBorlandプログラムがありました。後で同じコードが著者によってMercuryとして発行されました。数年後、EES(Engineering Equation Solver)と呼ばれるWindowsプログラムが出てきましたが、ソルバーはユーレカほど良くはありませんでした。 私は最近、Clifford Wolfによっていくつかのコードを見つけました http://svn.clifford.at/tools/trunk/electrotools/eqsolver.html これはJavaScriptであり、率直に言って私は彼のロジックに従いません。これは私がPythonでやっているのとほとんど同じです。 –

答えて

1

独自の式言語用のパーサーを作成したくない場合は、実際にPython構文を使用できます。コンパイラモジュールを使用しないでください。その代わりに、何らかの抽象構文を使用します。 2.5以来、あなたは_astモジュールを使用することができます:以前のバージョンでは

py> import _ast                  
py> tree = compile("e1,e2=0.58,0.62", "<string>", "exec", _ast.PyCF_ONLY_AST) 
py> tree 
<_ast.Module object at 0xb7cd5fac>          
py> tree.body[0] 
<_ast.Assign object at 0xb7cd5fcc> 
py> tree.body[0].targets[0] 
<_ast.Tuple object at 0xb7cd5fec> 
py> tree.body[0].targets[0].elts 
[<_ast.Name object at 0xb7cd5e4c>, <_ast.Name object at 0xb7cd5f6c>] 
py> tree.body[0].targets[0].elts[0].id 
'e1' 
py> tree.body[0].targets[0].elts[1].id 
'e2' 

を、あなたはあなたのプロセスがより困難であるコンクリート構文木を与える、parser.suiteを使用しなければならないでしょう。

+0

私はこれをベクトルx = []とf = []に変換する方法を理解していません ここではevalを使わずにreを使って式を解析しています。コードのいくつかは非常に有望ですので、私はその考えを試してみます。 –

+0

このページ http://stackoverflow.com/questions/928563/code-golf-evaluating-mathematical-expressions –

2

実際、私はPythonでまったく同じことを実装しました。私もあなたが言及したユーレカと他のプログラムに精通しています。あなたはxyzsolve.appspot.comで私の実装を見ることができます(恥知らずなプラグインには申し訳ありません)。実装はすべてPythonで行われます。コードが実行された繰り返しのリストを示します。

繰り返し#0:式の各変数の置換を簡単に検索し、変数を値に置き換えます。例えば、xとyの値が1.1と2.2の場合、x * yは1.1 * 2.2になります。変換された文字列を取得したら、evalを使用してその値を残差(またはあなたの場合はfベクトル)に入れることができます。 Scipyのfsolve/fmin関数は、残った関数に追加の引数を渡すことができるので、それを利用します。私。それぞれの名前付き変数のインデックスを含む辞書を渡します。あなたの辞書には{'x':0、 'y':1}のようなものが含まれていれば、各方程式の検索と置き換えができます。これは機能しますが、残りの関数が呼び出されるたびに検索置換を行う必要があるため、非常にゆっくりとします。

反復#1:反復番号0と同じですが、変数をx配列要素で直接置き換えることを除いて、 'y'は 'x [1]'になります。実際には、これをすべて実行してファンクション文字列を生成することができます。 "def f(x):x [0] + x [1]、x [0] - x [1]"を返します。次に、pythonでexec関数を使用して、fsolve/fminに渡す関数を作成することができます。あなたの方程式が有効なpython構文の形式であれば、スピードが低下し、この時点で停止することができます。より広範な方程式の入力形式をサポートしたい場合は、この方法でもっと多くのことを行うことはできません。

反復#2:カスタムのレクサーとパーサーを実装します。これは聞こえるほど難しくありません。私はレクサーのためにhttp://www.evanfosmark.com/2009/02/sexy-lexing-with-python/を使用しました。私は、各方程式を解析するために、再帰的な降下パーサーを作成しました(これは100行ほどのコード行ではありません)。これにより、方程式形式の完全な柔軟性が得られます。私は、変数、別々のリストの方程式の各側に発生する定数を追跡しています。パーサーは方程式を解析すると、 'var_000 + var_001 * var_002'のような数式文字列を作成します。最後に、 'var_000'をxベクトルの適切なインデックスに置き換えます。だから 'var_000'は 'x [0]'になります。あなたが望むならば、ASTを構築してより多くの洗練された変換を行うことができますが、私はここで中止しました。

最後に、入力方程式のタイプも考慮する必要があります。 fsolve(MINPACK hybrdjを使用しています)で解くことのできない無害な非線形方程式がかなりあります。おそらく、最初の推測を入力する方法も必要です。

これを行う方法が他にもある場合は、私は興味があります。

関連する問題