web-dev-qa-db-ja.com

Sympyによって有限セットとして返されたソリューションセットから値を取得します

Python Sympyライブラリでスクリプトを作成し、solveset()関数とlinsolve()関数によって返された結果にアクセスしようとしています。私の問題は、これらの関数によって返されたオブジェクトが有限セット型であることですいくつかの結果を自動的に選択して、他の方程式に再入力したいのですが、任意のボディが役立ちますか?

例: 2つの未知の変数を含む方程式のリストを作成します:

>>> a1, a2 = symbols('a1, a2')
>>> eq2_1 = Eq(-3*a1/10 - 3*a2/20 + 1/12)
>>> eq2_2 = Eq(-3*a1/20 - 13*a2/105 + 1/20)
>>> lista = [eq2_1,eq2_2]
>>> str(lista)
[-3*a1/10 - 3*a2/20 + 1/12, -3*a1/20 - 13*a2/105 + 1/20]

次に、linsolve()メソッドで解決します。

>>> a = linsolve(lista,a1,a2)
>>> a
{(71/369, 7/41)} 

結果は正しいですが、これらの結果を変数に入れることができません。

Oは、dics、lists、tuples、indexingコマンドを試しましたが、常にエラーを返しました。 "Finitesetオブジェクトには属性 'command'がありません。"

私はこのリンクでsympyライブラリの方法を見つけました http://docs.sympy.org/latest/tutorial/manipulation.html

関数または結果オブジェクトで.args属性を使用します。機能がある場合:

>>>func = Eq(u(x),−x+sin(x)) 
>>>func
u(x) = -x + sin(x)
>>>func.args[0] 
u(x)
>>>func.args[1]
-x+sin(x)

有限集合型の結果についても同様です。

もう少し一般的な解決策は、単にFiniteSetを標準のpython listに変換することです。

>>> a=list(linsolve(lista,a1,a2))
>>> a
[(71/369, 7/41)]

次に、標準のインデックスを使用して要素を抽出できます—この場合はa[0]。しかし、複数のソリューションを入手した場合、必要なソリューションを引き出すことができます。

4
Mike

iterを使用してセットに基づくイテレータを取得し、次にnextを使用してそのセットの1つの要素を返すことができます(要素が1つだけ必要な場合)。

例:

from sympy import *
var('x y')
sol = linsolve([x+y-2, 2*x-3*y], x, y)
(x0, y0) = next(iter(sol))

ここで、x0は6/5、y0は4/5です。

4
user3717023

変だ。 linsolve の結果の使用方法はどこにも説明されていません。

specs でも、要素を個別にチェックすることなく、結果セット全体をテストするだけです。

シーケンスの解凍

方程式系が少なくとも1つの解を許容することがわかっている場合は、割り当ての前に末尾のコンマを付けて sequence unpacking を使用できます。

>>> from sympy import linsolve, symbols, solve, Rational
>>> a1, a2 = symbols('a1 a2')
>>> equations = [-3*a1/10 - 3*a2/20 + Rational(1, 12), -3*a1/20 - 13*a2/105 + Rational(1, 20)]
>>> equations
[-3*a1/10 - 3*a2/20 + 1/12, -3*a1/20 - 13*a2/105 + 1/20]
>>> linsolve(equations, a1, a2)
{(71/369, 7/41)}
>>> solution, = linsolve(equations, a1, a2)
>>> solution
(71/369, 7/41)

この構文は、無限の解がある場合にも機能します。

>>> solution, = linsolve([a1, a1], a1, a2)
>>> solution
(0, a2)

しかし、解決策がない場合は失敗します。

>>> solution, = linsolve([a1 - 1, a1 - 2], a1, a2)
ValueError: not enough values to unpack (expected 1, got 0)

これは望ましい振る舞いかもしれません。

ソリューションを反復する:

別の可能性は、ソリューションを単純に反復することです:

>>> for solution in linsolve(equations, a1, a2):
...     print(solution)
... 
(71/369, 7/41)

解決策がない場合は何も起こりません。

>>> for solution in linsolve([a1 - 1, a1 - 2], a1, a2):
...     print(solution)
... 

linsolveの代わりに解決する

solve の代わりにlinsolveを使用することもできます。ただし、プロジェクトでは 非推奨 ですが、異なるタイプを出力できるためです。

>>> solve(equations, a1, a2)
{a1: 71/369, a2: 7/41}
>>> solve([a1 - 1, a1 - 2], a1, a2)
[]
4
Eric Duminil

Tupleを引数の解凍と組み合わせて使用​​できます。

var('x y z')
eqs = [ x + y + z - 1, x + y + 2*z - 3 ]
sol = linsolve( eqs, x, y, z )
(x0, y0, z0) = Tuple(*sol)

これでソリューションを確認できます:

eqs[0].subs( [(x, x0), (y, y0), (z, z0)] )
eqs[1].subs( [(x, x0), (y, y0), (z, z0)] )
1
Stilunke