1

テキストを解ける方程式に操作する一般的なPythonの方法を探しています。

例えば:

初期化する定数があるかもしれません

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)

これは5つの未知数を残すので、おそらくシステムは解決できます。

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()関数を試しましたが、構造化された内訳が表示されるようです。

誰もが最善のアプローチについていくつかのアイデアを与えることができますか?

4

2 に答える 2

2

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

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

反復 #1: 変数を x 配列要素に直接置き換えることを除いて、反復 #0 と同じことを行います。したがって、'y' は 'x[1]' になります。実際、これらすべてを実行して関数文字列を生成できます。「def f(x): return 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 を使用) で解けない無害な非線形方程式がかなりあります。おそらく、最初の推測を入力する方法も必要でしょう。

これを行う他の代替方法があるかどうか聞いてみたいと思います。

于 2009-07-25T06:17:07.700 に答える
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 を使用する必要がありましたが、これにより、処理がより困難な具体的な構文ツリーが得られました。

于 2009-07-23T04:41:15.557 に答える