a=3
b=2
print(a+b)
5
代数演算に変数名のまま使うには,Symbolあるいはsymbolsでpythonに教えてやる必要があります.
from sympy import *
a,b,c,x = symbols('a,b,c,x')
eq1 = a*x**2 + b*x + c
pprint(eq1)
2 a⋅x + b⋅x + c
値の代入はsubsで定義辞書を渡すことになります.
pprint(eq1.subs({x:3}))
9⋅a + 3⋅b + c
pprint(eq1.subs({a:2}))
2 b⋅x + c + 2⋅x
まちがって代入すると,それ以降のsubsが効かなくなるので,注意してください.
a=3
pprint(eq1)
pprint(eq1.subs({a:2}))
2 a⋅x + b⋅x + c 2 a⋅x + b⋅x + c
その場合は,symbolsなどで元に戻す必要があります.
a = symbols('a')
pprint(eq1.subs({a:2}))
2 b⋅x + c + 2⋅x
eq1 = 3*x - 2
pprint(eq1)
3⋅x - 2
solve(eq1)
[2/3]
2次方程式も同じようして解けます.
eq1 = a*x**2 + b*x + c
pprint(eq1)
2 a⋅x + b⋅x + c
solve(eq1)
[{a: -(b*x + c)/x**2}]
おやおや,おかしいですね.とくべき未知数(x)を指定するのを忘れています.
solve(eq1,x)
[(-b + sqrt(-4*a*c + b**2))/(2*a), -(b + sqrt(-4*a*c + b**2))/(2*a)]
出力としてpythonの辞書形式で戻す場合には,dict=Trueが必要になります.
solve(eq1,x, dict=True)
[{x: (-b + sqrt(-4*a*c + b**2))/(2*a)}, {x: -(b + sqrt(-4*a*c + b**2))/(2*a)}]
連立方程式も同じようにして解けます.
y = symbols('y')
solve({x+y-1,x-y-2},{x,y})
{x: 3/2, y: -1/2}
解析的に解けないときは,数値解を求める必要があります.これはpythonによる数値計算で詳述します.簡単なコマンドはなさそうです.
solve(log(x)-exp(-x),x)
--------------------------------------------------------------------------- NotImplementedError Traceback (most recent call last) <ipython-input-29-1d879874dca5> in <module> ----> 1 solve(log(x)-exp(-x),x) ~/opt/anaconda3/lib/python3.8/site-packages/sympy/solvers/solvers.py in solve(f, *symbols, **flags) 1092 ########################################################################### 1093 if bare_f: -> 1094 solution = _solve(f[0], *symbols, **flags) 1095 else: 1096 solution = _solve_system(f, symbols, **flags) ~/opt/anaconda3/lib/python3.8/site-packages/sympy/solvers/solvers.py in _solve(f, *symbols, **flags) 1692 1693 if result is False: -> 1694 raise NotImplementedError('\n'.join([msg, not_impl_msg % f])) 1695 1696 if flags.get('simplify', True): NotImplementedError: multiple generators [exp(x), log(x)] No algorithms are implemented to solve equation log(x) - exp(-x)
両辺ともに長い式の時には,右辺(rhs),左辺(lhs)なんかを使ってまとめたりします.
rhs = sin(x)**2 + 3*cos(x)
lhs = 2*cos(x)**2 + cos(2*x)
eq1 = rhs -lhs
pprint(eq1)
solve(eq1,x)
2 2 sin (x) - 2⋅cos (x) + 3⋅cos(x) - cos(2⋅x)
[0, I*(log(5) - log(-2 - sqrt(21)*I)), I*(log(5) - log(-2 + sqrt(21)*I))]
式の変形にも等号が使われます.例えば, $$ (x-2)^2 = x^2 -4x +4 $$ なんかです.これは左辺と右辺がどんな$x$に対しても 成り立っていること,恒等式であることを表現しています.
このような式の変形においても,問題としては
$(x-2)^2$を展開(expand)せよ
となります.ですので,
from sympy import *
x = Symbol('x')
eq1 = (x-2)**2
pprint(eq1)
pprint(eq1.expand())
2 (x - 2) 2 x - 4⋅x + 4
となります.因数分解,微積分なども同様にそれぞれのコマンドが用意されています.これは別の章で詳しく解説します.
3点(1,2),(-3,4),(-1,1)を通る2次方程式を求めよ.
from sympy import *
a,b,c,x = symbols('a,b,c,x')
f = a*x**2 + b*x + c
eq1 = f.subs({x:1})-2
eq2 = f.subs({x:-3})-4
eq3 = f.subs({x:-1})-1
s1 = solve({eq1,eq2,eq3},{a,b,c})
print(s1)
{a: 1/2, b: 1/2, c: 1}
f1 = f.subs(s1)
print(f1)
x**2/2 + x/2 + 1
from sympy.plotting import plot
plot(f1)
<sympy.plotting.plot.Plot at 0x7fee6af138b0>
得られた関数と与えられた点を同時にplotするのに苦労した. func内で上で得られたf1を使いたかったが,だめ. symbolと値の取り扱いが混ざってしまうのかな.
とりあえず,関数をベタ打ちすると以下のとおり表示OK.
#from sympy.plotting import plot
import matplotlib.pyplot as plt
import numpy as np
def func(x):
return x**2/2 + x/2 + 1
xx = np.linspace(-3,2, 100)
plt.plot(xx, func(xx))
px=[1,-3,-1]
py=[2,4,1]
plt.plot(px,py,'o', color='r')
plt.show()