web-dev-qa-db-ja.com

Pythonで方程式を解くにはどうすればよいですか?

私が方程式を持っているとしましょう:

_2x + 6 = 12_

代数を使用すると、_x = 3_がわかります。 xを解くことができるPythonでプログラムを作成するにはどうすればよいですか?プログラミングに不慣れで、eval()およびexec()しかし、私がそれらを私が望むことをさせる方法を理解することはできません外部ライブラリ(例えば、SAGE)を使いたくありません、私は単なるPythonでこれをしたいです。

21
user1221937

SymPysolver は必要なもののように見えます。ライブラリを自分でビルドする場合は、ソースコードをご覧ください…

28
eumiro

この問題に取り組むには、数値的と記号的の2つの方法があります。

数値的に解決するには、最初に「実行可能な」関数としてエンコードする必要があります-値を保持し、値を取得します。例えば、

def my_function(x):
    return 2*x + 6

文字列を解析してそのような関数を自動的に作成することはかなり可能です。 2x + 6リストへ、[6, 2](リストインデックスはxの累乗に対応するため、6 * x ^ 0 + 2 * x ^ 1)。次に:

def makePoly(arr):
    def fn(x):
        return sum(c*x**p for p,c in enumerate(arr))
    return fn

my_func = makePoly([6, 2])
my_func(3)    # returns 12

次に、関数にx値を繰り返しプラグインし、結果と検索したいものとの差を調べ、そのx値を微調整して(できれば)差を最小化する別の関数が必要です。

def dx(fn, x, delta=0.001):
    return (fn(x+delta) - fn(x))/delta

def solve(fn, value, x=0.5, maxtries=1000, maxerr=0.00001):
    for tries in xrange(maxtries):
        err = fn(x) - value
        if abs(err) < maxerr:
            return x
        slope = dx(fn, x)
        x -= err/slope
    raise ValueError('no solution found')

ここには多くの潜在的な問題があります-関数が実際に解を持っていると仮定して(つまり、x ^ 2 + 2 = 0に対する実数値の答えがない)良い開始x値を見つけ、計算精度の限界に達し、しかし、この場合、エラー最小化関数が適切であり、良い結果が得られます。

solve(my_func, 16)    # returns (x =) 5.000000000000496

このソリューションは絶対に、正確に正しくないことに注意してください。それを完璧にする必要がある場合、または方程式のファミリーを解析的に解こうとする場合は、より複雑な獣、つまりシンボリックソルバーを使用する必要があります。

MathematicaやMapleなどのシンボリックソルバーは、代数、計算などに関する多くの組み込みルール(「知識」)を備えたエキスパートシステムです。 sinの導関数がcosであること、kx ^ pの導関数がkpx ^(p-1)などであることを「認識」します。方程式を与えると、パス(ルールアプリケーションのセット)から(方程式)になりたい場所(方程式の最も単純な形式、できれば解決策)を見つけようとします。 。

方程式の例は非常に単純です。シンボリックソリューションは次のようになります。

=> LHS([6, 2]) RHS([16])

# rule: pull all coefficients into LHS
LHS, RHS = [lh-rh for lh,rh in izip_longest(LHS, RHS, 0)], [0]

=> LHS([-10,2]) RHS([0])

# rule: solve first-degree poly
if RHS==[0] and len(LHS)==2:
    LHS, RHS = [0,1], [-LHS[0]/LHS[1]]

=> LHS([0,1]) RHS([5])

そしてあなたの解決策があります:x = 5。

これがアイデアのフレーバーを与えることを願っています。実装の詳細(ルールの優れた完全なセットを見つけ、各ルールをいつ適用するかを決定する)は、多くの人年の労力を簡単に消費する可能性があります。

17
Hugh Bothwell

Pythonは良いかもしれませんが、それは神ではありません...

方程式を解く方法はいくつかあります。分析ソリューションを探しているなら、SymPyはすでに言及されています。

数値的な解決策があるだけなら、Numpyには役立ついくつかのルーチンがあります。多項式の解だけに興味がある場合は、numpy.rootsが機能します。特にあなたが言及した場合:

>>> import numpy
>>> numpy.roots([2,-6])
array([3.0])

より複雑な式については、scipy.fsolveをご覧ください。

いずれにしても、ライブラリを使用してエスケープすることはできません。

9
Pascal Bugnion

正の整数_mx + c = y_に対して極度に制限された方程式のセット_m, c, y_のみを解決したい場合は、次のようにします。

_import re
def solve_linear_equation ( equ ):
    """
    Given an input string of the format "3x+2=6", solves for x.
    The format must be as shown - no whitespace, no decimal numbers,
    no negative numbers.
    """
    match = re.match(r"(\d+)x\+(\d+)=(\d+)", equ)
    m, c, y = match.groups()
    m, c, y = float(m), float(c), float(y) # Convert from strings to numbers
    x = (y-c)/m
    print ("x = %f" % x)
_

いくつかのテスト:

_>>> solve_linear_equation("2x+4=12")
x = 4.000000
>>> solve_linear_equation("123x+456=789")
x = 2.707317
>>> 
_

sin(x) + e^(i*pi*x) = 1のような任意方程式を認識して解決したい場合は、maximaMathematica、MATLABのsolve()またはSymbolic Toolboxなど。初心者としては、これはあなたの考えを超えています。

6
Li-aung Yip

別のツールを使用してください。 Wolfram AlphaMaple[〜#〜] r [〜#〜]Octave 、-のようなもの Matlab またはその他の代数ソフトウェアパッケージ。

初心者として、おそらくこのような重要な問題を解決しようとすべきではありません。

4
user3850