必要なパッケージを import します。
from sympy.abc import *
from sympy import *
# SymPy Plotting Backends (SPB): グラフを描く際に利用
from spb import *
# グラフを SVG で Notebook にインライン表示
%config InlineBackend.figure_formats = ['svg']
偏微分:多変数関数の微分
SymPy での偏微分は(常微分と同様の書き方ですが)以下のように書きます。
$\displaystyle \frac{\partial}{\partial x} f(x, y) = $ diff(f(x, y), x);
$\displaystyle \frac{\partial}{\partial y} f(x, y) = $ diff(f(x, y), y);
f = Function('f')
diff(f(x, y), x)
diff(f(x, y), y)
例題
次の関数 $z$ の偏導関数を求めよ。
(1) $ z = x^3 – 4 x^2 y + x y + 3 y^2$
z = x**3 - 4*x**2*y + x*y + 3*y**2
diff(z, x)
diff(z, y)
(2) $\displaystyle z = \tan^{-1} \frac{y}{x} $
z = atan(y/x)
diff(z, x).simplify()
diff(z, y).simplify()
全微分
2変数関数 $z = f(x, y)$ の全微分 $dz$ とは
$$ dz = df(x,y) = \frac{\partial f}{\partial x} dx + \frac{\partial f}{\partial y} dy$$
例題
次の関数 $z$ の全微分を求めよ。
(1) $ z = \sqrt{x^2 – y^2} $
(2) $ z = x y^2 $
z = sqrt(x**2 - y**2)
var('dx dy')
diff(z, x) * dx + diff(z, y) * dy
上記の答え,
$\displaystyle dz = \frac{x}{\sqrt{x^{2} – y^{2}}} dx – \frac{y}{\sqrt{x^{2} – y^{2}}}dy $ と表示してほしいところ。
z = x*y**2
diff(z, x) * dx + diff(z, y) * dy
上記の答え,
$\displaystyle dz = y^{2}\,dx + 2 x y\, dy $ と表示してほしいところ。
高階偏導関数
SymPy が2階偏導関数に関して
$$ \frac{\partial^2 f}{\partial x \partial y} = \frac{\partial^2 f}{\partial y \partial x} $$
のように,偏微分の順序を変えてもよいことを知っているか確認。
f = Function('f')
Eq((Derivative(Derivative(f(x, y), x), y) -
Derivative(Derivative(f(x, y), y), x)),
(Derivative(Derivative(f(x, y), x), y) -
Derivative(Derivative(f(x, y), y), x)).doit())
テイラー展開(2変数)
1変数関数 $f(x)$ のテイラー展開の復習
$f(x)$ を $x = a$ のまわりで $n = 5$ 次($x^5$)まで展開するときは,SymPy では
series(f(x), x, a, 6)
のように書く。
例として,$f(x) = e^{x}$ を $x = 0$ まわりで $5$ 次まで展開してみる。
f = exp(x)
series(f, x, 0, 6) # 5 次までなら 6 と書く。それが Python 流。
$\sin x$ を $x = 0$ のまわりで $x^3$ まで展開するときは…
series(sin(x), x, 0, 4) # 3 次までなら 4 と書く。
2変数関数 $f(x, y)$ のテイラー展開
本題である2変数関数 $f(x, y)$ のテイラー展開。series()
は1変数関数のテイラー展開のみのようだ。
例として,$\displaystyle f(x, y) = \frac{e^x}{1-x+2 y}$ を $x = 0, y = 0$ のまわりで $2$ 次まで展開してみる。
f = exp(x)/(1-x+2*y)
f
$x \rightarrow \epsilon x, \ y \rightarrow \epsilon y$ とおき…
var('epsilon')
F = f.subs(x, epsilon*x).subs(y, epsilon*y)
F
1.$\epsilon$ について2次までテイラー展開し,$\dots$ series()
2.カッコをはずして展開。$\dots$ expand()
series(F, epsilon, 0, 3).expand()
3.高次の項を示す $O()$ を取り去り,$\dots$ removeO()
(ここで降べきの順に並ぶ。)
_.removeO()
4.最後に $\epsilon \rightarrow 1$ とおきなおす。$\dots$ subs()
_.subs(epsilon, 1)
合成関数の偏微分
例題
\begin{eqnarray}
z &=& f(x, y) = x y \\
x &=& x(u, v) = u\cos v \\
y &=& y(u, v) = u \sin v \\
\therefore\ \ z &=& f\left(x(u, v), y(u, v)\right) = z(u, v)
\end{eqnarray}
について,以下を求める。
$$ 1. \ \frac{\partial z}{\partial u} \quad 2. \ \frac{\partial z}{\partial v} $$
var('x y z u v')
x = u*cos(v)
y = u*sin(v)
z = x * y
$\displaystyle \frac{\partial z}{\partial u} = \cdots$
Eq(Derivative(z, u),
Derivative(z, u).doit())
右辺を簡単化してみます。
Eq(Derivative(z, u).doit(),
Derivative(z, u).doit().simplify())
$\displaystyle \frac{\partial z}{\partial v} = \cdots$
Eq(Derivative(z, v),
Derivative(z, v).doit())
# 右辺を簡単化
Eq(diff(z, v),
diff(z, v).simplify())
陰関数定理
例題
$f(x, y) = x^2 + y^2 -1 = 0$ を満たす陰関数 $y=y(x)$ の微分を求める。
陰関数定理を使わずに解く
陰関数定理より,
$$ \frac{dy}{dx} = – \frac{\frac{\partial f}{\partial x}}{\frac{\partial f}{\partial y}}$$
まずはこれを使わずに SymPy で導いてみます。
まず,$f(x, y) = 0$ より $y$ は $x$ の(陰)関数となるので,$y(x)$。
var('x y f')
y = Function('y')
f = x**2 + y(x)**2 - 1
f
df = diff(f, x)
df
$\displaystyle \frac{df}{dx} = 0$ を $\displaystyle \frac{dy}{dx}$ について解きます。
sol = solve(df, diff(y(x), x))
Eq(diff(y(x), x), sol[0])
陰関数定理を使って…
陰関数定理より,
$$ \frac{dy}{dx} = – \frac{\frac{\partial f}{\partial x}}{\frac{\partial f}{\partial y}}$$
var('x y f')
f = x**2 + y**2 - 1
dydx = - diff(f, x)/diff(f, y)
Eq(Derivative(y, x), dydx)
陽関数として表して微分する
別解として,陽関数として表して解く場合。
$f(x, y) = x^2 + y^2 – 1 = 0$ を $y$ について解く。
var('x y f')
f = x**2 + y**2 - 1
f
sols = solve(f, y)
sols
1つ目の解は以下のように取り出す。
Eq(y, sols[0])
そしてそれを微分すると…
dy0 = diff(sols[0], x)
Eq(Derivative(y, x), dy0)
微分した結果の右辺の分母に $\sqrt{1-x^2} = -y$ を代入して $y$ で書き直すと…
Eq(Derivative(y, x),
dy0.subs(-sols[0], -y))
2つ目の解についても同様に。
Eq(y, sols[1])
dy1 = diff(sols[1], x)
Eq(Derivative(y, x), dy1)
Eq(Derivative(y, x),
dy1.subs(sols[1], y))
以上のことから,1つ目の解 sols[0]
についても2つ目の解 sols[1]
についても,
$$\frac{dy}{dx} = – \frac{x}{y}$$
となることがわかる。これは陰関数定理で求めた解と一致する。
例題
$f(x,y) = x^2 + y^2 -1 = 0$ を満たす陰関数 $y = y(x)$ の極大値と極小値を求めよ。
極値を求めるには $\displaystyle \frac{dy}{dx}$ と極大・極小(上に凸・下に凸)を判断するために $\displaystyle \frac{d^2y}{dx^2}$ が必要。
陰関数の1階微分
すでに,$\displaystyle \frac{dy}{dx} = – \frac{x}{y}$ は求めていて,変数 sol[0]
に格納している。これを dy
として使っていこう。
y = Function('y')
dy = sol[0]
Eq(Derivative(y(x), x), dy)
陰関数の2階微分
dy
すなわち sol[0]
をもう1階 $x$ で微分して $\displaystyle \frac{d^2y}{dx^2}$ を求める。
ddy = diff(dy, x)
Eq(Derivative(y(x), x, 2), ddy)
上式の右辺に dy
つまり $\displaystyle \frac{dy(x)}{dx} = – \frac{x}{y(x)}$ を代入してやると…
ddy = ddy.subs(Derivative(y(x), x), dy)
Eq(Derivative(y(x), x, 2), ddy)
極値となりそうな $x$ の値は
$\displaystyle \frac{dy}{dx} = – \frac{x}{y} = 0$ より $x = 0$.
そのときの $y$ の値は連立方程式 $x = 0, \ f(x, y)=0$ を解いて…
ans2 = solve([x, x**2 + y(x)**2 - 1], [x, y(x)])
ans2
ans2[0]
つまり $(x, y) = (0, -1)$ のとき,$\displaystyle \frac{d^2y}{dx^2}$ つまり ddy
の右辺の値を評価すると…
Eq(Derivative(y(x), x, 2),
ddy.subs(x, ans2[0][0]).subs(y(0), ans2[0][1]))
… となり,$\displaystyle \frac{d^2y}{dx^2} = 1 > 0$ だからここでは下に凸,つまり極小値(最小値)。
同様に ans2[1]
つまり $(x, y) = (0, 1)$ の場合は…
Eq(Derivative(y(x), x, 2),
ddy.subs(x, ans2[1][0]).subs(y(0), ans2[1][1]))
… となり,$\displaystyle \frac{d^2y}{dx^2} = -1 < 0$ だからここでは上に凸,つまり極大値(最大値)。
参考:陰関数のグラフ
SymPy Plotting Backends では $f(x, y) = 0$ という陰関数表示のままでグラフを描くことができる。
var('x y f')
f = x**2 + y**2 - 1
p1 = plot_implicit(f, "$f(x,y)=0$",
(x, -1.2, 1.2), (y, -1.2, 1.5),
legend = True,
size=(6,6),
aspect = "equal");
$y(x)$ の最大値,最小値の点もあわせてグラフに。(以前のバージョンでは plot_implicit()
以外の凡例が表示されないという不具合があったが,v2.1.0 で修正された。)
p2 = plot_list([0],[1], "y(x) の最大値",
is_point = True, legend = True,
xlim=(-1.2, 1.2), ylim=(-1.2, 1.5),
size=(6,6),
aspect = "equal", show = False)
p3 = plot_list([0],[-1], "y(x) の最小値",
is_point = True, legend = True,
xlim=(-1.2, 1.2), ylim=(-1.2, 1.5),
size=(6,6),
aspect = "equal", show = False)
p = p1+p2+p3
p.show();